Lucene search

K
nmapGeorge ChatzisofroniouNMAP:HTTP-DOMBASED-XSS.NSE
HistoryAug 10, 2013 - 7:30 p.m.

http-dombased-xss NSE Script

2013-08-1019:30:56
George Chatzisofroniou
nmap.org
177

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

It looks for places where attacker-controlled information in the DOM may be used to affect JavaScript execution in certain ways. The attack is explained here: <http://www.webappsec.org/projects/articles/071105.shtml&gt;

See also:

Script Arguments

http-dombased-xss.singlepages

The pages to test. For example, {/index.php, /profile.php}. Default: nil (crawler mode on)

slaxml.debug

See the documentation for the slaxml library.

httpspider.doscraping, httpspider.maxdepth, httpspider.maxpagecount, httpspider.noblacklist, httpspider.url, httpspider.useheadfornonwebfiles, httpspider.withindomain, httpspider.withinhost

See the documentation for the httpspider library.

http.host, http.max-body-size, http.max-cache-size, http.max-pipeline, http.pipeline, http.truncated-ok, http.useragent

See the documentation for the http library.

smbdomain, smbhash, smbnoguest, smbpassword, smbtype, smbusername

See the documentation for the smbauth library.

Example Usage

nmap -p80 --script http-dombased-xss.nse &lt;target&gt;

DOM-based XSS occur in client-side JavaScript and this script tries to detect
them by using some patterns. Please note, that the script may generate some
false positives. Don't take everything in the output as a vulnerability, if
you don't review it first.

Most of the patterns used to determine the vulnerable code have been taken
from this page: https://code.google.com/p/domxsswiki/wiki/LocationSources

Script Output

PORT   STATE SERVICE REASON
80/tcp open  http    syn-ack
| http-dombased-xss:
| Spidering limited to: maxdepth=3; maxpagecount=20; withinhost=some-very-random-page.com
|   Found the following indications of potential DOM based XSS:
|
|     Source: document.write("&lt;OPTION value=1&gt;"+document.location.href.substring(document.location.href.indexOf("default=")
|     Pages: http://some-very-random-page.com:80/, http://some-very-random-page.com/foo.html
|
|     Source: document.write(document.URL.substring(pos,document.URL.length)
|_    Pages: http://some-very-random-page.com/foo.html

Requires


description = [[
It looks for places where attacker-controlled information in the DOM may be used
to affect JavaScript execution in certain ways. The attack is explained here:
http://www.webappsec.org/projects/articles/071105.shtml
]]

---
-- @usage nmap -p80 --script http-dombased-xss.nse <target>
--
-- DOM-based XSS occur in client-side JavaScript and this script tries to detect
-- them by using some patterns. Please note, that the script may generate some
-- false positives. Don't take everything in the output as a vulnerability, if
-- you don't review it first.
--
-- Most of the patterns used to determine the vulnerable code have been taken
-- from this page: https://code.google.com/p/domxsswiki/wiki/LocationSources
--
-- @args http-dombased-xss.singlepages The pages to test. For example,
--       {/index.php,  /profile.php}. Default: nil (crawler mode on)
--
-- @output
-- PORT   STATE SERVICE REASON
-- 80/tcp open  http    syn-ack
-- | http-dombased-xss:
-- | Spidering limited to: maxdepth=3; maxpagecount=20; withinhost=some-very-random-page.com
-- |   Found the following indications of potential DOM based XSS:
-- |
-- |     Source: document.write("<OPTION value=1>"+document.location.href.substring(document.location.href.indexOf("default=")
-- |     Pages: http://some-very-random-page.com:80/, http://some-very-random-page.com/foo.html
-- |
-- |     Source: document.write(document.URL.substring(pos,document.URL.length)
-- |_    Pages: http://some-very-random-page.com/foo.html
--
-- @see http-stored-xss.nse
-- @see http-phpself-xss.nse
-- @see http-xssed.nse
-- @see http-unsafe-output-escaping.nse
---

categories = {"intrusive", "exploit", "vuln"}
author = "George Chatzisofroniou"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"

local http = require "http"
local shortport = require "shortport"
local stdnse = require "stdnse"
local table = require "table"
local string = require "string"
local httpspider = require "httpspider"

JS_FUNC_PATTERNS = {
    '(document%.write%s*%((.-)%))',
    '(document%.writeln%s*%((.-)%))',
    '(document%.execCommand%s*%((.-)%))',
    '(document%.open%s*%((.-)%))',
    '(window%.open%s*%((.-)%))',
    '(eval%s*%((.-)%))',
    '(window%.execScript%s*%((.-)%))',
}

JS_CALLS_PATTERNS = {
   'document%.URL',
   'document%.documentURI',
   'document%.URLUnencoded',
   'document%.baseURI',
   'document%.referrer',
   'location',
}

portrule = shortport.port_or_service( {80, 443}, {"http", "https"}, "tcp", "open")

action = function(host, port)

  local singlepages = stdnse.get_script_args("http-dombased-xss.singlepages")

  local domxss = {}

  local crawler = httpspider.Crawler:new( host, port, '/', { scriptname = SCRIPT_NAME, withinhost = 1 } )

  if (not(crawler)) then
    return
  end

  crawler:set_timeout(10000)

  local index, k, target, response, path
  while (true) do

    if singlepages then
      k, target = next(singlepages, index)
      if (k == nil) then
        break
      end
      response = http.get(host, port, target)
      path = target

    else
      local status, r = crawler:crawl()
      -- if the crawler fails it can be due to a number of different reasons
      -- most of them are "legitimate" and should not be reason to abort
      if (not(status)) then
        if (r.err) then
          return stdnse.format_output(false, r.reason)
        else
          break
        end
      end

      response = r.response
      path = tostring(r.url)
    end

    if response.body then

      for _, fp in ipairs(JS_FUNC_PATTERNS) do
        for i in string.gmatch(response.body, fp) do
          for _, cp in ipairs(JS_CALLS_PATTERNS) do
            if string.find(i, cp) then
              if not domxss[i] then
                domxss[i] = {path}
              else
                table.insert(domxss[i], ", " .. path)
              end
            end
          end
        end
      end

      if (index) then
        index = index + 1
      else
        index = 1
      end
    end

  end

  -- If the table is empty.
  if next(domxss) == nil then
    return "Couldn't find any DOM based XSS."
  end

  local results = {}
  for x, _ in pairs(domxss) do
    table.insert(results, { "\nSource: " .. x, "Pages: " .. table.concat(_) })
  end

  table.insert(results, 1, "Found the following indications of potential DOM based XSS: ")

  results.name = crawler:getLimitations()

  return stdnse.format_output(true, results)

end

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.973 High

EPSS

Percentile

99.8%

Related for NMAP:HTTP-DOMBASED-XSS.NSE