new smtp_login module

bugs fixed in smtp modules
better trace output in http_fuzz
pull/4/merge
Lanjelot 13 years ago
parent 974ad0e1cb
commit 8c4569bfac

@ -32,6 +32,7 @@ Currently it supports the following modules:
- ftp_login : Brute-force FTP
- ssh_login : Brute-force SSH
- telnet_login : Brute-force Telnet
- smtp_login : Brute-force SMTP
- smtp_vrfy : Enumerate valid users using the SMTP 'VRFY' command
- smtp_rcpt : Enumerate valid users using the SMTP 'RCPT TO' command
- http_fuzz : Brute-force HTTP/HTTPS
@ -55,7 +56,6 @@ Future modules to be implemented:
- rdp_login
- vmware_login (902/tcp)
- pop3_login
- smtp_login
The name "Patator" comes from http://www.youtube.com/watch?v=xoBkBvnTTjo
"Whatever the payload to fire, always use the same launch tube"
@ -314,9 +314,14 @@ smtp_vrfy host=10.0.0.1 user=FILE0 0=logins.txt -x ignore:fgrep='User unknown in
* Use the RCPT TO command in case the VRFY command was disabled.
---------
smtp_rcpt host=10.0.0.1 user=FILE0@localhost 0=logins.txt helo='EHLO mx.fb.com' mail_from=root
smtp_rcpt host=10.0.0.1 user=FILE0@localhost 0=logins.txt helo='ehlo mx.fb.com' mail_from=root
* Brute-force authentication.
(a) Send a fake hostname (by default the real hostname is sent)
------------ (a)
smtp_login host=10.0.0.1 helo='ehlo its.me.com' user=FILE0@dom.com password=FILE1 0=logins.txt 1=passwords.txt
}}}
{{{ HTTP
@ -566,6 +571,7 @@ from datetime import timedelta, datetime
from struct import unpack
import socket
import subprocess
import hashlib
warnings = []
try:
@ -613,6 +619,9 @@ def create_time_dir(top_path, desc):
def pprint_seconds(seconds, fmt):
return fmt % reduce(lambda x,y: divmod(x[0], y) + x[1:], [(seconds,),60,60])
def md5hex(plain):
return hashlib.md5(plain).hexdigest()
# }}}
# Controller {{{
@ -637,6 +646,7 @@ class Controller:
available_encodings = {
'hex': (hexlify, 'encode in hexadecimal'),
'b64': (b64encode, 'encode in base64'),
'md5': (md5hex, 'hash in md5'),
}
def expand_key(self, arg):
@ -1468,82 +1478,107 @@ class Telnet_login(TCP_Cache):
# }}}
# SMTP {{{
from smtplib import SMTP
class SMTP_vrfy(TCP_Cache):
'''Enumerate valid users using SMTP VRFY'''
usage_hints = (
'''%prog host=10.0.0.1 user=FILE0 0=logins.txt [helo='EHLO blah.example.com']'''
''' -x ignore:fgrep='User unknown' -x ignore,reset,retry:code=421''',
)
from smtplib import SMTP, SMTPAuthenticationError, SMTPHeloError, SMTPException
class SMTP_Base(TCP_Cache):
available_options = (
available_options = TCP_Cache.available_options
available_options += (
('host', 'hostnames or subnets to target'),
('port', 'ports to target [25]'),
('helo', 'first command to send after connect [None]'),
('user', 'usernames to test'),
('helo', 'first command to send after connect'),
)
available_options += TCP_Cache.available_options
Response = Response_Base
def new_tcp(self, host, port):
cache_keys = ('host', 'port', 'helo')
def new_tcp(self, host, port, helo):
fp = SMTP()
resp = fp.connect(host, int(port or 25))
if helo:
cmd, name = helo.split(' ', 1)
if cmd.lower() == 'ehlo':
resp = fp.ehlo(name)
else:
resp = fp.helo(name)
return fp, resp
def execute(self, host, port=None, helo=None, user=None, persistent='1'):
fp, resp = self.get_tcp(persistent, host=host, port=port)
class SMTP_vrfy(SMTP_Base):
'''Enumerate valid users using SMTP VRFY'''
if helo is not None and resp == '':
resp = fp.docmd(helo)
usage_hints = (
'''%prog host=10.0.0.1 user=FILE0 0=logins.txt [helo='ehlo its.me.com']'''
''' -x ignore:fgrep='User unknown' -x ignore,reset,retry:code=421''',
)
def execute(self, host, port=None, helo=None, user=None, persistent='1'):
fp, resp = self.get_tcp(persistent, host=host, port=port, helo=helo)
if user is not None:
resp = fp.docmd('VRFY ' + user)
resp = fp.verify(user)
code, mesg = resp
return self.Response(code, mesg)
class SMTP_rcpt(TCP_Cache):
"""Enumerate valid users using SMTP RCPT TO"""
class SMTP_rcpt(SMTP_Base):
'''Enumerate valid users using SMTP RCPT TO'''
usage_hints = (
'''%prog host=10.0.0.1 user=FILE0@localhost 0=logins.txt [helo='EHLO blah.example.com']'''
''' [mail_from=foo@bar.org] -x ignore:fgrep='User unknown' -x ignore,reset,retry:code=421''',
'''%prog host=10.0.0.1 user=FILE0@localhost 0=logins.txt [helo='ehlo its.me.com']'''
''' [mail_from=bar@example.com] -x ignore:fgrep='User unknown' -x ignore,reset,retry:code=421''',
)
available_options = (
('host', 'hostnames or subnets to target'),
('port', 'ports to target [25]'),
('user', 'usernames to test'),
available_options = SMTP_Base.available_options
available_options += (
('mail_from', 'sender email [test@example.org]'),
('helo', 'first command to send after connect'),
)
available_options += TCP_Cache.available_options
Response = Response_Base
def execute(self, host, port=None, helo=None, mail_from='test@example.org', user=None, persistent='1'):
fp, resp = self.get_tcp(persistent, host=host, port=port, helo=helo)
def new_tcp(self, host, port):
fp = SMTP()
resp = fp.connect(host, int(port or 25))
return fp, resp
if mail_from:
resp = fp.mail(mail_from)
def execute(self, host, port=None, helo=None, mail_from='test@example.org', user=None, persistent='1'):
fp, resp = self.get_tcp(persistent, host=host, port=port)
if user:
resp = fp.rcpt(user)
if helo is not None and resp == '':
resp = fp.docmd(helo)
fp.rset()
if mail_from:
resp = fp.docmd('MAIL FROM: ' + mail_from)
code, mesg = resp
return self.Response(code, mesg)
if rcpt_to:
resp = fp.docmd('RCPT TO: ' + user)
fp.docmd('RSET')
class SMTP_login(SMTP_Base):
'''Brute-force SMTP authentication'''
usage_hints = (
'''%prog host=10.0.0.1 user=f.bar@dom.com password=FILE0 0=passwords.txt [helo='ehlo its.me.com']''',
''' -x ignore:fgrep='Authentication failed' -x ignore,reset,retry:code=421''',
)
available_options = SMTP_Base.available_options
available_options += (
('password', 'passwords to test'),
)
def execute(self, host, port=None, helo=None, user='', password='', persistent='1'):
fp, resp = self.get_tcp(persistent, host=host, port=port, helo=helo)
try:
resp = fp.login(user, password)
except (SMTPHeloError,SMTPAuthenticationError,SMTPException) as resp:
logger.debug('SMTPError: %s' % resp)
code, mesg = resp
return self.Response(code, mesg)
# }}}
# LDAP {{{
@ -1984,11 +2019,10 @@ class Controller_HTTP(Controller):
class Response_HTTP(Response_Base):
def __init__(self, code, content_length, response, request):
self.code, self.content_length, \
self.response, self.request = code, content_length, response, request
def __init__(self, code, content_length, response, trace):
self.code, self.content_length = code, content_length
self.response, self.trace = response, trace
self.size = len(self.response)
self.trace = '%s\n%s\n\n%s' % (self.request, '='*80, self.response)
def compact(self):
return '%s %s' % (self.code, '%d:%d' % (self.size, self.content_length))
@ -2082,16 +2116,18 @@ class HTTP_fuzz(TCP_Cache):
fp.setopt(pycurl.WRITEFUNCTION, noop)
def debug_func(t, s):
if max_mem > 0 and trace.tell() > max_mem:
return 0
if t in (pycurl.INFOTYPE_HEADER_IN, pycurl.INFOTYPE_DATA_IN):
if max_mem < 0 or response.tell() < max_mem:
response.write(s)
response.write(s)
elif t in (pycurl.INFOTYPE_HEADER_OUT, pycurl.INFOTYPE_DATA_OUT):
if max_mem < 0 or response.tell() < max_mem:
request.write(s)
if t != pycurl.INFOTYPE_TEXT:
trace.write(s)
max_mem = int(max_mem)
response, request = StringIO(), StringIO(),
response, trace = StringIO(), StringIO()
fp.setopt(pycurl.DEBUGFUNCTION, debug_func)
fp.setopt(pycurl.VERBOSE, 1)
@ -2158,7 +2194,7 @@ class HTTP_fuzz(TCP_Cache):
http_code = fp.getinfo(pycurl.HTTP_CODE)
content_length = fp.getinfo(pycurl.CONTENT_LENGTH_DOWNLOAD)
return self.Response(http_code, content_length, response.getvalue(), request.getvalue())
return self.Response(http_code, content_length, response.getvalue(), trace.getvalue())
# }}}
@ -2715,6 +2751,7 @@ modules = (
'ftp_login', (Controller, FTP_login),
'ssh_login', (Controller, SSH_login),
'telnet_login', (Controller, Telnet_login),
'smtp_login', (Controller, SMTP_login),
'smtp_vrfy', (Controller, SMTP_vrfy),
'smtp_rcpt', (Controller, SMTP_rcpt),
'http_fuzz', (Controller_HTTP, HTTP_fuzz),
@ -2753,7 +2790,7 @@ or
Available modules:
%s''' % '\n'.join(' + %-13s : %s' % (k, v[1].__doc__) for k, v in modules))
if warnings:
print('\nWARNING missing dependencies (see README inside)')
print('\nWARNING missing dependencies (see README inside for the supported versions)')
for w in warnings:
print('- %s' % w)
exit(2)

Loading…
Cancel
Save