Add docker-compose and fix bugs

pull/154/head
lanjelot 4 years ago
parent 902c650e04
commit da3d9751d7

@ -9,30 +9,44 @@ RUN apt-get update && apt-get install -y \
libcurl4-openssl-dev python3-dev libssl-dev \ libcurl4-openssl-dev python3-dev libssl-dev \
ldap-utils \ ldap-utils \
libmariadbclient-dev \ libmariadbclient-dev \
libpq-dev \
ike-scan unzip default-jdk \ ike-scan unzip default-jdk \
libsqlite3-dev libsqlcipher-dev \ libsqlite3-dev libsqlcipher-dev \
libpq-dev \ python3-pip python-pip
python3-pip
# cx_oracle # cx_oracle
RUN apt-get update && apt-get install -y libaio1 wget unzip RUN apt-get update && apt-get install -y libaio1 wget unzip git
WORKDIR /opt/oracle WORKDIR /opt/oracle
RUN wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip RUN wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip \
RUN unzip instantclient-basiclite-linuxx64.zip && wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip \
RUN rm -f instantclient-basiclite-linuxx64.zip && unzip instantclient-basiclite-linuxx64.zip \
RUN cd /opt/oracle/instantclient* && rm -f instantclient-basiclite-linuxx64.zip \
RUN rm -f *jdbc* *occi* *mysql* *README *jar uidrvci genezi adrci && unzip instantclient-sdk-linuxx64.zip \
RUN echo /opt/oracle/instantclient* > /etc/ld.so.conf.d/oracle-instantclient.conf && rm -f instantclient-sdk-linuxx64.zip \
RUN ldconfig && cd /opt/oracle/instantclient* \
&& rm -f *jdbc* *occi* *mysql* *README *jar uidrvci genezi adrci \
&& echo /opt/oracle/instantclient* > /etc/ld.so.conf.d/oracle-instantclient.conf \
&& ldconfig
RUN git clone --branch 5.3 https://github.com/oracle/python-cx_Oracle \
&& cd python-cx_Oracle && export ORACLE_HOME=/opt/oracle/instantclient_19_6 && python2 setup.py build && python2 setup.py install
# xfreerdp (see https://github.com/FreeRDP/FreeRDP/wiki/Compilation) # xfreerdp (see https://github.com/FreeRDP/FreeRDP/wiki/Compilation)
RUN apt-get update && apt-get install -y ninja-build build-essential git-core debhelper cdbs dpkg-dev autotools-dev cmake pkg-config xmlto libssl-dev docbook-xsl xsltproc libxkbfile-dev libx11-dev libwayland-dev libxrandr-dev libxi-dev libxrender-dev libxext-dev libxinerama-dev libxfixes-dev libxcursor-dev libxv-dev libxdamage-dev libxtst-dev libcups2-dev libpcsclite-dev libasound2-dev libpulse-dev libjpeg-dev libgsm1-dev libusb-1.0-0-dev libudev-dev libdbus-glib-1-dev uuid-dev libxml2-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libfaad-dev libfaac-dev \ RUN apt-get update && apt-get install -y ninja-build build-essential git-core debhelper cdbs dpkg-dev autotools-dev cmake pkg-config xmlto libssl-dev docbook-xsl xsltproc libxkbfile-dev libx11-dev libwayland-dev libxrandr-dev libxi-dev libxrender-dev libxext-dev libxinerama-dev libxfixes-dev libxcursor-dev libxv-dev libxdamage-dev libxtst-dev libcups2-dev libpcsclite-dev libasound2-dev libpulse-dev libjpeg-dev libgsm1-dev libusb-1.0-0-dev libudev-dev libdbus-glib-1-dev uuid-dev libxml2-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libfaad-dev libfaac-dev \
&& apt-get install -y libavutil-dev libavcodec-dev libavresample-dev && apt-get install -y libavutil-dev libavcodec-dev libavresample-dev
RUN git clone https://github.com/FreeRDP/FreeRDP/ /tmp/FreeRDP WORKDIR /opt/FreeRDP
WORKDIR /tmp/FreeRDP RUN git clone https://github.com/FreeRDP/FreeRDP/ .
RUN cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_SSE2=ON . && cmake --build . && cmake --build . --target install RUN cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_SSE2=ON . && cmake --build . && cmake --build . --target install
WORKDIR /opt/patator WORKDIR /opt/patator
RUN python3 -m pip install patator COPY ./requirements.txt ./
RUN python3 -m pip install -r requirements.txt
RUN sed -e '/cx_Oracle/d' -e 's,pysqlcipher3,pysqlcipher,' requirements.txt | python2 -m pip install -r /dev/stdin
# utils
RUN apt-get update && apt-get install -y ipython3 ipython iputils-ping iproute2 netcat curl rsh-client telnet vim mlocate nmap
RUN echo 'set bg=dark' > /root/.vimrc
ENTRYPOINT ["patator.py"] COPY ./patator.py ./
ENTRYPOINT ["python3", "./patator.py"]

@ -0,0 +1,55 @@
version: "3"
services:
unix:
build: testing/unix
image: patator-unix-testing
# ports:
# - "21:21"
# - "22:22"
# - "23:23"
# - "25:25"
# - "79:79"
# - "80:80"
# - "106:106"
# - "110:110"
# - "139:139"
# - "143:143"
# - "389:389"
# - "445:445"
# - "513:513"
# - "636:636"
# - "993:993"
# - "995:995"
# - "3306:3306"
# - "4444:4444"
# - "5432:5432"
# - "5900:5900"
# - "8009:8009"
# - "8080:8080"
volumes:
- .:/opt/patator
oracle:
image: oracleinanutshell/oracle-xe-11g
environment:
- ORACLE_ENABLE_XDB=true
ports:
- "1521:1521"
mssql:
image: mcr.microsoft.com/mssql/server:2019-latest
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=Password1
ports:
- "1433:1433"
patator:
build: .
image: patator
depends_on:
- unix
- oracle
- mssql
volumes:
- .:/opt/patator

