1
0
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:
tomsellers
2009-10-13 01:19:33 +00:00
parent 4dca11125f
commit 3b4fa34257
2 changed files with 97 additions and 8 deletions

View File

@@ -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):

View File

@@ -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