From 0d47952611198ef6b1163f366dc03922d20b1475 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 09:42:04 +0200 Subject: Adding upstream version 7.94+git20230807.3be01efb1+dfsg. Signed-off-by: Daniel Baumann --- scripts/http-vuln-cve2011-3368.nse | 160 +++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 scripts/http-vuln-cve2011-3368.nse (limited to 'scripts/http-vuln-cve2011-3368.nse') diff --git a/scripts/http-vuln-cve2011-3368.nse b/scripts/http-vuln-cve2011-3368.nse new file mode 100644 index 0000000..e60f1f5 --- /dev/null +++ b/scripts/http-vuln-cve2011-3368.nse @@ -0,0 +1,160 @@ +local http = require "http" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local vulns = require "vulns" +local rand = require "rand" + +description = [[ +Tests for the CVE-2011-3368 (Reverse Proxy Bypass) vulnerability in Apache HTTP server's reverse proxy mode. +The script will run 3 tests: +* the loopback test, with 3 payloads to handle different rewrite rules +* the internal hosts test. According to Contextis, we expect a delay before a server error. +* The external website test. This does not mean that you can reach a LAN ip, but this is a relevant issue anyway. + +References: +* http://www.contextis.com/research/blog/reverseproxybypass/ +]] + +--- +-- @usage +-- nmap --script http-vuln-cve2011-3368 +-- +-- @output +-- PORT STATE SERVICE +-- 80/tcp open http +-- | http-vuln-cve2011-3368: +-- | VULNERABLE: +-- | Apache mod_proxy Reverse Proxy Security Bypass +-- | State: VULNERABLE +-- | IDs: CVE:CVE-2011-3368 BID:49957 +-- | Description: +-- | An exposure was reported affecting the use of Apache HTTP Server in +-- | reverse proxy mode. The exposure could inadvertently expose internal +-- | servers to remote users who send carefully crafted requests. +-- | Disclosure date: 2011-10-05 +-- | Extra information: +-- | Proxy allows requests to external websites +-- | References: +-- | https://www.securityfocus.com/bid/49957 +-- |_ https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3368 +-- +-- @args http-vuln-cve2011-3368.prefix sets the path prefix (directory) to check for the vulnerability. +-- + +author = {"Ange Gutek", "Patrik Karlsson"} +license = "Same as Nmap--See https://nmap.org/book/man-legal.html" +categories = {"intrusive", "vuln"} + + + +portrule = shortport.http + +action = function(host, port) + + local vuln = { + title = 'Apache mod_proxy Reverse Proxy Security Bypass', + IDS = { CVE='CVE-2011-3368', BID='49957'}, + description = [[ +An exposure was reported affecting the use of Apache HTTP Server in +reverse proxy mode. The exposure could inadvertently expose internal +servers to remote users who send carefully crafted requests.]], + references = { 'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3368' }, + dates = { + disclosure = { year='2011', month='10', day='05'} + }, + } + + local report = vulns.Report:new(SCRIPT_NAME, host, port) + local prefix = stdnse.get_script_args("http-vuln-cve2011-3368.prefix") or "" + + -- Take a reference chrono for a 404 + local start = os.time(os.date('*t')) + local random_page = rand.random_alpha(20) + local reference = http.get(host,port,("%s/%s.htm"):format(prefix,random_page)) + local chrono_404 = os.time(os.date('*t'))-start + + -- TEST 1: the loopback test, with 3 payloads to handle different rewrite rules + local all + all = http.pipeline_add(("%s@localhost"):format(prefix),nil, all) + all = http.pipeline_add(("%s:@localhost"):format(prefix),nil, all) + all = http.pipeline_add(("%s:@localhost:80"):format(prefix), nil, all) + + local bypass_request = http.pipeline_go(host,port, all) + if ( not(bypass_request) ) then + stdnse.debug1("got no answers from pipelined queries") + return stdnse.format_output(false, "Got no answers from pipelined queries") + end + + + -- going through the results of TEST 1 we could see + -- * 200 OK + -- o This could be the result of the server being vulnerable + -- o This could also be the result of a generic error page + -- * 40X Error + -- o This is most likely the result of the server NOT being vulnerable + -- + -- We can not determine whether the server is vulnerable or not solely + -- by relying on the 200 OK. If we have no 200 OK abort, otherwise continue + local got_200_ok + for _, response in ipairs(bypass_request) do + if ( response.status == 200 ) then + got_200_ok = true + end + end + + -- if we didn't get at least one 200 OK, the server is most like NOT vulnerable + if ( not(got_200_ok) ) then + vuln.state = vulns.STATE.NOT_VULN + return report:make_output(vuln) + end + + for i=1, #bypass_request, 1 do + stdnse.debug1("test %d returned a %d",i,bypass_request[i].status) + + -- here a 400 should be the evidence for a patched server. + if ( bypass_request[i].status == 200 and vuln.state ~= vulns.STATE.VULN ) then + + -- TEST 2: the internal hosts test. According to Contextis, we expect a delay before a server error. + -- According to my (Patrik) tests, internal hosts reachable by the server may return instant responses + local tests = { + { prefix = "", suffix = "" }, + { prefix = ":", suffix = ""}, + { prefix = ":", suffix = ":80"} + } + + -- try a bunch of hosts, and hope we hit one that's + -- not on the network, this will give us the delay we're expecting + local hosts = { + "10.10.10.10", + "192.168.211.211", + "172.16.16.16" + } + + -- perform one request for each host, and stop once we + -- receive a timeout for one of them + for _, h in ipairs(hosts) do + local response = http.get( + host, + port, + ("%s%s@%s%s"):format(prefix, tests[i].prefix, h, tests[i].suffix), + { timeout = ( chrono_404 + 5 ) * 1000 } + ) + -- check if the GET timed out + if ( not(response.status) ) then + vuln.state = vulns.STATE.VULN + break + end + end + end + end + + -- TEST 3: The external website test. This does not mean that you can reach a LAN ip, but this is a relevant issue anyway. + local external = http.get(host,port, ("%s@scanme.nmap.org"):format(prefix)) + if ( external.status == 200 and string.match(external.body,"Go ahead and ScanMe") ) then + vuln.extra_info = "Proxy allows requests to external websites" + end + return report:make_output(vuln) +end + -- cgit v1.2.3