1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 05:01:29 +00:00

Update the SSH protocol flow. Closes #1460

Allows the server to start the key exchange before the protocol version
exchange (banner exchange) is completed
This commit is contained in:
nnposter
2020-09-13 00:12:48 +00:00
parent dd6650b887
commit fa6bd3f901
2 changed files with 14 additions and 17 deletions

View File

@@ -45,6 +45,10 @@ o [GH#2104] Fixed parsing of TCP options which would hang (infinite loop) if an
option had an explicit length of 0. Affects Nmap 7.80 only. option had an explicit length of 0. Affects Nmap 7.80 only.
[Daniel Miller, Imed Mnif] [Daniel Miller, Imed Mnif]
o [NSE][GH#1460] Script ssh2-enum-algos would fail if the server initiated
the key exchange before completing the protocol version exchange
[Scott Ellis, nnposter]
o [NSE][GH#2105] Fetching of SSH2 keys might fail because of key exchange o [NSE][GH#2105] Fetching of SSH2 keys might fail because of key exchange
confusion [nnposter] confusion [nnposter]

View File

@@ -160,18 +160,20 @@ end
action = function(host, port) action = function(host, port)
local sock = nmap.new_socket() local sock = nmap.new_socket()
local status = sock:connect(host, port) local status = sock:connect(host, port)
if not status then if not status then
return return
end end
status = sock:receive_lines(1) -- send the client banner
-- NB: The protocol does not prescribe which side sends the banner first
status = sock:send("SSH-2.0-Nmap_SSH2_Enum_Algos\r\n")
if not status then if not status then
sock:close() sock:close()
return return
end end
status = sock:send("SSH-2.0-Nmap_SSH2_Enum_Algos\r\n") -- slurp the server banner
status = sock:receive_buf("\r?\n", false)
if not status then if not status then
sock:close() sock:close()
return return
@@ -179,26 +181,17 @@ action = function(host, port)
local ssh = ssh2.transport local ssh = ssh2.transport
-- I would think that the server would send its kex data right after -- send the client key exchange
-- receiving and verifying our protocol id string above, then we could -- NB: The protocol does not prescribe which side sends the kex init first
-- just use it here, but I've seen no definitive documentation saying status = sock:send(ssh.build(ssh.kex_init()))
-- that we don't ever send ours first. All I've seen is that if the
-- server doesn't care about compatibility with older clients then it
-- MAY send its kex data after the protocol id string. So I guess I'll
-- send it here until I know for sure (removing this send works against
-- OpenSSH though).
local pkt = ssh.build(ssh.kex_init())
status = sock:send(pkt)
if not status then if not status then
sock:close() sock:close()
return return
end end
local status, response = ssh.receive_packet(sock) local response
status, response = ssh.receive_packet(sock)
sock:close() sock:close()
if not status then if not status then
return return
end end