1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-12 18:59:03 +00:00

Main changes on script http-open-proxy.nse:

- Attempts requests using HEAD and CONNECT also (not only GET, as before).
- Script now accepts destination url for doing the test as argument
- Chekings now are made using response code (200, 301, 302) and no longer google server header
This commit is contained in:
joao
2009-06-12 23:28:21 +00:00
parent f39e109b64
commit c951c9d0c1

View File

@@ -2,12 +2,22 @@ description=[[
Checks if an HTTP proxy is open. Checks if an HTTP proxy is open.
The script attempts to connect to www.google.com through the (possible) proxy and checks The script attempts to connect to www.google.com through the (possible) proxy and checks
for a <code>Server: gws</code> header field in the response. for a valid HTTP response code.
Valid HTTP response codes are actually: 200, 301, 302.
If the target is an open proxy, this script causes the target to retrieve a If the target is an open proxy, this script causes the target to retrieve a
web page from www.google.com. web page from www.google.com.
]] ]]
---
-- @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 succesfully tested: GET HEAD CONNECT
-- Arturo 'Buanzo' Busleiman <buanzo@buanzo.com.ar> / www.buanzo.com.ar / linux-consulting.buanzo.com.ar -- 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. -- Changelog: Added explode() function. Header-only matching now works.
-- * Fixed set_timeout -- * Fixed set_timeout
@@ -15,64 +25,102 @@ web page from www.google.com.
-- 2008-10-02 Vlatko Kosturjak <kost@linux.hr> -- 2008-10-02 Vlatko Kosturjak <kost@linux.hr>
-- * Match case-insensitively against "^Server: gws" rather than -- * Match case-insensitively against "^Server: gws" rather than
-- case-sensitively against "^Server: GWS/". -- case-sensitively against "^Server: GWS/".
-- 2009-05-14 Joao Correa <joao@livewire.com.br>
-- * Included tests for HEAD and CONNECT methods
-- * Included url arguments
-- * Script now checks for http response status code
author = "Arturo 'Buanzo' Busleiman <buanzo@buanzo.com.ar>" author = "Arturo 'Buanzo' Busleiman <buanzo@buanzo.com.ar>"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html" license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default", "discovery", "external", "intrusive"} categories = {"default", "discovery", "external", "intrusive"}
require "comm" require "comm"
require "shortport" require "shortport"
require "stdnse"
require "url"
--- An explode function for NSE/LUA. Taken (and fixed) from http://lua-users.org/wiki/LuaRecipes --- check function, makes checkings for all valid returned status
--@param d Delimiter --- If any of the HTTP status below is found, the proxy is potentially open
--@param p Buffer to explode --@param result connection result
--@return A LUA Table --@return true if any of the status is found, otherwise false
function explode(d,p) function check(result)
local t,ll,l local status = false
t={} if string.match(result:lower(),"^http.*200.*") then return true end
ll=0 if string.match(result:lower(),"^http.*301.*") then return true end
while true do if string.match(result:lower(),"^http.*302.*") then return true end
l=string.find(p,d,ll+1,true) -- find the next d in the string return false
if l~=nil then -- if "not not" found then..
table.insert(t, string.sub(p,ll,l-1)) -- Save it in our array.
ll=l+1 -- save just after where we found it for searching next time.
else
table.insert(t, string.sub(p,ll)) -- Save what's left in our array.
break -- Break at end, as it should be, according to the lua manual.
end
end
return t
end end
portrule = shortport.port_or_service({3128,8000,8080},{'squid-http','http-proxy'}) portrule = shortport.port_or_service({8123,3128,8000,8080},{'polipo','squid-http','http-proxy'})
action = function(host, port) action = function(host, port)
local response local response
local i local i
-- We will return this if we don't find "^Server: gws" in response headers
local retval local retval
local supported_methods = "\nMethods succesfully tested: "
local fstatus = false
-- Ask proxy to open www.google.com -- Default url = nmap.org
local req = "GET http://www.google.com HTTP/1.0\r\nHost: www.google.com\r\n\r\n" -- Default host = nmap.org
local status, result = comm.exchange(host, port, req, {lines=1,proto=port.protocol, timeout=10000}) local test_url = "http://www.google.com"
local hostname = "www.google.com"
if not status then
return -- If arg url exists, use it as url
-- If arg hurl exists, use it as host_url
-- If arg url exists, but arg hurl doesn't, use url as host_url
if(nmap.registry.args.openproxy and nmap.registry.args.openproxy.url) then
test_url = nmap.registry.args.openproxy.url
if not string.match(test_url, "^http://.*") then
test_url = "http://" .. test_url
stdnse.print_debug("URL missing scheme. URL concatenated to http://")
end
url_table = url.parse(test_url)
hostname = url_table.host
end end
-- Trying GET method!
req = "GET " .. test_url .. " HTTP/1.0\r\nHost: " .. hostname .. "\r\n\r\n"
stdnse.print_debug("GET Request: " .. req)
local status, result = comm.exchange(host, port, req, {lines=1,proto=port.protocol, timeout=10000})
-- Explode result into the response table if status then
response = explode("\n",result) lstatus = check(result)
if lstatus then
-- Now, search for "Server: gws" until headers (or table) end. supported_methods = supported_methods .. "GET "
i = 0 fstatus = true
while true do
i = i+1
if i > table.getn(response) then break end
if response[i]=="\r" then break end
if string.match(response[i]:lower(),"^server: gws") then
retval = "Potentially OPEN proxy. Google\'s \"Server: gws\" header FOUND."
break
end end
end end
return retval -- Trying HEAD method
req = "HEAD " .. test_url .. " HTTP/1.0\r\nHost: " .. hostname .. "\r\n\r\n"
stdnse.print_debug("HEAD Request: " .. req)
local status, result = comm.exchange(host, port, req, {lines=1,proto=port.protocol, timeout=10000})
if status then
lstatus = check(result)
if lstatus then
supported_methods = supported_methods .. "HEAD "
fstatus = true
end
end
-- Trying CONNECT method
-- Not really sure about how correct the code below really is!
req = "CONNECT " .. hostname .. ":80 HTTP/1.0\r\n\r\n"
stdnse.print_debug("CONNECT Request: " .. req)
local status, result = comm.exchange(host, port, req, {lines=1,proto=port.protocol, timeout=10000})
if status then
lstatus = check(result);
if lstatus then
supported_methods = supported_methods .. "CONNECT"
fstatus = true
end
end
-- If any of the tests were OK, then the proxy is potentially open
if fstatus then
retval = "Potentially OPEN proxy.\n" .. supported_methods
return retval
end
return
end end