2010-06-03 18:18:00 +00:00
##
2017-07-24 13:26:21 +00:00
# This module requires Metasploit: https://metasploit.com/download
2013-10-15 18:50:46 +00:00
# Current source: https://github.com/rapid7/metasploit-framework
2010-06-03 18:18:00 +00:00
##
2016-03-08 13:02:44 +00:00
class MetasploitModule < Msf :: Auxiliary
2016-11-17 14:44:03 +00:00
include Msf :: Exploit :: Remote :: HttpClient
2013-08-30 21:28:54 +00:00
include Msf :: Auxiliary :: Scanner
include Msf :: Auxiliary :: WmapScanServer
include Msf :: Auxiliary :: Report
def initialize ( info = { } )
super ( update_info ( info ,
'Name' = > 'HTTP Open Proxy Detection' ,
'Description' = > %q{
2016-11-17 14:44:03 +00:00
Checks if an HTTP proxy is open . False positive are avoided
2016-11-18 17:39:26 +00:00
verifying the HTTP return code and matching a pattern .
The CONNECT method is verified only the return code .
2016-11-17 14:44:03 +00:00
HTTP headers are shown regarding the use of proxy or load balancer .
2013-08-30 21:28:54 +00:00
} ,
'References' = >
[
[ 'URL' , 'http://en.wikipedia.org/wiki/Open_proxy' ] ,
[ 'URL' , 'http://nmap.org/svn/scripts/http-open-proxy.nse' ] ,
] ,
'Author' = > 'Matteo Cantoni <goony[at]nothink.org>' ,
'License' = > MSF_LICENSE
) )
register_options (
[
Opt :: RPORT ( 8080 ) ,
2016-11-17 14:44:03 +00:00
OptBool . new ( 'MULTIPORTS' , [ false , 'Multiple ports will be used: 80, 443, 1080, 3128, 8000, 8080, 8123' , false ] ) ,
OptBool . new ( 'VERIFYCONNECT' , [ false , 'Enable CONNECT HTTP method check' , false ] ) ,
OptString . new ( 'CHECKURL' , [ true , 'The web site to test via alleged web proxy' , 'http://www.google.com' ] ) ,
OptString . new ( 'VALIDCODES' , [ true , " Valid HTTP code for a successfully request " , '200,302' ] ) ,
OptString . new ( 'VALIDPATTERN' , [ true , " Valid pattern match (case-sensitive into the headers and HTML body) for a successfully request " , '<TITLE>302 Moved</TITLE>' ] ) ,
2017-05-03 20:42:21 +00:00
] )
2013-08-30 21:28:54 +00:00
register_wmap_options ( {
2016-11-17 14:44:03 +00:00
'OrderID' = > 1 ,
'Require' = > { } ,
} )
2013-08-30 21:28:54 +00:00
end
def run_host ( target_host )
2016-11-17 14:44:03 +00:00
check_url = datastore [ 'CHECKURL' ]
2013-08-30 21:28:54 +00:00
2016-11-17 14:44:03 +00:00
if datastore [ 'VERIFYCONNECT' ]
target_method = 'CONNECT'
# CONNECT doesn't need <scheme> but need port
check_url = check_url . gsub ( / [http: \/ \/ |https: \/ \/ ] / , '' )
if check_url !~ / :443$ /
check_url = check_url + " :443 "
end
else
target_method = 'GET'
# GET only http request
check_url = check_url . gsub ( / https: \/ \/ / , '' )
if check_url !~ / ^http: \/ \/ /i
check_url = 'http://' + check_url
end
2013-08-30 21:28:54 +00:00
end
2016-11-17 14:44:03 +00:00
target_ports = [ ]
2014-06-28 20:21:54 +00:00
2016-11-17 14:44:03 +00:00
if datastore [ 'MULTIPORTS' ]
target_ports = [ 80 , 443 , 1080 , 3128 , 8000 , 8080 , 8123 ]
else
target_ports . push ( datastore [ 'RPORT' ] . to_i )
2013-08-30 21:28:54 +00:00
end
2016-11-17 14:44:03 +00:00
target_proxy_headers = [ 'Forwarded' , 'Front-End-Https' , 'Max-Forwards' , 'Via' , 'X-Cache' , 'X-Cache-Lookup' , 'X-Client-IP' , 'X-Forwarded-For' , 'X-Forwarded-Host' ]
2013-08-30 21:28:54 +00:00
target_ports . each do | target_port |
2016-11-17 14:44:03 +00:00
verify_target ( target_host , target_port , target_method , check_url , target_proxy_headers )
2013-08-30 21:28:54 +00:00
end
end
2016-11-17 14:44:03 +00:00
def verify_target ( target_host , target_port , target_method , check_url , target_proxy_headers )
2013-08-30 21:28:54 +00:00
2016-11-17 14:44:03 +00:00
vprint_status ( " #{ peer } - Sending a web request... [ #{ target_method } ][ #{ check_url } ] " )
2010-06-03 18:25:29 +00:00
2016-11-17 14:44:03 +00:00
datastore [ 'RPORT' ] = target_port
2010-06-03 18:25:29 +00:00
2013-08-30 21:28:54 +00:00
begin
2016-11-17 14:44:03 +00:00
res = send_request_cgi (
'uri' = > check_url ,
'method' = > target_method ,
'version' = > '1.1'
)
2010-06-03 18:25:29 +00:00
2016-11-17 14:44:03 +00:00
return if not res
2010-06-03 18:25:29 +00:00
2016-11-17 14:44:03 +00:00
vprint_status ( " #{ peer } - Returns with ' #{ res . code } ' status code [ #{ target_method } ][ #{ check_url } ] " )
2010-06-03 18:18:00 +00:00
2016-11-17 14:44:03 +00:00
valid_codes = datastore [ 'VALIDCODES' ] . split ( / , / )
2010-06-03 18:25:29 +00:00
2016-11-17 14:44:03 +00:00
target_proxy_headers_results = [ ]
target_proxy_headers . each do | proxy_header |
if ( res . headers . to_s . match ( / #{ proxy_header } : (.*) / ) )
proxy_header_value = $1
# Ok...I don't like it but works...
target_proxy_headers_results . push ( " \n |_ #{ proxy_header } : #{ proxy_header_value } " )
2013-08-30 21:28:54 +00:00
end
end
2010-06-03 18:18:00 +00:00
2016-11-17 14:44:03 +00:00
if target_proxy_headers_results . any?
proxy_headers = target_proxy_headers_results . join ( )
2013-08-30 21:28:54 +00:00
end
2010-06-03 18:18:00 +00:00
2016-11-17 14:44:03 +00:00
if datastore [ 'VERIFYCONNECT' ]
# Verifiying CONNECT we check only the return code
if valid_codes . include? ( res . code . to_s )
2010-06-03 18:18:00 +00:00
2016-11-17 14:44:03 +00:00
print_good ( " #{ peer } - Potentially open proxy [ #{ res . code } ][ #{ target_method } ] #{ proxy_headers } " )
2010-06-03 18:25:29 +00:00
2013-08-30 21:28:54 +00:00
report_note (
:host = > target_host ,
:port = > target_port ,
2016-11-17 14:44:03 +00:00
:method = > target_method ,
:proto = > 'tcp' ,
:sname = > ( ssl ? 'https' : 'http' ) ,
:type = > 'OPEN HTTP PROXY' ,
:data = > 'Open http proxy (CONNECT)'
2013-08-30 21:28:54 +00:00
)
2010-06-03 18:18:00 +00:00
2016-11-17 14:44:03 +00:00
end
else
# Verify return code && (headers.pattern or body.pattern)
2016-11-18 17:41:04 +00:00
if valid_codes . include? ( res . code . to_s ) && ( res . headers . include? ( datastore [ 'VALIDPATTERN' ] ) || res . body . include? ( datastore [ 'VALIDPATTERN' ] ) )
2010-06-03 18:25:29 +00:00
2016-11-17 14:44:03 +00:00
print_good ( " #{ peer } - Potentially open proxy [ #{ res . code } ][ #{ target_method } ] #{ proxy_headers } " )
2010-06-03 18:25:29 +00:00
2013-08-30 21:28:54 +00:00
report_note (
:host = > target_host ,
:port = > target_port ,
2016-11-17 14:44:03 +00:00
:method = > target_method ,
:proto = > 'tcp' ,
:sname = > ( ssl ? 'https' : 'http' ) ,
:type = > 'OPEN HTTP PROXY' ,
:data = > 'Open http proxy (GET)'
2013-08-30 21:28:54 +00:00
)
2010-06-03 18:25:29 +00:00
2013-08-30 21:28:54 +00:00
end
end
2010-06-03 18:18:00 +00:00
2016-11-17 14:44:03 +00:00
rescue :: Rex :: ConnectionRefused , :: Rex :: HostUnreachable , :: Rex :: ConnectionTimeout , :: Timeout :: Error , :: Errno :: EPIPE = > e
vprint_error ( " #{ peer } - The port ' #{ target_port } ' is unreachable! " )
return nil
end
2013-08-30 21:28:54 +00:00
end
2010-06-03 18:18:00 +00:00
end