diff --git a/CHANGELOG b/CHANGELOG
index a4820a420..41c27e387 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,10 @@
# Nmap Changelog ($Id$); -*-text-*-
+o [NSE] Added http-affiliate-id.nse, which scrapes a web page for
+ affiliate IDs (like Google AdSense and Amazon associates) that can
+ be used to link sites to the same owner. [Hani Benhabiles, Daniel
+ Miller]
+
o Fixed an overflow in scan elapsed time display that caused negative
times to be printed after about 25 days. [Daniel Miller]
diff --git a/scripts/http-affiliate-id.nse b/scripts/http-affiliate-id.nse
new file mode 100644
index 000000000..0ff89976f
--- /dev/null
+++ b/scripts/http-affiliate-id.nse
@@ -0,0 +1,64 @@
+description = [[
+
+This script grabs Google Analytics and Adsense IDs.
+They could be used to further look for related websites (that have
+the same owner.)
+
+]]
+
+---
+-- @args http-affiliate-id.url-path The path to request. Defaults to
+-- /.
+--
+-- @usage
+-- nmap --script=http-affiliate-id.nse --script-args http-affiliate-id.url-path=/website
+--
+-- @output
+-- PORT STATE SERVICE
+-- 80/tcp open http
+-- | http-affiliate-id:
+-- | Google Analytics ID: UA-XXXXXXXX-XX
+-- |_ Google Adsense ID: pub-YYYYYYYYYYYYYYYY
+
+author = "Hani Benhabiles, Daniel Miller"
+
+license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
+
+categories = {"safe", "discovery"}
+
+require 'shortport'
+require 'http'
+require 'pcre'
+require 'stdnse'
+
+portrule = shortport.port_or_service( {80,443}, {"http","https"} )
+
+action = function(host, port)
+ local url_path, body, analyticsid, adsenseid, result
+ result = ""
+ url_path = stdnse.get_script_args("http-affiliate-id.url-path") or "/"
+ body = http.get( host, port, url_path).body
+
+ -- these are the regular expressions for affiliate IDs
+ local affiliates = {
+ ["Google Analytics ID"] = "(?PUA-[0-9]{6,9}-[0-9]{1,2})",
+ ["Google Adsense ID"] = "(?Ppub-[0-9]{16,16})",
+ ["Amazon Associates ID"] = "href=\"http://www.amazon.com/[^\"]*[&;]tag=(?P\\w+-\\d+)",
+ }
+
+
+ -- Here goes affiliate matching
+ for name,re in pairs(affiliates) do
+ local regex, limit, limit2, matches, affiliateid
+ regex = pcre.new(re, 0, "C")
+ limit, limit2, matches = regex:match(body)
+ if limit ~= nil then
+ affiliateid = matches["id"]
+ result = result .. "\n " .. name .. ": " .. affiliateid
+ end
+ end
+
+ if result ~= "" then
+ return result
+ end
+end
diff --git a/scripts/script.db b/scripts/script.db
index 86c74ede8..d1a76661a 100644
--- a/scripts/script.db
+++ b/scripts/script.db
@@ -50,6 +50,7 @@ Entry { filename = "giop-info.nse", categories = { "discovery", "safe", } }
Entry { filename = "gopher-ls.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "hddtemp-info.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "hostmap.nse", categories = { "discovery", "external", "intrusive", } }
+Entry { filename = "http-affiliate-id.nse", categories = { "discovery", "safe", } }
Entry { filename = "http-auth.nse", categories = { "auth", "default", "intrusive", } }
Entry { filename = "http-brute.nse", categories = { "auth", "intrusive", } }
Entry { filename = "http-date.nse", categories = { "discovery", "safe", } }