diff --git a/scripts/http-phpself-xss.nse b/scripts/http-phpself-xss.nse
new file mode 100644
index 000000000..96f1f13b4
--- /dev/null
+++ b/scripts/http-phpself-xss.nse
@@ -0,0 +1,157 @@
+description=[[
+Crawls a web server and attempts to find PHP files vulnerable to reflected cross site scripting via the variable $_SERVER["PHP_SELF"].
+
+This script crawls the webserver to create a list of PHP files and then sends an attack vector/probe to identify PHP_SELF cross site scripting vulnerabilities.
+PHP_SELF XSS refers to reflected 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 that display forms and when the script file name is needed.
+
+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: /'"/>
+]]
+---
+-- @usage
+-- nmap --script=http-phpself-xss -p80
+-- nmap -sV --script http-self-xss
+-- @output
+-- PORT STATE SERVICE REASON
+-- 80/tcp open http syn-ack
+-- | http-phpself-xss:
+-- | VULNERABLE:
+-- | Unsafe use of $_SERVER["PHP_SELF"] in PHP files
+-- | State: VULNERABLE (Exploitable)
+-- | Description:
+-- | PHP files are not handling safely the variable $_SERVER["PHP_SELF"] causing Reflected Cross Site Scripting vulnerabilities.
+-- |
+-- | Extra information:
+-- |
+-- | Vulnerable files with proof of concept:
+-- | http://calder0n.com/sillyapp/three.php/%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E
+-- | http://calder0n.com/sillyapp/secret/2.php/%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E
+-- | http://calder0n.com/sillyapp/1.php/%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E
+-- | http://calder0n.com/sillyapp/secret/1.php/%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E
+-- | Spidering limited to: maxdepth=3; maxpagecount=20; withinhost=calder0n.com
+-- | References:
+-- | https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
+-- |_ http://php.net/manual/en/reserved.variables.server.php
+-- @args http-phpself-xss.uri URI. Default: /
+-- @args http-phpself-xss.timeout Spidering timeout. Default:10000
+author = "Paulino Calderon"
+license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
+categories = {"fuzzer", "intrusive", "vuln"}
+
+local http = require 'http'
+local httpspider = require 'httpspider'
+local shortport = require 'shortport'
+local url = require 'url'
+local stdnse = require 'stdnse'
+local vulns = require 'vulns'
+
+portrule = shortport.http
+
+-- PHP_SELF Attack vector
+local PHP_SELF_PROBE = '/%27%22/%3E%3Cscript%3Ealert(1)%3C/script%3E'
+local probes = {}
+
+--Checks if attack vector is in the response's body
+--@param response Response table
+--@return True if attack vector is found in response's body
+local function check_probe_response(response)
+ stdnse.print_debug(3, "Probe response:\n%s", response.body)
+ if string.find(response.body, "'\"/>", 1, true) ~= nil then
+ return true
+ end
+ return false
+end
+
+--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
+
+ --We avoid repeating probes.
+ --This is a temp fix since httpspider do not keep track of previously parsed links at the moment.
+ if probes[uri] then
+ return false
+ end
+
+ stdnse.print_debug(1, "%s:HTTP GET %s%s", SCRIPT_NAME, uri, PHP_SELF_PROBE)
+ probe_response = http.get(host, port, uri .. PHP_SELF_PROBE)
+
+ --save probe in list to avoid repeating it
+ probes[uri] = true
+
+ if check_probe_response(probe_response) then
+ return true
+ end
+ return false
+end
+
+---
+--main
+---
+action = function(host, port)
+ local uri = stdnse.get_script_args(SCRIPT_NAME..".uri") or "/"
+ local timeout = stdnse.get_script_args(SCRIPT_NAME..'.timeout') or 10000
+ local crawler = httpspider.Crawler:new(host, port, uri, { scriptname = SCRIPT_NAME } )
+ crawler:set_timeout(timeout)
+
+ local vuln = {
+ title = 'Unsafe use of $_SERVER["PHP_SELF"] in PHP files',
+ state = vulns.STATE.NOT_VULN,
+ description = [[
+PHP files are not handling safely the variable $_SERVER["PHP_SELF"] causing Reflected Cross Site Scripting vulnerabilities.
+ ]],
+ references = {
+ 'http://php.net/manual/en/reserved.variables.server.php',
+ 'https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)'
+ }
+ }
+ local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
+
+ local vulnpages = {}
+ local probed_pages= {}
+
+ while(true) do
+ local status, r = crawler:crawl()
+ if ( not(status) ) then
+ if ( r.err ) then
+ return stdnse.format_output(true, "ERROR: %s", r.reason)
+ else
+ break
+ end
+ end
+
+ local parsed = url.parse(tostring(r.url))
+
+ --Only work with .php files
+ if ( parsed.path and parsed.path:match(".*.php") ) then
+ --The following port/scheme code was seen in http-backup-finder and its neat =)
+ local host, port = parsed.host, parsed.port
+ if ( not(port) ) then
+ port = (parsed.scheme == 'https') and 443
+ port = port or ((parsed.scheme == 'http') and 80)
+ end
+ local escaped_link = parsed.path:gsub(" ", "%%20")
+ if launch_probe(host,port,escaped_link) then
+ table.insert(vulnpages, parsed.scheme..'://'..host..escaped_link..PHP_SELF_PROBE)
+ end
+ end
+ end
+
+ if ( #vulnpages > 0 ) then
+ vuln.state = vulns.STATE.EXPLOIT
+ vulnpages.name = "Vulnerable files with proof of concept:"
+ vuln.extra_info = stdnse.format_output(true, vulnpages)..crawler:getLimitations()
+ end
+
+ return vuln_report:make_output(vuln)
+
+end
+
diff --git a/scripts/script.db b/scripts/script.db
index d3cd80f0d..6f5dc7d5d 100644
--- a/scripts/script.db
+++ b/scripts/script.db
@@ -163,6 +163,7 @@ Entry { filename = "http-open-proxy.nse", categories = { "default", "discovery",
Entry { filename = "http-open-redirect.nse", categories = { "discovery", "intrusive", } }
Entry { filename = "http-passwd.nse", categories = { "intrusive", "vuln", } }
Entry { filename = "http-php-version.nse", categories = { "discovery", "safe", } }
+Entry { filename = "http-phpself-xss.nse", categories = { "fuzzer", "intrusive", "vuln", } }
Entry { filename = "http-proxy-brute.nse", categories = { "brute", "external", "intrusive", } }
Entry { filename = "http-put.nse", categories = { "discovery", "intrusive", } }
Entry { filename = "http-qnap-nas-info.nse", categories = { "discovery", "safe", } }