@ -714,15 +714,12 @@ class TXTFormatter(logging.Formatter):
def __init__(self, indicatorsfmt): def __init__(self, indicatorsfmt):
self.resultfmt = '%(asctime)s %(name)-7s %(levelname)7s - ' + ' '.join('%%(%s)%ss' % (k, v) for k, v in indicatorsfmt) + ' | %(candidate)-34s | %(num)5s | %(mesg)s' self.resultfmt = '%(asctime)s %(name)-7s %(levelname)7s - ' + ' '.join('%%(%s)%ss' % (k, v) for k, v in indicatorsfmt) + ' | %(candidate)-34s | %(num)5s | %(mesg)s'
logging.Formatter.__init__(self, datefmt='%H:%M:%S') super(TXTFormatter, self).__init__(datefmt='%H:%M:%S')
def format(self, record): def format(self, record):
if not record.msg or record.msg == 'headers': if not record.msg or record.msg == 'headers':
fmt = self.resultfmt fmt = self.resultfmt
if not all(True if 0x20 <= ord(c) < 0x7f else False for c in record.candidate):
record.candidate = repr(record.candidate)
else: else:
if record.levelno == logging.DEBUG: if record.levelno == logging.DEBUG:
fmt = '%(asctime)s %(name)-7s %(levelname)7s [%(pname)s] %(message)s' fmt = '%(asctime)s %(name)-7s %(levelname)7s [%(pname)s] %(message)s'
@ -734,18 +731,30 @@ class TXTFormatter(logging.Formatter):
else: else:
self._fmt = fmt self._fmt = fmt
return logging.Formatter.format(self, record) pp = {}
for k, v in record.__dict__.items():
if k in ['candidate', 'mesg']:
pp[k] = repr23(v)
else:
pp[k] = v
return super(TXTFormatter, self).format(logging.makeLogRecord(pp))
class CSVFormatter(logging.Formatter): class CSVFormatter(logging.Formatter):
def __init__(self, indicatorsfmt): def __init__(self, indicatorsfmt):
fmt = '%(asctime)s,%(levelname)s,'+','.join('%%(%s)s' % name for name, _ in indicatorsfmt)+',%(candidate)s,%(num)s,%(mesg)s' fmt = '%(asctime)s,%(levelname)s,'+','.join('%%(%s)s' % name for name, _ in indicatorsfmt)+',%(candidate)s,%(num)s,%(mesg)s'
logging.Formatter.__init__(self, fmt, datefmt='%H:%M:%S') super(CSVFormatter, self).__init__(fmt=fmt, datefmt='%H:%M:%S')
def format(self, record): def format(self, record):
for k in ['candidate', 'mesg']: pp = {}
record.__dict__[k] = '"%s"' % record.__dict__[k].replace('"', '""') for k, v in record.__dict__.items():
return logging.Formatter.format(self, record) if k in ['candidate', 'mesg']:
pp[k] = '"%s"' % v.replace('"', '""')
else:
pp[k] = v
return super(CSVFormatter, self).format(logging.makeLogRecord(pp))
class XMLFormatter(logging.Formatter): class XMLFormatter(logging.Formatter):
def __init__(self, indicatorsfmt): def __init__(self, indicatorsfmt):
@ -757,15 +766,17 @@ class XMLFormatter(logging.Formatter):
<target %(target)s/> <target %(target)s/>
</result>''' </result>'''
logging.Formatter.__init__(self, fmt, datefmt='%H:%M:%S') super(XMLFormatter, self).__init__(fmt=fmt, datefmt='%H:%M:%S')
def format(self, record): def format(self, record):
pp = {}
for k, v in record.__dict__.items(): for k, v in record.__dict__.items():
if isinstance(v, str): if isinstance(v, str):
record.__dict__[k] = xmlescape(v) pp[k] = xmlescape(v)
else:
pp[k] = v
return super(XMLFormatter, self).format(record) return super(XMLFormatter, self).format(logging.makeLogRecord(pp))
class MsgFilter(logging.Filter): class MsgFilter(logging.Filter):
@ -779,12 +790,12 @@ def process_logs(queue, indicatorsfmt, argv, log_dir, runtime_file, csv_file, xm
ignore_ctrlc() ignore_ctrlc()
try: if PY3:
# python3
logging._levelToName[logging.ERROR] = 'FAIL' logging._levelToName[logging.ERROR] = 'FAIL'
except: encoding = 'latin1'
# python2 else:
logging._levelNames[logging.ERROR] = 'FAIL' logging._levelNames[logging.ERROR] = 'FAIL'
encoding = None
handler_out = logging.StreamHandler() handler_out = logging.StreamHandler()
handler_out.setFormatter(TXTFormatter(indicatorsfmt)) handler_out.setFormatter(TXTFormatter(indicatorsfmt))
@ -801,7 +812,7 @@ def process_logs(queue, indicatorsfmt, argv, log_dir, runtime_file, csv_file, xm
with open(runtime_log, 'a') as f: with open(runtime_log, 'a') as f:
f.write('$ %s\n' % ' '.join(argv)) f.write('$ %s\n' % ' '.join(argv))
handler_log = logging.FileHandler(runtime_log) handler_log = logging.FileHandler(runtime_log, encoding=encoding)
handler_log.setFormatter(TXTFormatter(indicatorsfmt)) handler_log.setFormatter(TXTFormatter(indicatorsfmt))
logger.addHandler(handler_log) logger.addHandler(handler_log)
@ -813,7 +824,7 @@ def process_logs(queue, indicatorsfmt, argv, log_dir, runtime_file, csv_file, xm
with open(results_csv, 'w') as f: with open(results_csv, 'w') as f:
f.write('time,level,%s\n' % ','.join(names)) f.write('time,level,%s\n' % ','.join(names))
handler_csv = logging.FileHandler(results_csv) handler_csv = logging.FileHandler(results_csv, encoding=encoding)
handler_csv.addFilter(MsgFilter()) handler_csv.addFilter(MsgFilter())
handler_csv.setFormatter(CSVFormatter(indicatorsfmt)) handler_csv.setFormatter(CSVFormatter(indicatorsfmt))
@ -835,7 +846,7 @@ def process_logs(queue, indicatorsfmt, argv, log_dir, runtime_file, csv_file, xm
while i < len(argv): while i < len(argv):
arg = argv[i] arg = argv[i]
if arg[0] == '-': if arg[0] == '-':
if arg in ('-d', '--debug', '--allow-ignore-failures'): if arg in ('-d', '--debug', '--allow-ignore-failures', '-y'):
f.write(' <option type="global" name=%s/>\n' % xmlquoteattr(arg)) f.write(' <option type="global" name=%s/>\n' % xmlquoteattr(arg))
else: else:
if not arg.startswith('--') and len(arg) > 2: if not arg.startswith('--') and len(arg) > 2:
@ -860,7 +871,7 @@ def process_logs(queue, indicatorsfmt, argv, log_dir, runtime_file, csv_file, xm
f.seek(offset) f.seek(offset)
f.truncate(f.tell()) f.truncate(f.tell())
handler_xml = logging.FileHandler(results_xml) handler_xml = logging.FileHandler(results_xml, encoding=encoding)
handler_xml.addFilter(MsgFilter()) handler_xml.addFilter(MsgFilter())
handler_xml.setFormatter(XMLFormatter(indicatorsfmt)) handler_xml.setFormatter(XMLFormatter(indicatorsfmt))
@ -904,13 +915,13 @@ def process_logs(queue, indicatorsfmt, argv, log_dir, runtime_file, csv_file, xm
if log_dir: if log_dir:
filename = '%d_%s' % (num, '-'.join(map(str, resp.indicators()))) filename = '%d_%s' % (num, '-'.join(map(str, resp.indicators())))
with open('%s.txt' % os.path.join(log_dir, filename), 'w') as f: with open('%s.txt' % os.path.join(log_dir, filename), 'wb') as f:
f.write(resp.dump()) f.write(resp.dump())
elif action == 'save_hit': elif action == 'save_hit':
if hits_file: if hits_file:
with open(hits_file, 'a') as f: with open(hits_file, 'ab') as f:
f.write('%s\n' % ':'.join(args)) f.write(b(args[0] +'\n'))
elif action == 'setLevel': elif action == 'setLevel':
logger.setLevel(args[0]) logger.setLevel(args[0])
@ -946,28 +957,33 @@ import glob
from xml.sax.saxutils import escape as xmlescape, quoteattr as xmlquoteattr from xml.sax.saxutils import escape as xmlescape, quoteattr as xmlquoteattr
from ssl import wrap_socket from ssl import wrap_socket
from binascii import hexlify, unhexlify from binascii import hexlify, unhexlify
import mmap
try: PY3 = sys.version_info >= (3,)
# python3+
if PY3:
from queue import Empty, Full from queue import Empty, Full
from urllib.parse import quote, urlencode, urlparse, urlunparse, parse_qsl, quote_plus from urllib.parse import quote, urlencode, urlparse, urlunparse, parse_qsl, quote_plus
from io import StringIO from io import StringIO
from sys import maxsize as maxint from sys import maxsize as maxint
except ImportError: else:
# python2.6+
from Queue import Empty, Full from Queue import Empty, Full
from urllib import quote, urlencode, quote_plus from urllib import quote, urlencode, quote_plus
from urlparse import urlparse, urlunparse, parse_qsl from urlparse import urlparse, urlunparse, parse_qsl
from cStringIO import StringIO from cStringIO import StringIO
from sys import maxint from sys import maxint
PY3 = sys.version_info >= (3,)
if PY3: # http://python3porting.com/problems.html if PY3: # http://python3porting.com/problems.html
def b(x): def b(x):
return x.encode('ISO-8859-1', errors='ignore') if isinstance(x, bytes):
return x
else:
return x.encode('ISO-8859-1', errors='ignore')
def B(x): def B(x):
return x.decode('ISO-8859-1', errors='ignore') if isinstance(x, str):
return x
else:
return x.decode('ISO-8859-1', errors='ignore')
else: else:
def b(x): def b(x):
return x return x
@ -1054,20 +1070,20 @@ def which(program):
return None return None
def build_logdir(opt_dir, opt_auto): def build_logdir(opt_dir, opt_auto, assume_yes):
if opt_auto: if opt_auto:
return create_time_dir(opt_dir or '/tmp/patator', opt_auto) return create_time_dir(opt_dir or '/tmp/patator', opt_auto)
elif opt_dir: elif opt_dir:
return create_dir(opt_dir) return create_dir(opt_dir, assume_yes)
else: else:
return None return None
def create_dir(top_path): def create_dir(top_path, assume_yes):
top_path = os.path.abspath(top_path) top_path = os.path.abspath(top_path)
if os.path.isdir(top_path): if os.path.isdir(top_path):
files = os.listdir(top_path) files = os.listdir(top_path)
if files: if files:
if input("Directory '%s' is not empty, do you want to wipe it ? [Y/n]: " % top_path) != 'n': if assume_yes or input("Directory '%s' is not empty, do you want to wipe it ? [Y/n]: " % top_path) != 'n':
for root, dirs, files in os.walk(top_path): for root, dirs, files in os.walk(top_path):
if dirs: if dirs:
print("Directory '%s' contains sub-directories, safely aborting..." % root) print("Directory '%s' contains sub-directories, safely aborting..." % root)
@ -1098,6 +1114,15 @@ def create_time_dir(top_path, desc):
def pprint_seconds(seconds, fmt): def pprint_seconds(seconds, fmt):
return fmt % reduce(lambda x, y: divmod(x[0], y) + x[1:], [(seconds,), 60, 60]) return fmt % reduce(lambda x, y: divmod(x[0], y) + x[1:], [(seconds,), 60, 60])
def repr23(s):
if all(True if 0x20 <= ord(c) < 0x7f else False for c in s):
return s
if PY3:
return repr(s.encode('latin1'))[1:]
else:
return repr(s)
def md5hex(plain): def md5hex(plain):
return hashlib.md5(plain).hexdigest() return hashlib.md5(plain).hexdigest()
@ -1344,6 +1369,7 @@ def flatten(l):
else: else:
r.append(ppstr(x)) r.append(ppstr(x))
return r return r
# }}} # }}}
# Controller {{{ # Controller {{{
@ -1464,7 +1490,8 @@ Please read the README inside for more examples and usage information.
exe_grp.add_option('-e', dest='encodings', action='append', default=[], metavar='arg', help='encode everything between two tags, see Syntax below') exe_grp.add_option('-e', dest='encodings', action='append', default=[], metavar='arg', help='encode everything between two tags, see Syntax below')
exe_grp.add_option('-C', dest='combo_delim', default=':', metavar='str', help="delimiter string in combo files (default is ':')") exe_grp.add_option('-C', dest='combo_delim', default=':', metavar='str', help="delimiter string in combo files (default is ':')")
exe_grp.add_option('-X', dest='condition_delim', default=',', metavar='str', help="delimiter string in conditions (default is ',')") exe_grp.add_option('-X', dest='condition_delim', default=',', metavar='str', help="delimiter string in conditions (default is ',')")
exe_grp.add_option('--allow-ignore-failures', action='store_true', default=False, dest='allow_ignore_failures', help="failures cannot be ignored with -x (this is by design to avoid false negatives) this option overrides this safeguard") exe_grp.add_option('--allow-ignore-failures', dest='allow_ignore_failures', action='store_true', help="failures cannot be ignored with -x (this is by design to avoid false negatives) this option overrides this safeguard")
exe_grp.add_option('-y', dest='assume_yes', action='store_true', help="automatically answer yes for all questions")
opt_grp = OptionGroup(parser, 'Optimization') opt_grp = OptionGroup(parser, 'Optimization')
opt_grp.add_option('--rate-limit', dest='rate_limit', type='float', default=0, metavar='N', help='wait N seconds between each attempt (default is 0)') opt_grp.add_option('--rate-limit', dest='rate_limit', type='float', default=0, metavar='N', help='wait N seconds between each attempt (default is 0)')
@ -1482,7 +1509,7 @@ Please read the README inside for more examples and usage information.
log_grp.add_option('--hits', dest='hits_file', metavar='FILE', help="save found candidates to FILE") log_grp.add_option('--hits', dest='hits_file', metavar='FILE', help="save found candidates to FILE")
dbg_grp = OptionGroup(parser, 'Debugging') dbg_grp = OptionGroup(parser, 'Debugging')
dbg_grp.add_option('-d', '--debug', dest='debug', action='store_true', default=False, help='enable debug messages') dbg_grp.add_option('-d', '--debug', dest='debug', action='store_true', help='enable debug messages')
dbg_grp.add_option('--auto-progress', dest='auto_progress', type='int', default=0, metavar='N', help='automatically display progress every N seconds') dbg_grp.add_option('--auto-progress', dest='auto_progress', type='int', default=0, metavar='N', help='automatically display progress every N seconds')
parser.option_groups.extend([exe_grp, opt_grp, log_grp, dbg_grp]) parser.option_groups.extend([exe_grp, opt_grp, log_grp, dbg_grp])
@ -1539,7 +1566,7 @@ Please read the README inside for more examples and usage information.
log_queue = multiprocessing.Queue() log_queue = multiprocessing.Queue()
logsvc = multiprocessing.Process(name='LogSvc', target=process_logs, args=(log_queue, module.Response.indicatorsfmt, argv, build_logdir(opts.log_dir, opts.auto_log), opts.runtime_file, opts.csv_file, opts.xml_file, opts.hits_file)) logsvc = multiprocessing.Process(name='LogSvc', target=process_logs, args=(log_queue, module.Response.indicatorsfmt, argv, build_logdir(opts.log_dir, opts.auto_log, opts.assume_yes), opts.runtime_file, opts.csv_file, opts.xml_file, opts.hits_file))
logsvc.daemon = True logsvc.daemon = True
logsvc.start() logsvc.start()
@ -2244,6 +2271,7 @@ Please read the README inside for more examples and usage information.
total_count, total_count,
total_size/num_threads, total_size/num_threads,
p.current)) p.current))
# }}} # }}}
# Response_Base {{{ # Response_Base {{{
@ -2312,13 +2340,13 @@ class Response_Base:
return val == self.mesg return val == self.mesg
def match_fgrep(self, val): def match_fgrep(self, val):
return val in str(self) return val in self.mesg
def match_egrep(self, val): def match_egrep(self, val):
return re.search(val, str(self)) return re.search(val, self.mesg)
def dump(self): def dump(self):
return self.trace or str(self) return b(self.trace or str(self))
def str_target(self): def str_target(self):
return '' return ''
@ -2353,7 +2381,7 @@ class TCP_Cache:
) )
def __init__(self): def __init__(self):
self.cache = {} # {'10.0.0.1:22': ('root', conn1), '10.0.0.2:22': ('admin', conn2), self.cache = {} # '10.0.0.1:22': ('root', conn1), '10.0.0.2:22': ('admin', conn2),
self.curr = None self.curr = None
def __del__(self): def __del__(self):
@ -2569,8 +2597,8 @@ class Telnet_login(TCP_Cache):
'''Brute-force Telnet''' '''Brute-force Telnet'''
usage_hints = ( usage_hints = (
"""%prog host=10.0.0.1 inputs='FILE0\\nFILE1' 0=logins.txt 1=passwords.txt persistent=0""" """%prog host=10.0.0.1 inputs='FILE0\\nFILE1' 0=logins.txt 1=passwords.txt"""
""" prompt_re='Username:|Password:' -x ignore:egrep='Login incorrect.+Username:'""", """ prompt_re='login:|Password:' -x ignore:fgrep='Login incorrect'""",
) )
available_options = ( available_options = (
@ -2590,7 +2618,7 @@ class Telnet_login(TCP_Cache):
return TCP_Connection(fp) return TCP_Connection(fp)
def execute(self, host, port='23', inputs=None, prompt_re='\w+:', timeout='20', persistent='1'): def execute(self, host, port='23', inputs=None, prompt_re='\w+:', timeout='20', persistent='0'):
with Timing() as timing: with Timing() as timing:
fp, _ = self.bind(host, port, timeout=timeout) fp, _ = self.bind(host, port, timeout=timeout)
@ -2622,10 +2650,7 @@ class Telnet_login(TCP_Cache):
if persistent == '0': if persistent == '0':
self.reset() self.reset()
raw = B(raw) mesg = B(raw).strip()
trace = B(trace)
mesg = repr(raw)[1:-1] # strip enclosing single quotes
return self.Response(0, mesg, timing, trace) return self.Response(0, mesg, timing, trace)
# }}} # }}}
@ -2763,10 +2788,6 @@ class SMTP_login(SMTP_Base):
logger.debug('SMTPResponseException: %s' % e) logger.debug('SMTPResponseException: %s' % e)
resp = e.args resp = e.args
except SMTPException as e:
logger.debug('SMTPException: %s' % e)
resp = '1', b(str(e))
if persistent == '0': if persistent == '0':
self.reset() self.reset()
@ -2817,25 +2838,25 @@ class Finger_lookup:
s.send(b(user)) s.send(b(user))
s.send(b'\r\n') s.send(b'\r\n')
data = b'' raw = b''
with Timing() as timing: with Timing() as timing:
while True: while True:
raw = s.recv(1024) resp = s.recv(1024)
if not raw: if not resp:
break break
data += raw raw += resp
s.close() s.close()
logger.debug('recv: %r' % data) logger.debug('recv: %r' % raw)
data = B(data).strip() mesg = B(raw).strip()
mesg = repr(data)
resp = self.Response(0, mesg, timing, data) resp = self.Response(0, mesg, timing, raw)
resp.lines = [l.strip('\r\n') for l in data.split('\n')] resp.lines = [l.strip('\r\n') for l in mesg.split('\n')]
return resp return resp
# }}} # }}}
# LDAP {{{ # LDAP {{{
@ -2869,14 +2890,13 @@ class LDAP_login:
def execute(self, host, port='389', binddn='', bindpw='', basedn='', ssl='0'): def execute(self, host, port='389', binddn='', bindpw='', basedn='', ssl='0'):
uri = 'ldap%s://%s:%s' % ('s' if ssl != '0' else '', host, port) uri = 'ldap%s://%s:%s' % ('s' if ssl != '0' else '', host, port)
cmd = ['ldapsearch', '-H', uri, '-e', 'ppolicy', '-D', binddn, '-w', bindpw, '-b', basedn, '-s', 'one'] cmd = ['ldapsearch', '-H', uri, '-e', 'ppolicy', '-D', binddn, '-w', bindpw, '-b', basedn, '-s', 'one']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env={'LDAPTLS_REQCERT': 'never'})
out = p.stdout.read()
err = p.stderr.read()
with Timing() as timing: with Timing() as timing:
code = p.wait() p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env={'LDAPTLS_REQCERT': 'never'})
out, err = map(B, p.communicate())
code = p.returncode
mesg = repr((out + err).strip())[1:-1] mesg = (out + err).strip()
trace = '[out]\n%s\n[err]\n%s' % (out, err) trace = '[out]\n%s\n[err]\n%s' % (out, err)
return self.Response(code, mesg, timing, trace) return self.Response(code, mesg, timing, trace)
@ -2888,8 +2908,9 @@ try:
from impacket.smbconnection import SMBConnection, SessionError from impacket.smbconnection import SMBConnection, SessionError
from impacket import nt_errors from impacket import nt_errors
from impacket.dcerpc.v5 import transport, lsat, lsad from impacket.dcerpc.v5 import transport, lsat, lsad
from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED
from impacket.dcerpc.v5.samr import SID_NAME_USE from impacket.dcerpc.v5.samr import SID_NAME_USE
from impacket.dcerpc.v5.dtypes import MAXIMUM_ALLOWED
from impacket.dcerpc.v5.rpcrt import DCERPCException
except ImportError: except ImportError:
notfound.append('impacket') notfound.append('impacket')
@ -2900,6 +2921,17 @@ class SMB_Connection(TCP_Connection):
class Response_SMB(Response_Base): class Response_SMB(Response_Base):
indicatorsfmt = [('code', -8), ('size', -4), ('time', 6)] indicatorsfmt = [('code', -8), ('size', -4), ('time', 6)]
def split_ntlm(password_hash):
if password_hash:
if ':' in password_hash:
lmhash, nthash = password_hash.split(':')
else:
lmhash, nthash = 'aad3b435b51404eeaad3b435b51404ee', password_hash
else:
lmhash, nthash = '', ''
return lmhash, nthash
class SMB_login(TCP_Cache): class SMB_login(TCP_Cache):
'''Brute-force SMB''' '''Brute-force SMB'''
@ -2937,12 +2969,9 @@ class SMB_login(TCP_Cache):
else: else:
with Timing() as timing: with Timing() as timing:
if password_hash: if password_hash:
if ':' in password_hash: lmhash, nthash = split_ntlm(password_hash)
lmhash, nthash = password_hash.split(':')
else:
lmhash, nthash = 'aad3b435b51404eeaad3b435b51404ee', password_hash
fp.login(user, '', domain, lmhash, nthash)
fp.login(user, '', domain, lmhash, nthash)
else: else:
fp.login(user, password, domain) fp.login(user, password, domain)
@ -2961,12 +2990,12 @@ class SMB_login(TCP_Cache):
return self.Response(code, mesg, timing) return self.Response(code, mesg, timing)
class DCE_Connection(TCP_Connection): class DCE_Connection(TCP_Connection):
def __init__(self, fp, smbt): def __init__(self, fp, rpct):
self.smbt = smbt self.rpct = rpct
TCP_Connection.__init__(self, fp) TCP_Connection.__init__(self, fp)
def close(self): def close(self):
self.smbt.get_socket().close() self.rpct.get_socket().close()
# impacket/examples/lookupsid.py is much faster because it queries 1000 SIDs per packet # impacket/examples/lookupsid.py is much faster because it queries 1000 SIDs per packet
class SMB_lookupsid(TCP_Cache): class SMB_lookupsid(TCP_Cache):
@ -2978,24 +3007,32 @@ class SMB_lookupsid(TCP_Cache):
available_options = ( available_options = (
('host', 'target host'), ('host', 'target host'),
('port', 'target port [139]'), ('port', 'target port [445]'),
('sid', 'SID to test'), ('sid', 'SID to test'),
('rid', 'RID to test'), ('rid', 'RID to test'),
('user', 'username to use if auth required'), ('user', 'username to use if auth required'),
('password', 'password to use if auth required'), ('password', 'password to use if auth required'),
('password_hash', "LM/NT hashes to test, at least one hash must be provided ('lm:nt' or ':nt' or 'lm:')"),
('domain', 'domain to test'),
) )
available_options += TCP_Cache.available_options available_options += TCP_Cache.available_options
Response = Response_Base Response = Response_Base
def connect(self, host, port, user, password, sid): def connect(self, host, port, user, password, domain, password_hash, sid):
smbt = transport.SMBTransport(host, int(port), r'\lsarpc', user, password)
lmhash, nthash = split_ntlm(password_hash)
dce = smbt.get_dce_rpc() rpctransport = transport.DCERPCTransportFactory(r'ncacn_np:%s[\pipe\lsarpc]' % host) # remoteName
rpctransport.set_dport(port)
rpctransport.setRemoteHost(host)
rpctransport.set_credentials(user, password, domain, lmhash, nthash)
dce = rpctransport.get_dce_rpc()
dce.connect() dce.connect()
dce.bind(lsat.MSRPC_UUID_LSAT) dce.bind(lsat.MSRPC_UUID_LSAT)
op2 = lsat.hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES) op2 = lsad.hLsarOpenPolicy2(dce, MAXIMUM_ALLOWED | lsat.POLICY_LOOKUP_NAMES)
if sid is None: if sid is None:
res = lsad.hLsarQueryInformationPolicy2(dce, op2['PolicyHandle'], lsad.POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation) res = lsad.hLsarQueryInformationPolicy2(dce, op2['PolicyHandle'], lsad.POLICY_INFORMATION_CLASS.PolicyAccountDomainInformation)
@ -3004,11 +3041,11 @@ class SMB_lookupsid(TCP_Cache):
self.sid = sid self.sid = sid
self.policy_handle = op2['PolicyHandle'] self.policy_handle = op2['PolicyHandle']
return DCE_Connection(dce, smbt) return DCE_Connection(dce, rpctransport)
def execute(self, host, port='139', user='', password='', sid=None, rid=None, persistent='1'): def execute(self, host, port='445', user='', password='', password_hash=None, domain='', sid=None, rid=None, persistent='1'):
fp, _ = self.bind(host, port, user, password, sid) dce, _ = self.bind(host, port, user, password, domain, password_hash, sid)
if rid: if rid:
sid = '%s-%s' % (self.sid, rid) sid = '%s-%s' % (self.sid, rid)
@ -3016,24 +3053,32 @@ class SMB_lookupsid(TCP_Cache):
sid = self.sid sid = self.sid
try: try:
res = lsat.hLsarLookupSids(fp, self.policy_handle, [sid], lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta) res = lsat.hLsarLookupSids(dce, self.policy_handle, [sid], lsat.LSAP_LOOKUP_LEVEL.LsapLookupWksta)
code, names = 0, [] code, names = 0, []
for n, item in enumerate(res['TranslatedNames']['Names']): for n, item in enumerate(res['TranslatedNames']['Names']):
names.append("%s\\%s (%s)" % (res['ReferencedDomains']['Domains'][item['DomainIndex']]['Name'], item['Name'], SID_NAME_USE.enumItems(item['Use']).name[7:])) names.append("%s\\%s (%s)" % (res['ReferencedDomains']['Domains'][item['DomainIndex']]['Name'], item['Name'], SID_NAME_USE.enumItems(item['Use']).name[7:]))
except lsat.DCERPCSessionError: except DCERPCException:
code, names = 1, ['unknown'] # STATUS_NONE_MAPPED code, names = 1, ['unknown'] # STATUS_NONE_MAPPED
if persistent == '0': if persistent == '0':
self.reset() self.reset()
return self.Response(code, ', '.join(names)) return self.Response(code, ', '.join(names))
# }}} # }}}
# POP {{{ # POP {{{
from poplib import POP3, POP3_SSL, error_proto as pop_error from poplib import POP3, POP3_SSL, error_proto as pop_error
class POP_Connection(TCP_Connection):
def close(self):
if PY3:
self.fp.close()
else:
self.fp.quit()
class POP_login(TCP_Cache): class POP_login(TCP_Cache):
'''Brute-force POP3''' '''Brute-force POP3'''
@ -3063,7 +3108,7 @@ class POP_login(TCP_Cache):
port = 995 port = 995
fp = POP3_SSL(host, int(port)) # timeout=int(timeout)) # no timeout option in python2 fp = POP3_SSL(host, int(port)) # timeout=int(timeout)) # no timeout option in python2
return TCP_Connection(fp, fp.welcome) return POP_Connection(fp, fp.welcome)
def execute(self, host, port='', ssl='0', user=None, password=None, timeout='10', persistent='1'): def execute(self, host, port='', ssl='0', user=None, password=None, timeout='10', persistent='1'):
@ -3084,7 +3129,7 @@ class POP_login(TCP_Cache):
except pop_error as e: except pop_error as e:
logger.debug('pop_error: %s' % e) logger.debug('pop_error: %s' % e)
resp = e.args[0] resp = ', '.join(map(B, e.args))
if persistent == '0': if persistent == '0':
self.reset() self.reset()
@ -3178,19 +3223,17 @@ class IMAP_login:
with Timing() as timing: with Timing() as timing:
fp = klass(host, port) fp = klass(host, port)
code, resp = 0, fp.welcome code, resp = 0, B(fp.welcome)
try: try:
if user is not None and password is not None: if user is not None and password is not None:
with Timing() as timing: with Timing() as timing:
r = fp.login(user, password) r = fp.login(user, password)
resp = ', '.join(r[1]) code, resp = r[0], ', '.join(map(B, r[1]))
# doesn't it need to self.reset() to test more creds?
except IMAP4.error as e: except IMAP4.error as e:
logger.debug('imap_error: %s' % e) logger.debug('imap_error: %s' % e)
code, resp = 1, str(e) code, resp = 1, ', '.join(map(B, e.args))
return self.Response(code, resp, timing) return self.Response(code, resp, timing)
@ -3202,8 +3245,8 @@ class Rlogin_login(TCP_Cache):
usage_hints = ( usage_hints = (
"""Please note that rlogin requires to bind a socket to an Internet domain privileged port.""", """Please note that rlogin requires to bind a socket to an Internet domain privileged port.""",
"""%prog host=10.0.0.1 user=root luser=FILE0 0=logins.txt persistent=0 -x ignore:fgrep=Password:""", """%prog host=10.0.0.1 user=root luser=FILE0 0=logins.txt""",
"""%prog host=10.0.0.1 user=john password=FILE0 0=passwords.txt -x 'reset:egrep!=Login incorrect.+login:'""", """%prog host=10.0.0.1 user=john password=FILE0 0=passwords.txt""",
) )
available_options = ( available_options = (
@ -3234,7 +3277,7 @@ class Rlogin_login(TCP_Cache):
return TCP_Connection(fp) return TCP_Connection(fp)
def execute(self, host, port='513', luser='root', user='', password=None, prompt_re='\w+:', timeout='10', persistent='1'): def execute(self, host, port='513', luser='root', user='', password=None, prompt_re='\w+:', timeout='10', persistent='0'):
fp, _ = self.bind(host, port, timeout=int(timeout)) fp, _ = self.bind(host, port, timeout=int(timeout))
@ -3249,22 +3292,22 @@ class Rlogin_login(TCP_Cache):
else: else:
fp.write(b('%s\r' % user)) fp.write(b('%s\r' % user))
_, _, resp = fp.expect([prompt_re], timeout=timeout) # expecting the Password: prompt _, m, raw = fp.expect([prompt_re], timeout=timeout) # expecting the Password: prompt
trace += resp logger.debug('raw: %r' % raw)
trace += raw
if password is not None: if m and password is not None:
fp.write(b('%s\r' % password)) fp.write(b('%s\r' % password))
_, _, resp = fp.expect([prompt_re], timeout=timeout) # expecting the login: prompt _, _, raw = fp.expect([prompt_re], timeout=timeout) # expecting the login: prompt
trace += resp logger.debug('raw: %r' % raw)
trace += raw
if persistent == '0': if persistent == '0':
self.reset() self.reset()
resp = B(resp) mesg = B(raw).strip()
trace = B(trace)
mesg = repr(resp.strip())[1:-1]
return self.Response(0, mesg, timing, trace) return self.Response(0, mesg, timing, trace)
# }}} # }}}
# VMauthd {{{ # VMauthd {{{
@ -3439,9 +3482,11 @@ class MySQL_query(TCP_Cache):
fp.query(query) fp.query(query)
rs = fp.store_result() rs = fp.store_result()
rows = rs.fetch_row(10, 0) rows = rs.fetch_row(maxrows=0, how=0)
logger.debug('fetched %d rows: %s' % (len(rows), rows))
code, mesg = '0', '\n'.join(', '.join(map(str, r)) for r in filter(any, rows)) code, mesg = '0', '\n'.join(', '.join(map(B, r)) for r in filter(any, rows))
return self.Response(code, mesg, timing) return self.Response(code, mesg, timing)
# }}} # }}}
@ -3501,6 +3546,7 @@ class MSSQL_login:
fp.disconnect() fp.disconnect()
return self.Response(code, mesg, timing) return self.Response(code, mesg, timing)
# }}} # }}}
# Oracle {{{ # Oracle {{{
@ -3589,7 +3635,7 @@ class Pgsql_login:
except psycopg2.OperationalError as e: except psycopg2.OperationalError as e:
logger.debug('OperationalError: %s' % e) logger.debug('OperationalError: %s' % e)
code, mesg = '1', str(e)[:-1] code, mesg = '1', str(e).strip()
return self.Response(code, mesg, timing) return self.Response(code, mesg, timing)
@ -3636,9 +3682,6 @@ class Response_HTTP(Response_Base):
def match_clen(self, val): def match_clen(self, val):
return match_range(self.content_length, val) return match_range(self.content_length, val)
def match_fgrep(self, val):
return val in self.mesg
def match_egrep(self, val): def match_egrep(self, val):
return re.search(val, self.mesg, re.M) return re.search(val, self.mesg, re.M)
@ -4065,7 +4108,7 @@ class AJP_fuzz(TCP_Cache):
# }}} # }}}
# {{{ RDP # RDP {{{
if not which('xfreerdp'): if not which('xfreerdp'):
notfound.append('xfreerdp') notfound.append('xfreerdp')
@ -4101,10 +4144,11 @@ class RDP_login:
elif 'Authentication only, exit status 0' in err: elif 'Authentication only, exit status 0' in err:
err = 'OK' err = 'OK'
mesg = repr((out + err).strip())[1:-1] mesg = (out + err).strip()
trace = '[out]\n%s\n[err]\n%s' % (out, err) trace = '[out]\n%s\n[err]\n%s' % (out, err)
return self.Response(code, mesg, timing, trace) return self.Response(code, mesg, timing, trace)
# }}} # }}}
# VNC {{{ # VNC {{{
@ -4340,16 +4384,17 @@ def generate_srv():
import re import re
files = ['/usr/share/nmap/nmap-protocols', '/usr/share/nmap/nmap-services', '/etc/protocols', '/etc/services'] files = ['/usr/share/nmap/nmap-protocols', '/usr/share/nmap/nmap-services', '/etc/protocols', '/etc/services']
ret = [] ret = []
for f in files: for filepath in files:
if not os.path.isfile(f): if not os.path.isfile(filepath):
logger.warn("File '%s' is missing, there will be less records to test" % f) logger.warn("File '%s' is missing, there will be less records to test" % filepath)
continue continue
for line in open(f): with open(filepath, 'rb') as f:
match = re.match(r'([a-zA-Z0-9]+)\s', line) for line in f:
if not match: match = re.match(r'([a-zA-Z0-9]+)\s', B(line))
continue if not match:
for w in re.split(r'[^a-z0-9]', match.group(1).strip().lower()): continue
ret.extend(['_%s.%s' % (w, i) for i in ('_tcp', '_udp')]) for w in re.split(r'[^a-z0-9]', match.group(1).strip().lower()):
ret.extend(['_%s.%s' % (w, i) for i in ('_tcp', '_udp')])
return ret return ret
srv = set(common + distro()) srv = set(common + distro())
@ -4827,7 +4872,7 @@ class Unzip_pass:
out, err = map(B, p.communicate()) out, err = map(B, p.communicate())
code = p.returncode code = p.returncode
mesg = repr(out.strip())[1:-1] mesg = out.strip()
trace = '%s\n[out]\n%s\n[err]\n%s' % (cmd, out, err) trace = '%s\n[out]\n%s\n[err]\n%s' % (cmd, out, err)
return self.Response(code, mesg, timing, trace) return self.Response(code, mesg, timing, trace)
@ -4864,7 +4909,7 @@ class Keystore_pass:
out, err = map(B, p.communicate()) out, err = map(B, p.communicate())
code = p.returncode code = p.returncode
mesg = repr(out.strip())[1:-1] mesg = out.strip()
trace = '%s\n[out]\n%s\n[err]\n%s' % (cmd, out, err) trace = '%s\n[out]\n%s\n[err]\n%s' % (cmd, out, err)
return self.Response(code, mesg, timing, trace) return self.Response(code, mesg, timing, trace)
@ -4873,7 +4918,10 @@ class Keystore_pass:
# SQLCipher {{{ # SQLCipher {{{
try: try:
from pysqlcipher3 import dbapi2 as sqlcipher if PY3:
from pysqlcipher3 import dbapi2 as sqlcipher
else:
from pysqlcipher import dbapi2 as sqlcipher
except ImportError: except ImportError:
notfound.append('pysqlcipher') notfound.append('pysqlcipher')
@ -4964,12 +5012,14 @@ class TCP_fuzz:
if ssl != '0': if ssl != '0':
fp = wrap_socket(fp) fp = wrap_socket(fp)
fp.send(unhexlify(data)) fp.send(unhexlify(data))
#fp.send(b(data))
with Timing() as timing: with Timing() as timing:
resp = fp.recv(1024) resp = fp.recv(1024)
fp.close() fp.close()
code = 0 code = 0
mesg = B(hexlify(resp)) #mesg = B(hexlify(resp))
mesg = B(resp)
return self.Response(code, mesg, timing) return self.Response(code, mesg, timing)
@ -5076,6 +5126,7 @@ dependencies = {
'pysqlcipher': [('sqlcipher_pass',), 'https://github.com/rigglemania/pysqlcipher3', '1.0.3'], 'pysqlcipher': [('sqlcipher_pass',), 'https://github.com/rigglemania/pysqlcipher3', '1.0.3'],
'python': [('ftp_login',), 'Patator requires Python 3.6 or above and may still work on Python 2.'], 'python': [('ftp_login',), 'Patator requires Python 3.6 or above and may still work on Python 2.'],
} }
# }}} # }}}
# main {{{ # main {{{

@ -0,0 +1,108 @@
#!/bin/bash
case "$1" in
python2|python3)
PYTHON=$1
;;
*)
docker-compose up -d --build
$0 python3
$0 python2
exit 0
;;
esac
UNIX='unix'
ORACLE='oracle'
MSSQL='mssql'
LOGS='-l ./asdf -y --hits ./hits.txt'
run()
{
echo
echo "$ $@"
docker-compose run --rm --entrypoint "$PYTHON patator.py" patator "$@"
}
echo
echo ">>> $PYTHON"
run ftp_login host=$UNIX
run ftp_login host=$UNIX user=userRANGE0 password=PasswordRANGE0 0=int:0-9
run ssh_login host=$UNIX
run ssh_login host=$UNIX user=userRANGE0 password=PasswordRANGE0 0=int:0-9
run telnet_login host=$UNIX
run telnet_login host=$UNIX inputs='userRANGE0\nPasswordRANGE0' 0=int:0-9 prompt_re='login:|Password:' timeout=5
run smtp_vrfy host=$UNIX
run smtp_vrfy host=$UNIX user=userRANGE0 0=int:1-500 -x ignore:fgrep='User unknown' -x ignore,reset,retry:code=421 --auto-progress 10
run smtp_rcpt host=$UNIX
run smtp_rcpt host=$UNIX mail_from=root@localhost user=userRANGE0@localhost 0=int:1-200 -x ignore:fgrep='User unknown'
run smtp_login host=$UNIX
run smtp_login host=$UNIX user=userRANGE0 password=PasswordRANGE0 0=int:0-30 starttls=1 #-x ignore,reset,retry:code=421
run finger_lookup host=$UNIX
run finger_lookup host=$UNIX user=userRANGE0 0=int:0-20 -x ignore:fgrep='no such user'
run ldap_login host=$UNIX
run ldap_login host=$UNIX binddn='cn=admin,dc=example,dc=com' bindpw=PasswordRANGE0 0=int:0-9 basedn='dc=example,dc=com'
run smb_login host=$UNIX
run smb_login host=$UNIX user=userRANGE0 password=PasswordRANGE0 0=int:0-9
run pop_login host=$UNIX
run pop_login host=$UNIX user=userRANGE0 password=PasswordRANGE0 0=int:0-9
run pop_passd host=$UNIX
run pop_passd host=$UNIX user=userRANGE0 password=PasswordRANGE0 0=int:0-9
run imap_login host=$UNIX
run imap_login host=$UNIX user=userRANGE0 password=PasswordRANGE0 0=int:0-9
run rlogin_login host=$UNIX user=userRANGE0 password=PasswordRANGE0 0=int:0-9
run mysql_login host=$UNIX
run mysql_login host=$UNIX user=root password=PasswordRANGE0 0=int:0-9
run mysql_query host=$UNIX user=root password=Password1 query='select host, user from mysql.user'
run mysql_query host=$UNIX user=root password=Password1 query='select load_file("/etc/hosts")'
run mssql_login host=$MSSQL user=sa password=PasswordRANGE0 0=int:0-9
run oracle_login host=$ORACLE sid=xRANGE0 0=lower:a-f -t 1
run oracle_login host=$ORACLE sid=xe user=sys password=oraclRANGE0 0=lower:a-f
run pgsql_login host=$UNIX
run pgsql_login host=$UNIX user=postgres password=PasswordRANGE0 0=int:0-9
run http_fuzz url="http://$UNIX/RANGE0" 0=lower:a-zzz -x ignore:code=404
run http_fuzz url=http://$UNIX:8080/manager/html user_pass=tomcat:PasswordRANGE0 0=int:0-9
run ajp_fuzz url=ajp://$UNIX/manager/html user_pass=tomcat:PasswordRANGE0 0=int:0-9
run vnc_login host=$UNIX port=5900 password=PassworRANGE0 0=lower:a-f
run dns_reverse host=NET0 0=216.239.32.0-216.239.32.255,8.8.8.0/24 -x ignore:code=3 -x ignore:fgrep!=google.com -x ignore:fgrep=216-239-
run dns_forward name=MOD0.microsoft.com 0=SRV qtype=SRV -x ignore:code=3 --auto-progress 15
run unzip_pass zipfile=enc.zip password=PasswordRANGE0 0=int:0-9
run keystore_pass keystore=keystore.jks password=PasswordRANGE0 0=int:0-9
run sqlcipher_pass database=enc.db password=PasswordRANGE0 0=int:0-9
run umbraco_crack hashlist=@umbraco_users.pw password=PasswordRANGE0 0=int:0-9
run tcp_fuzz host=$UNIX port=4444 data=RANGE0 0=hex:0xf0-0xf9 # $LOGS
echo -e '\xde\xad\xbe\xef\nprintable ascii' > dummy.txt
run dummy_test delay=0 data=FILE0 0=dummy.txt data2=RANGE1 1=lower:a-b
echo -e 'wrong pass\np\x1fssw\x09rd' > user9.pass
run ssh_login host=unix user=user9 password=FILE0 0=user9.pass
rm -f dummy.txt user9.pass

