1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-07 13:11:28 +00:00

Support fragmented TLS records. Closes #194

This commit is contained in:
dmiller
2015-10-29 22:18:32 +00:00
parent b376b889bf
commit bbee119188
3 changed files with 42 additions and 10 deletions

View File

@@ -1,5 +1,8 @@
# Nmap Changelog ($Id$); -*-text-*- # Nmap Changelog ($Id$); -*-text-*-
o [NSE] [GH#194] Add support for reading fragmented TLS messages to
ssl-enum-ciphers. [Jacob Gajek]
o [Ncat] [GH#193] Fix Ncat listen mode over Unix sockets (named pipes) on OS X. o [Ncat] [GH#193] Fix Ncat listen mode over Unix sockets (named pipes) on OS X.
This was crashing with the error: This was crashing with the error:
Ncat: getnameinfo failed: Undefined error: 0 QUITTING. Ncat: getnameinfo failed: Undefined error: 0 QUITTING.

View File

@@ -1108,12 +1108,14 @@ end
--- ---
-- Read a SSL/TLS record -- Read a SSL/TLS record
-- @param buffer The read buffer -- @param buffer The read buffer
-- @param i The position in the buffer to start reading -- @param i The position in the buffer to start reading
-- @param fragment Message fragment left over from previous record (nil if none)
-- @return The current position in the buffer -- @return The current position in the buffer
-- @return The record that was read, as a table -- @return The record that was read, as a table
function record_read(buffer, i) function record_read(buffer, i, fragment)
local b, h, len local b, h, len
local add = 0
------------ ------------
-- Header -- -- Header --
@@ -1148,6 +1150,14 @@ function record_read(buffer, i)
return i, nil return i, nil
end end
-- Adjust buffer and length to account for message fragment left over
-- from last record.
if fragment then
add = #fragment
len = len + add
buffer = buffer:sub(1, j - 1) .. fragment .. buffer:sub(j, -1)
end
-- Convert to human-readable form. -- Convert to human-readable form.
---------- ----------
@@ -1155,12 +1165,11 @@ function record_read(buffer, i)
---------- ----------
h["body"] = {} h["body"] = {}
while j < len do
while j <= len do
-- RFC 2246, 6.2.1 "multiple client messages of the same ContentType may -- RFC 2246, 6.2.1 "multiple client messages of the same ContentType may
-- be coalesced into a single TLSPlaintext record" -- be coalesced into a single TLSPlaintext record"
-- TODO: implement reading of fragmented records
b = {} b = {}
table.insert(h["body"], b)
if h["type"] == "alert" then if h["type"] == "alert" then
-- Parse body. -- Parse body.
j, b["level"] = bin.unpack("C", buffer, j) j, b["level"] = bin.unpack("C", buffer, j)
@@ -1169,7 +1178,16 @@ function record_read(buffer, i)
-- Convert to human-readable form. -- Convert to human-readable form.
b["level"] = find_key(TLS_ALERT_LEVELS, b["level"]) b["level"] = find_key(TLS_ALERT_LEVELS, b["level"])
b["description"] = find_key(TLS_ALERT_REGISTRY, b["description"]) b["description"] = find_key(TLS_ALERT_REGISTRY, b["description"])
table.insert(h["body"], b)
elseif h["type"] == "handshake" then elseif h["type"] == "handshake" then
-- Check for message fragmentation.
if len - j < 3 then
h.fragment = buffer:sub(j, len)
return len + 1 - add, h
end
-- Parse body. -- Parse body.
j, b["type"] = bin.unpack("C", buffer, j) j, b["type"] = bin.unpack("C", buffer, j)
local msg_end local msg_end
@@ -1179,6 +1197,12 @@ function record_read(buffer, i)
-- Convert to human-readable form. -- Convert to human-readable form.
b["type"] = find_key(TLS_HANDSHAKETYPE_REGISTRY, b["type"]) b["type"] = find_key(TLS_HANDSHAKETYPE_REGISTRY, b["type"])
-- Check for message fragmentation.
if msg_end > len + 1 then
h.fragment = buffer:sub(j - 4, len)
return len + 1 - add, h
end
if b["type"] == "server_hello" then if b["type"] == "server_hello" then
-- Parse body. -- Parse body.
j, b["protocol"] = bin.unpack(">S", buffer, j) j, b["protocol"] = bin.unpack(">S", buffer, j)
@@ -1226,18 +1250,21 @@ function record_read(buffer, i)
stdnse.debug2("Unknown handshake message type: %s", b["type"]) stdnse.debug2("Unknown handshake message type: %s", b["type"])
j, b["data"] = bin.unpack("A" .. msg_end - j, buffer, j) j, b["data"] = bin.unpack("A" .. msg_end - j, buffer, j)
end end
table.insert(h["body"], b)
elseif h["type"] == "heartbeat" then elseif h["type"] == "heartbeat" then
j, b["type"], b["payload_length"] = bin.unpack("C>S", buffer, j) j, b["type"], b["payload_length"] = bin.unpack("C>S", buffer, j)
j, b["payload"], b["padding"] = bin.unpack("PP", buffer, j) j, b["payload"], b["padding"] = bin.unpack("PP", buffer, j)
table.insert(h["body"], b)
else else
stdnse.debug1("Unknown message type: %s", h["type"]) stdnse.debug1("Unknown message type: %s", h["type"])
end end
end end
-- Ignore unparsed bytes. -- Ignore unparsed bytes.
j = len+1 j = len + 1
return j, h return j - add, h
end end
--- ---

View File

@@ -149,20 +149,22 @@ end
local function get_record_iter(sock) local function get_record_iter(sock)
local buffer = "" local buffer = ""
local i = 1 local i = 1
local fragment
return function () return function ()
local record local record
i, record = tls.record_read(buffer, i) i, record = tls.record_read(buffer, i, fragment)
if record == nil then if record == nil then
local status, err local status, err
status, buffer, err = tls.record_buffer(sock, buffer, i) status, buffer, err = tls.record_buffer(sock, buffer, i)
if not status then if not status then
return nil, err return nil, err
end end
i, record = tls.record_read(buffer, i) i, record = tls.record_read(buffer, i, fragment)
if record == nil then if record == nil then
return nil, "done" return nil, "done"
end end
end end
fragment = record.fragment
return record return record
end end
end end