description = [[ [WORK IN PROGRESS] Scans the ports of a target through a Glype web proxy. The script requests the target host and port through the Glype web proxy by exploiting and identifies their state by exploiting verbose errors returned by libcurl (which is used by Glype). Works for versions prior to 1.4. For more information see: * http://www.sensepost.com/blog/4620.html ]] --- -- @args glype-portscan.proxy Glype web proxy to scan through. -- -- @args glype-portscan.port Glype web proxy port to use. -- Defaults to 80 -- -- @args glype-portscan.root Glype web proxy base path. -- Defaults to / -- -- @args glype-portscan.targetports Table of target ports to scan. -- Defaults to 80,53,23,22,21,443. -- -- @usage -- nmap -sC --script=glype-portscan --script-args glype-portscan.proxy='wwww.someglypeproxy.com', 'glype-portscan.ports={80,21,22}' -- --@output author = "Hani Benhabiles" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} require 'http' require 'stdnse' require 'url' require 'base64' -- FIX rule hostrule = function(host) return true end -- Get curl message function get_curl_message(responsebody) local curl_message = { timeout = "connect() timed out!", -- Port closed noconnect = "couldn't connect to host", -- Port closed ok = "empty reply from server", -- Open port, most probably not HTTP resolvetimeout = "name lookup timed out", -- Proxy has problem with name resolution noresolve = "Couldn't resolve host", -- Proxy couldn't resolve target name curl_error = "%s", -- Used to check if curl errors are verbose } local pre_message = "The requested resource could not be loaded. libcurl returned the error:
" -- Check body for identification string local beginpre, endpre = string.find(responsebody, pre_message) if beginpre == nil then print("error") return false end for message_type, message in pairs(curl_message) do print(string.sub(responsebody, endpre+1, endpre + #message)) if string.sub(responsebody, endpre+1, endpre + #message) == message then return message_type end end end action = function(host, port) local proxy = stdnse.get_script_args(SCRIPT_NAME .. '.proxy') local port = tonumber(stdnse.get_script_args(SCRIPT_NAME .. '.port')) or 80 local root = stdnse.get_script_args(SCRIPT_NAME .. '.root') or "/" local targetports = stdnse.get_script_args(SCRIPT_NAME .. '.targetports') or {80,79,22} -- check the proxy argument if not proxy then stdnse.print_debug(SCRIPT_NAME .. " : No value for proxy argument.") end -- messages returned by local result = {} local all = {} local requests = {} -- Check curl error local error_path = "index.php?e=curl_error" -- Request Glype curl error pattern to Proxy local responsebody = http.get(proxy, port, root .. error_path).body if get_curl_message(responsebody) ~= "curl_error" then stdnse.print_debug(SCRIPT_NAME .. " : Curl error message not returned.") return false end -- Add requests for _,targetport in pairs(targetports) do -- Create url to request print("PORT: ", targetport) local url = "browse.php?u=" .. url.escape(base64.enc("http://" .. (host.name or host.ip .. targetport))) .. "&b=13&f=norefer" -- add request to pipeline all = http.pipeline_add(root .. url, nil, all, "GET") -- add to requests buffer table.insert(requests, targetport) end -- send requests local pipeline_responses = http.pipeline_go(proxy, port, all) if not pipeline_responses then stdnse.print_debug(1, "No answers from pipelined requests ", SCRIPT_NAME) return nil end -- Check responses -- for i, response in pairs(pipeline_responses) do -- Check for returned curl message for each response local curl_message = get_curl_message(response.body) print(" .. ", curl_message) -- string.match(response.body, identification_string) then -- table.insert(result, requests[i]) end -- return results return stdnse.format_output(true,result) end