@ -0,0 +1,118 @@
FROM ubuntu:18.04
MAINTAINER Sebastien Macke <lanjelot@gmail.com>
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN { for i in {3..5}; do useradd -m -s /bin/bash user$i; echo -e "Password$i\nPassword$i" | passwd user$i; done; } \
&& useradd -m user9 && echo -e 'p\x1fssw\x09rd\np\x1fssw\x09rd' | passwd user9
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y vsftpd openssh-server telnetd rsh-redone-server fingerd apache2 socat
RUN { echo "postfix postfix/mailname string ubuntu-bionic"; \
echo "postfix postfix/main_mailer_type string 'Internet Site'"; \
} | debconf-set-selections \
&& apt-get update && apt-get install -y postfix mail-stack-delivery \
&& postconf -e 'smtpd_sasl_exceptions_networks='
RUN echo 'ServerName localhost' >> /etc/apache2/apache2.conf \
&& mkdir /var/www/html/{wp,pma,bak} && echo secret > /var/www/html/key
RUN LDAPPW=Password1; \
{ \
echo slapd slapd/internal/generated_adminpw password $LDAPPW; \
echo slapd slapd/password2 password $LDAPPW; \
echo slapd slapd/internal/adminpw password $LDAPPW; \
echo slapd slapd/password1 password $LDAPPW; \
echo slapd slapd/domain string example.com; \
echo slapd shared/organization string example.com; \
} | debconf-set-selections \
&& apt-get update && apt-get install -y slapd ldap-utils
RUN MYSRP=Password1; \
{ echo "mysql-server mysql-server/root_password password $MYSRP"; \
echo "mysql-server mysql-server/root_password_again password $MYSRP"; \
} | debconf-set-selections \
&& apt-get update && apt-get install -y mysql-server \
&& sed -i "s/bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/mysql.conf.d/mysqld.cnf \
&& echo secure_file_priv= >> /etc/mysql/mysql.conf.d/mysqld.cnf \
&& Q1="GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY '$MYSRP' WITH GRANT OPTION;" \
&& Q2="FLUSH PRIVILEGES;" \
&& SQL="${Q1}${Q2}" \
&& rm -f /etc/apparmor.d/usr.sbin.mysqld \
&& service mysql start \
&& mysql -uroot -p"$MYSRP" -e "$SQL"
RUN PGPW=Password1 \
&& apt-get update && apt-get install -y postgresql \
&& sed -ie 's,127.0.0.1/32,0.0.0.0/0,' /etc/postgresql/10/main/pg_hba.conf \
&& sed -ie "s,^#listen_addresses = 'localhost',listen_addresses = '*'," /etc/postgresql/10/main/postgresql.conf \
&& service postgresql start \
&& su - postgres -c "psql -c \"ALTER USER postgres WITH PASSWORD '$PGPW';\" -c '\\q'" \
&& su - postgres -c "PGPASSWORD='$PGPW' psql -d postgres -w --no-password -h localhost -p 5432 -t -c 'SELECT version()'"
RUN apt-get update && apt-get install -y tomcat9 tomcat9-admin \
&& TOMCATPW=Password1 \
&& echo '<?xml version="1.0" encoding="UTF-8"?><tomcat-users xmlns="http://tomcat.apache.org/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd" version="1.0"><user username="tomcat" password="Password1" roles="manager-gui"/></tomcat-users>' > /etc/tomcat9/tomcat-users.xml \
&& sed -ie 's,^.*Define an AJP .* Connector on port.*$,<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />,' /etc/tomcat9/server.xml \
&& sed -ie 's,catalina.realm.LockOutRealm",catalina.realm.LockOutRealm" lockOutTime="0",' /etc/tomcat9/server.xml \
&& echo -e "#!/bin/bash\n\
export CATALINA_HOME=/usr/share/tomcat9\n\
export CATALINA_BASE=/var/lib/tomcat9\n\
export CATALINA_TMPDIR=/tmp\n\
export SECURITY_MANAGER=true\n\
export JAVA_OPTS=-Djava.awt.headless=true\n\
/usr/libexec/tomcat9/tomcat-update-policy.sh\n\
/usr/libexec/tomcat9/tomcat-start.sh &\n" > /usr/local/sbin/start-tomcat.sh
RUN apt-get update && apt-get install -y dovecot-imapd dovecot-pop3d poppassd \
&& sed -ie 's,^#login_trusted_networks = *$,login_trusted_networks = 0.0.0.0/0,' /etc/dovecot/dovecot.conf
RUN apt-get update && apt-get install -y p7zip-full \
&& 7za a -pPassword1 /root/enc.zip /etc/passwd
RUN apt-get update && apt-get install -y openjdk-11-jre-headless \
&& keytool -genkey -alias test -storepass Password1 -keypass Password1 -keystore /root/keystore.jks -dname "CN=a,OU=b,O=c,L=d,ST=e,C=f"
RUN apt-get update && apt-get install -y sqlcipher \
&& sqlcipher /root/enc.db "PRAGMA key = 'Password1';create table a(id int);"
RUN echo -e 'user1:kW+7AlKMnSZQIRluNxwJOMiohAw=\nuser2:oBk37hmkFgZdZ247+g6c0Ay6Vw8=\nuser3:kW+7AlKMnSZQIRluNxwJOMiohAw=' > /root/umbraco_users.pw
RUN apt-get update && apt-get install -y tightvncserver \
&& useradd -m vncuser && mkdir ~vncuser/.vnc && echo Password | vncpasswd -f > ~vncuser/.vnc/passwd \
&& chmod 400 ~vncuser/.vnc/passwd && chown -R vncuser:vncuser ~vncuser/.vnc
# utils
RUN sed -i 's:^path-exclude=/usr/share/man:#path-exclude=/usr/share/man:' /etc/dpkg/dpkg.cfg.d/excludes \
&& apt-get update && apt-get install -y man manpages-posix iproute2 mlocate lsof sudo vim less \
telnet finger rsh-client smbclient \
&& echo 'set bg=dark' > /root/.vimrc \
&& usermod -aG sudo user3
RUN apt-get update && apt-get install -y samba \
&& { for i in {3..5}; do echo -e "Password$i\nPassword$i" | smbpasswd -a "user$i"; done; } \
&& sed -ie 's,map to guest =,#map to guest =,' /etc/samba/smb.conf
RUN echo -e "echo Starting services\n\
service vsftpd start\n\
service ssh start\n\
/usr/sbin/inetd\n\
service postfix start\n\
service dovecot start\n\
service apache2 start\n\
service slapd start\n\
service mysql start\n\
service postgresql start\n\
bash /usr/local/sbin/start-tomcat.sh\n\
socat tcp-l:106,fork,reuseaddr exec:/usr/sbin/poppassd &\n\
socat tcp-l:4444,fork,reuseaddr exec:\"echo -e 'W\xe1\xc0me'\" &\n\
cp -v /root/enc.zip /root/keystore.jks /root/enc.db /root/umbraco_users.pw /opt/patator/\n\
su - vncuser -c 'vncserver -rfbport 5900'\n\
service smbd start\n\
touch /opt/patator/.all-started\n\
tail -f /dev/null\n" > /usr/local/sbin/start-all-services.sh
CMD ["bash", "/usr/local/sbin/start-all-services.sh"]
Loading…
Cancel
Save