diff --git a/README.md b/README.md index 0fc9f5f..696f8b6 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,6 @@ $ ftp_login host=10.0.0.1 user=FILE0 0=logins.txt password=asdf -x ignore:mesg=' 19:36:08 patator INFO - 530 18 1.000 | root | 1 | Permission denied. 19:36:17 patator INFO - 530 18 1.000 | michael | 50 | Permission denied. 19:36:36 patator INFO - 530 18 1.000 | robert | 93 | Permission denied. -19:36:38 patator INFO - Hits/Done/Skip/Fail/Size: 5/100/0/0/100, Avg: 3 r/s, Time: 0h 0m 31s ... ``` @@ -98,6 +97,41 @@ $ grep AllowNoPassword /tmp/qsdf/72_200\:13215\:0\:0.351.txt Tested against phpMyAdmin 4.2.7.1. +* IKE : Enumerate transforms supported by VPN peer + +``` +# ike_enum host=10.0.0.1 transform=MOD0 0=TRANS aggressive=RANGE1 1=int:0-1 -x ignore:fgrep='NO-PROPOSAL' +16:52:58 patator INFO - Starting Patator v0.7-beta (https://github.com/lanjelot/patator) at 2015-04-05 16:52 AEST +16:52:58 patator INFO - +16:52:58 patator INFO - code size time | candidate | num | mesg +16:52:58 patator INFO - ----------------------------------------------------------------------------- +16:53:03 patator INFO - 0 70 0.034 | 5,1,1,2:0 | 1539 | Handshake returned: Enc=3DES Hash=MD5 Group=2:modp1024 Auth=PSK (Main) +16:53:03 patator INFO - 0 72 0.031 | 5,1,65001,2:0 | 1579 | Handshake returned: Enc=3DES Hash=MD5 Group=2:modp1024 Auth=XAUTH (Main) +16:53:03 patator INFO - 0 76 0.033 | 5,1,1,2:1 | 1540 | Handshake returned: Enc=3DES Hash=MD5 Group=2:modp1024 Auth=PSK (Aggressive) +16:53:03 patator INFO - 0 78 0.034 | 5,1,65001,2:1 | 1580 | Handshake returned: Enc=3DES Hash=MD5 Group=2:modp1024 Auth=XAUTH (Aggressive) +16:53:06 patator INFO - 0 84 0.034 | 7/128,2,1,2:0 | 2371 | Handshake returned: Enc=AES KeyLength=128 Hash=SHA1 Group=2:modp1024 Auth=PSK (Main) +16:53:06 patator INFO - 0 90 0.033 | 7/128,2,1,2:1 | 2372 | Handshake returned: Enc=AES KeyLength=128 Hash=SHA1 Group=2:modp1024 Auth=PSK (Aggressive) +16:53:06 patator INFO - 0 86 0.034 | 7/128,2,65001,2:0 | 2411 | Handshake returned: Enc=AES KeyLength=128 Hash=SHA1 Group=2:modp1024 Auth=XAUTH (Main) +16:53:06 patator INFO - 0 92 0.035 | 7/128,2,65001,2:1 | 2412 | Handshake returned: Enc=AES KeyLength=128 Hash=SHA1 Group=2:modp1024 Auth=XAUTH (Aggressive) + ++ 10.0.0.1:500 (Main Mode) + Encryption Hash Auth Group + ---------- ---------- ---------- ---------- + 3DES MD5 PSK modp1024 + 3DES MD5 XAUTH modp1024 + AES128 SHA1 PSK modp1024 + AES128 SHA1 XAUTH modp1024 + ++ 10.0.0.1:500 (Aggressive Mode) + Encryption Hash Auth Group + ---------- ---------- ---------- ---------- + 3DES MD5 PSK modp1024 + 3DES MD5 XAUTH modp1024 + AES128 SHA1 PSK modp1024 + AES128 SHA1 XAUTH modp1024 +16:53:11 patator INFO - Hits/Done/Skip/Fail/Size: 8/3840/0/0/3840, Avg: 284 r/s, Time: 0h 0m 13s +``` + * SNMPv3 : Find valid usernames ``` diff --git a/patator.py b/patator.py index c920152..34cfa10 100755 --- a/patator.py +++ b/patator.py @@ -57,6 +57,7 @@ Currently it supports the following modules: + dns_forward : Forward DNS lookup + dns_reverse : Reverse DNS lookup + snmp_login : Brute-force SNMP v1/2/3 + + ike_enum : Enumerate IKE transforms + unzip_pass : Brute-force the password of encrypted ZIP files + keystore_pass : Brute-force the password of Java keystore files @@ -631,7 +632,7 @@ logging.setLoggerClass(CrossProcessLogger) logging._levelNames[logging.ERROR] = 'FAIL' logger = logging.getLogger('patator') -from multiprocessing.managers import SyncManager, current_process +from multiprocessing.managers import SyncManager import signal manager = SyncManager() @@ -787,7 +788,7 @@ import socket import subprocess import hashlib from collections import defaultdict -from multiprocessing import Process, active_children, Queue +from multiprocessing import Process, active_children, current_process, Queue try: # python3+ from queue import Empty, Full @@ -3932,6 +3933,131 @@ class SNMP_login: # }}} +# IKE {{{ +if not which('ike-scan'): + warnings.append('ike-scan') + +# http://www.iana.org/assignments/ipsec-registry/ipsec-registry.xhtml +IKE_ENC = [('1', 'DES'), ('2', 'IDEA'), ('3', 'BLOWFISH'), ('4', 'RC5'), ('5', '3DES'), ('6', 'CAST'), ('7/128', 'AES128'), ('7/192', 'AES192'), ('7/256', 'AES256'), ('8', 'Camellia')] +IKE_HASH = [('1', 'MD5'), ('2', 'SHA1'), ('3', 'Tiger'), ('4', 'SHA2-256'), ('5', 'SHA2-384'), ('6', 'SHA2-512')] +IKE_AUTH = [('1', 'PSK'), ('2', 'DSS Sig'), ('3', 'RSA Sig'), ('4', 'RSA Enc'), ('5', 'Revised RSA Enc'), + #('6', 'EIGAMEL Enc'), ('7', 'Revised EIGAMEL Enc'), ('8', 'ECDSA Sig'), # Reserved + #('9', 'ECDSA SHA-256'), ('10', 'ECDSA SHA-384'), ('11', 'ECDSA SHA-512'), # RFC4754 + ('65001', 'XAUTH'), ('64221', 'Hybrid'), ('64222', 'Hybrid 64222')] #, ('64223', 'Hybrid 64223'), ... ('65002', 'Hybrid 65002') ... +IKE_GROUP = [('1', 'modp768'), ('2', 'modp1024'), ('5', 'modp1536'), + #('3', 'ecc3'), ('4', 'ecc4'), # any implementations? + # '6', '7', '8', '9', '10', '11', '12', '13', # only in draft, not RFC + ('14', 'modp2048')] #, ('15', 'modp3072'), ('16', 'modp4096'), ('17', 'modp6144'), ('18', 'modp8192')] # RFC3526 + # '19', '20', '21', '22', '23', '24', '25', '26', # RFC5903 + # '27', '28', '29', '30', # RFC6932 + +def generate_transforms(): + lists = map(lambda l: [i[0] for i in l], [IKE_ENC, IKE_HASH, IKE_AUTH, IKE_GROUP]) + return map(lambda p: ','.join(p), product(*[chain(l) for l in lists])), reduce(lambda x,y: x*y, map(len, lists)) + +class Controller_IKE(Controller): + + results = defaultdict(list) + + def show_final(self): + ''' Expected output: ++ 10.0.0.1:500 (Main Mode) + Encryption Hash Auth Group + ---------- ---------- ---------- ---------- + 3DES MD5 PSK modp1024 + 3DES MD5 XAUTH modp1024 + AES128 SHA1 PSK modp1024 + AES128 SHA1 XAUTH modp1024 + ++ 10.0.0.1:500 (Aggressive Mode) + Encryption Hash Auth Group + ---------- ---------- ---------- ---------- + 3DES MD5 PSK modp1024 + 3DES MD5 XAUTH modp1024 + AES128 SHA1 PSK modp1024 + AES128 SHA1 XAUTH modp1024 + ''' + + ike_enc = dict(IKE_ENC) + ike_hsh = dict(IKE_HASH) + ike_ath = dict(IKE_AUTH) + ike_grp = dict(IKE_GROUP) + + for endpoint, transforms in self.results.iteritems(): + print('\n+ %s' % endpoint) + print(' %10s %10s %12s %10s' % ('Encryption', 'Hash', 'Auth', 'Group')) + print(' %10s %10s %12s %10s' % ('-'*10, '-'*10, '-'*10, '-'*10)) + for transform in transforms: + e, h, a, g = transform.split(',') + enc = ike_enc[e] + hsh = ike_hsh[h] + ath = ike_ath[a] + grp = ike_grp[g] + print(' %10s %10s %12s %10s' % (enc, hsh, ath, grp)) + + def push_final(self, resp): + if hasattr(resp, 'rrs'): + endpoint, transform = resp.rrs + self.results[endpoint].append(transform) + +class IKE_enum: + '''Enumerate IKE transforms''' + + usage_hints = [ + """%prog host=10.0.0.1 transform=MOD0 0=TRANS -x ignore:fgrep=NO-PROPOSAL""", + """%prog host=10.0.0.1 transform=MOD0 0=TRANS -x ignore:fgrep=NO-PROPOSAL aggressive=RANGE1 1=int:0-1""", + ] + + available_options = ( + ('host', 'target host'), + ('host', 'target port [500]'), + ('transform', 'transform to test [5,1,1,2]'), + ('aggressive', 'use aggressive mode [0|1]'), + ('groupname', 'identification value for aggressive mode [foo]'), + ) + available_actions = () + + available_keys = { + 'TRANS': generate_transforms, + } + + Response = Response_Base + + def __init__(self): + uid = current_process().name[9:] + self.sport = '51%s' % uid + + def execute(self, host, port='500', transform='5,1,1,2', aggressive='0', groupname='foo'): + + cmd = ['ike-scan', '-M', '--sport', self.sport, host, '--dport', port, '--trans', transform] + if aggressive == '1': + cmd.append('-A') + if groupname: + cmd.extend(['--id', groupname]) + + with Timing() as timing: + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + code = p.returncode + + trace = '%s\n[out]\n%s\n[err]\n%s' % (cmd, out, err) + logger.debug('trace: %s' % repr(trace)) + + has_sa = 'SA=(' in out + if has_sa: + mesg = 'Handshake returned: %s (%s)' % (re.search('SA=\((.+) LifeType', out).group(1), re.search('\t(.+) Mode Handshake returned', out).group(1)) + else: + mesg = out.strip().split('\n')[1].split('\t')[-1] + + resp = self.Response(code, mesg, timing, trace) + if has_sa: + endpoint = '%s:%s (%s Mode)' % (host, port, 'Aggressive' if aggressive == '1' else 'Main') + resp.rrs = endpoint, transform + + return resp + +# }}} + # Unzip {{{ if not which('unzip'): warnings.append('unzip') @@ -3955,15 +4081,14 @@ class Unzip_pass: def execute(self, zipfile, password): zipfile = os.path.abspath(zipfile) cmd = ['unzip', '-t', '-q', '-P', password, zipfile] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out = p.stdout.read() - err = p.stderr.read() with Timing() as timing: - code = p.wait() + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + code = p.returncode mesg = repr(out.strip())[1:-1] - trace = '[out]\n%s\n[err]\n%s' % (out, err) + trace = '%s\n[out]\n%s\n[err]\n%s' % (cmd, out, err) return self.Response(code, mesg, timing, trace) @@ -3993,15 +4118,14 @@ class Keystore_pass: def execute(self, keystore, password, storetype='jks'): keystore = os.path.abspath(keystore) cmd = ['keytool', '-list', '-keystore', keystore, '-storepass', password, '-storetype', storetype] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out = p.stdout.read() - err = p.stderr.read() with Timing() as timing: - code = p.wait() + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + code = p.returncode mesg = repr(out.strip())[1:-1] - trace = '[out]\n%s\n[err]\n%s' % (out, err) + trace = '%s\n[out]\n%s\n[err]\n%s' % (cmd, out, err) return self.Response(code, mesg, timing, trace) @@ -4128,6 +4252,7 @@ modules = [ ('dns_forward', (Controller_DNS, DNS_forward)), ('dns_reverse', (Controller_DNS, DNS_reverse)), ('snmp_login', (Controller, SNMP_login)), + ('ike_enum', (Controller_IKE, IKE_enum)), ('unzip_pass', (Controller, Unzip_pass)), ('keystore_pass', (Controller, Keystore_pass)), @@ -4149,6 +4274,7 @@ dependencies = { 'dnspython': [('dns_reverse', 'dns_forward'), 'http://www.dnspython.org/', '1.10.0'], 'IPy': [('dns_reverse', 'dns_forward'), 'https://github.com/haypo/python-ipy', '0.75'], 'pysnmp': [('snmp_login',), 'http://pysnmp.sf.net/', '4.2.1'], + 'ike-scan': [('ike_enum',), 'http://www.nta-monitor.com/tools-resources/security-tools/ike-scan', '1.9'], 'unzip': [('unzip_pass',), 'http://www.info-zip.org/', '6.0'], 'java': [('keystore_pass',), 'http://www.oracle.com/technetwork/java/javase/', '6'], 'python': [('ftp_login',), 'http://www.python.org/', '2.7'],