mirror of
https://github.com/nmap/nmap.git
synced 2026-01-19 12:49:02 +00:00
[NSE] Modified NSE script ssl-cert.nse to support TLS negotiation
against SMTP ports that support it. Depends on Patrick's addition the of the reconnect_ssl method. [Tom Sellers, David]
This commit is contained in:
11
CHANGELOG
11
CHANGELOG
@@ -1,5 +1,16 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [NSE] Modified NSE script ssl-cert.nse to support TLS negotiation
|
||||
against SMTP ports that support it. Depends on Patrick's addition
|
||||
of the reconnect_ssl method. [Tom Sellers, David]
|
||||
|
||||
o [NSE] Added the reconnect_ssl method for sockets. We sometimes need
|
||||
to reconnect a socket with SSL because the initial communication on
|
||||
the socket is done without SSL. See this thread [1] for more details.
|
||||
[Patrick, Tom Sellers]
|
||||
|
||||
[1] http://seclists.org/nmap-dev/2009/q4/3
|
||||
|
||||
o [Zenmap] Fixed a crash that could occur when entering certain
|
||||
characters in the target entry (those whose UTF-8 encoding contains
|
||||
a byte that counts as whitespace in the Windows locale):
|
||||
|
||||
@@ -71,24 +71,38 @@ require("stdnse")
|
||||
local stringify_name
|
||||
local date_to_string
|
||||
local table_find
|
||||
local s
|
||||
|
||||
local LIKELY_SSL_PORTS = { 443, 465, 989, 990, 992, 993, 994, 995, 587, 8443 }
|
||||
local STARTTLS_PORTS = { 25, 587 }
|
||||
|
||||
portrule = function(host, port)
|
||||
return port.version.service_tunnel == "ssl"
|
||||
or table_find(LIKELY_SSL_PORTS, port.number)
|
||||
or table_find(LIKELY_SSL_PORTS, port.number) or table_find(STARTTLS_PORTS, port.number)
|
||||
end
|
||||
|
||||
action = function(host, port)
|
||||
local s = nmap.new_socket()
|
||||
local status, error = s:connect(host.ip, port.number, "ssl")
|
||||
if not status then
|
||||
if nmap.verbosity() > 0 then
|
||||
return error
|
||||
else
|
||||
s = nmap.new_socket()
|
||||
|
||||
if table_find(STARTTLS_PORTS, port.number) then
|
||||
local status = starttls_negotiate(host,port)
|
||||
|
||||
if not status then
|
||||
return nil
|
||||
end
|
||||
end
|
||||
else
|
||||
local status, error = s:connect(host.ip, port.number, "ssl")
|
||||
|
||||
if not status then
|
||||
if nmap.verbosity() > 0 then
|
||||
return error
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local cert = s:get_ssl_certificate()
|
||||
s:close()
|
||||
|
||||
@@ -166,3 +180,67 @@ function date_to_string(date)
|
||||
return os.date("%Y-%m-%d %H:%M:%S", os.time(date))
|
||||
end
|
||||
end
|
||||
|
||||
function starttls_negotiate(host, port)
|
||||
-- Attempt to negotiate TLS over SMTP for services that support it
|
||||
-- Works for SMTP (25) and SMTP Submission (587)
|
||||
|
||||
-- Open a standard TCP socket
|
||||
local status, error = s:connect(host.ip, port.number, "tcp")
|
||||
|
||||
if not status then
|
||||
return nil
|
||||
else
|
||||
|
||||
-- Loop until the service presents a banner to deal with server
|
||||
-- load and timing issues. There may be a better way to handle this.
|
||||
local i = 0
|
||||
repeat
|
||||
status, resultEHLO = s:receive_lines(1)
|
||||
i = i + 1
|
||||
until string.match(resultEHLO, "^220") or i == 5
|
||||
|
||||
-- Send EHLO because the the server expects it
|
||||
-- We are not going to check for STARTTLS in the capabilities
|
||||
-- list, sometimes it is not advertised.
|
||||
local query = "EHLO example.org\r\n"
|
||||
status = s:send(query)
|
||||
status, resultEHLO = s:receive_lines(1)
|
||||
|
||||
if not (string.match(resultEHLO, "^250")) then
|
||||
stdnse.print_debug("1","%s",resultEHLO)
|
||||
stdnse.print_debug("1","EHLO with errors or timeout. Enable --script-trace to see what is happening.")
|
||||
return nil
|
||||
end
|
||||
|
||||
resultEHLO = ""
|
||||
|
||||
-- Send STARTTLS command ask the service to start encryption
|
||||
local query = "STARTTLS\r\n"
|
||||
status = s:send(query)
|
||||
status, resultEHLO = s:receive_lines(1)
|
||||
|
||||
if not (string.match(resultEHLO, "^220")) then
|
||||
stdnse.print_debug("1","%s",resultEHLO)
|
||||
stdnse.print_debug("1","STARTTLS failed or unavailable. Enable --script-trace to see what is happening.")
|
||||
|
||||
-- Send QUIT to clean up server side connection
|
||||
local query = "QUIT\r\n"
|
||||
status = s:send(query)
|
||||
resultEHLO = ""
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Service supports STARTTLS, tell NSE start SSL negotiation
|
||||
status, error = s:reconnect_ssl()
|
||||
if not status then
|
||||
stdnse.print_debug("1","Could not establish SSL session after STARTTLS command.")
|
||||
s:close()
|
||||
return nil
|
||||
end
|
||||
|
||||
end
|
||||
-- Should have a solid TLS over SMTP session now...
|
||||
return "Connected"
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user