-
Notifications
You must be signed in to change notification settings - Fork 1
/
http-open-proxy.nse
216 lines (185 loc) · 8.13 KB
/
http-open-proxy.nse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
local proxy = require "proxy"
local shortport = require "shortport"
local stdnse = require "stdnse"
local string = require "string"
local url = require "url"
description=[[
Checks if an HTTP proxy is open.
The script attempts to connect to www.google.com through the proxy and
checks for a valid HTTP response code. Valid HTTP response codes are
200, 301, and 302. If the target is an open proxy, this script causes
the target to retrieve a web page from www.google.com.
]]
---
-- @args proxy.url Url that will be requested to the proxy
-- @args proxy.pattern Pattern that will be searched inside the request results
-- @output
-- Interesting ports on scanme.nmap.org (64.13.134.52):
-- PORT STATE SERVICE
-- 8080/tcp open http-proxy
-- | proxy-open-http: Potentially OPEN proxy.
-- |_ Methods successfully tested: GET HEAD CONNECT
-- Arturo 'Buanzo' Busleiman <buanzo@buanzo.com.ar> / www.buanzo.com.ar / linux-consulting.buanzo.com.ar
-- Changelog: Added explode() function. Header-only matching now works.
-- * Fixed set_timeout
-- * Fixed some \r\n's
-- 2008-10-02 Vlatko Kosturjak <kost@linux.hr>
-- * Match case-insensitively against "^Server: gws" rather than
-- case-sensitively against "^Server: GWS/".
-- 2009-05-14 Joao Correa <joao@livewire.com.br>
-- * Included tests for HEAD and CONNECT methods
-- * Included url and pattern arguments
-- * Script now checks for http response status code, when url is used
-- * If google is used, script checks for Server: gws
--
-- @usage
-- nmap --script http-open-proxy.nse \
-- --script-args proxy.url=<url>,proxy.pattern=<pattern>
author = "Arturo 'Buanzo' Busleiman"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "external", "safe"}
--- Performs the custom test, with user's arguments
-- @param host The host table
-- @param port The port table
-- @param test_url The url te send the request
-- @param pattern The pattern to check for valid result
-- @return status (if any request was succeded
-- @return response String with supported methods
function custom_test(host, port, test_url, pattern)
local lstatus = false
local response = ""
-- if pattern is not used, result for test is code check result.
-- otherwise it is pattern check result.
-- strip hostname
if not string.match(test_url, "^http://.*") then
test_url = "http://" .. test_url
stdnse.print_debug("URL missing scheme. URL concatenated to http://")
end
local url_table = url.parse(test_url)
local hostname = url_table.host
local get_status = proxy.test_get(host, port, "http", test_url, hostname, pattern)
local head_status = proxy.test_head(host, port, "http", test_url, hostname, pattern)
local conn_status = proxy.test_connect(host, port, "http", hostname)
if get_status then
lstatus = true
response = response .. " GET"
end
if head_status then
lstatus = true
response = response .. " HEAD"
end
if conn_status then
lstatus = true
response = response .. " CONNECTION"
end
if lstatus then response = "Methods supported: " .. response end
return lstatus, response
end
--- Performs the default test
-- First: Default google request and checks for Server: gws
-- Seconde: Request to wikipedia.org and checks for wikimedia pattern
-- Third: Request to computerhistory.org and checks for museum pattern
--
-- If any of the requests is succesful, the proxy is considered open
-- If all get requests return the same result, the user is alerted that
-- the proxy might be redirecting his requests (very common on wi-fi
-- connections at airports, cafes, etc.)
--
-- @param host The host table
-- @param port The port table
-- @return status (if any request was succeded
-- @return response String with supported methods
function default_test(host, port)
local fstatus = false
local cstatus = false
local response = ""
local get_status, head_status, conn_status
local get_r1, get_r2, get_r3
local get_cstatus, head_cstatus
-- Start test n1 -> google.com
-- making requests
local test_url = "http://www.google.com"
local hostname = "www.google.com"
local pattern = "^server: gws"
get_status, get_r1, get_cstatus = proxy.test_get(host, port, "http", test_url, hostname, pattern)
local _
head_status, _, head_cstatus = proxy.test_head(host, port, "http", test_url, hostname, pattern)
conn_status = proxy.test_connect(host, port, "http", hostname)
-- checking results
-- conn_status use a different flag (cstatus)
-- because test_connection does not use patterns, so it is unable to detect
-- cases where you receive a valid code, but the response does not match the
-- pattern.
-- if it was using the same flag, program could return without testing GET/HEAD
-- once more before returning
if get_status then fstatus = true; response = response .. " GET" end
if head_status then fstatus = true; response = response .. " HEAD" end
if conn_status then cstatus = true; response = response .. " CONNECTION" end
-- if proxy is open, return it!
if fstatus then return fstatus, "Methods supported: " .. response end
-- if we receive a invalid response, but with a valid
-- response code, we should make a next attempt.
-- if we do not receive any valid status code,
-- there is no reason to keep testing... the proxy is probably not open
if not (get_cstatus or head_cstatus or conn_status) then return false, nil end
stdnse.print_debug("Test 1 - Google Web Server\nReceived valid status codes, but pattern does not match")
test_url = "http://www.wikipedia.org"
hostname = "www.wikipedia.org"
pattern = "wikimedia"
get_status, get_r2, get_cstatus = proxy.test_get(host, port, "http", test_url, hostname, pattern)
head_status, _, head_cstatus = proxy.test_head(host, port, "http", test_url, hostname, pattern)
conn_status = proxy.test_connect(host, port, "http", hostname)
if get_status then fstatus = true; response = response .. " GET" end
if head_status then fstatus = true; response = response .. " HEAD" end
if conn_status then
if not cstatus then response = response .. " CONNECTION" end
cstatus = true
end
if fstatus then return fstatus, "Methods supported: " .. response end
-- same valid code checking as above
if not (get_cstatus or head_cstatus or conn_status) then return false, nil end
stdnse.print_debug("Test 2 - Wikipedia.org\nReceived valid status codes, but pattern does not match")
test_url = "http://www.computerhistory.org"
hostname = "www.computerhistory.org"
pattern = "museum"
get_status, get_r3, get_cstatus = proxy.test_get(host, port, "http", test_url, hostname, pattern)
conn_status = proxy.test_connect(host, port, "http", hostname)
if get_status then fstatus = true; response = response .. " GET" end
if conn_status then
if not cstatus then response = response .. " CONNECTION" end
cstatus = true
end
if fstatus then return fstatus, "Methods supported:" .. response end
if not get_cstatus then
stdnse.print_debug("Test 3 - Computer History\nReceived valid status codes, but pattern does not match")
end
-- Check if GET is being redirected
if proxy.redirectCheck(get_r1, get_r2) and proxy.redirectCheck(get_r2, get_r3) then
return false, "Proxy might be redirecting requests"
end
-- Check if at least CONNECTION worked
if cstatus then return true, "Methods supported:" .. response end
-- Nothing works...
return false, nil
end
portrule = shortport.port_or_service({8123,3128,8000,8080},{'polipo','squid-http','http-proxy'})
action = function(host, port)
local supported_methods = "\nMethods successfully tested: "
local fstatus = false
local def_test = true
local test_url, pattern
test_url, pattern = proxy.return_args()
if(test_url) then def_test = false end
if(pattern) then pattern = ".*" .. pattern .. ".*" end
if def_test
then fstatus, supported_methods = default_test(host, port)
else fstatus, supported_methods = custom_test(host, port, test_url, pattern);
end
-- If any of the tests were OK, then the proxy is potentially open
if fstatus then
return "Potentially OPEN proxy.\n" .. supported_methods
elseif not fstatus and supported_methods then
return supported_methods
end
return
end