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