description = [[ Crawls a web server looking for PHP files vulnerable to PHP_SELF cross site scripting vulnerabilities. This script crawls the webserver to create a list of PHP files and then sends an attack vector/probe to all of them to identify PHP_SELF cross site scripting vulnerabilities. PHP_SELF XSS refers to cross site scripting vulnerabilities caused by the lack of sanitation of the variable $_SERVER["PHP_SELF"] in PHP scripts. This variable is commonly used in php scripts with forms and a lot of developers out there think it's safe to print it without escaping it first. Examples of Cross Site Scripting vulnerabilities in the variable $_SERVER[PHP_SELF]: *http://www.securityfocus.com/bid/37351 *http://software-security.sans.org/blog/2011/05/02/spot-vuln-percentage *http://websec.ca/advisories/view/xss-vulnerabilities-mantisbt-1.2.x The attack vector/probe used is: /'"/> You may test this script against http://calder0n.com/sillyapp/ ]] --- -- @usage -- nmap -sV --script http-phpselfxss-scan -- nmap -p80 --script http-phpself-xss --script-args 'httpspider.path=/sillyapp/' -- It's important you don't forget the last / if you're setting a path -- -- @output -- PORT STATE SERVICE REASON -- 80/tcp open http syn-ack -- | http-phpself-xss: Possible PHPSELF XSS: http://calder0n.com/sillyapp/1.php/%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E -- |_Possible PHPSELF XSS: http://calder0n.com/sillyapp/three.php/%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E --- author = "Paulino Calderon" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"vuln", "intrusive"} require "http" require "shortport" require "stdnse" require "httpspider" portrule = shortport.http -- PHP_SELF Attack vector local PHP_SELF_PROBE = '/%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E' --Launches probe request --@param host Hostname --@param port Port number --@param uri URL String --@return True if page is vulnerable/attack vector was found in body local function launch_probe(host, port, uri) local probe_response stdnse.print_debug(1, "HTTP GET %s%s", uri, PHP_SELF_PROBE) probe_response = http.get(host, port, uri .. PHP_SELF_PROBE) if http.response_contains(probe_response, "", false) then stdnse.print_debug(2, "%s: Vulnerable URI", SCRIPT_NAME, uri) return true end return false end --MAIN action = function(host, port) local output = {"Vulnerable files:"} httpspider.crawl(host, port) local uris = httpspider.get_sitemap() for _, uri in pairs(uris) do local extension = httpspider.get_uri_extension(uri) if extension == ".php" then stdnse.print_debug(2, "%s: PHP file found -> %s", SCRIPT_NAME, uri) if launch_probe(host, port, uri) then output[ #output + 1 ] = string.format("%s%s", uri, '/%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E') end end end return #output > 1 and stdnse.strjoin("\n", output) or nil end