Index: nselib/ike.lua =================================================================== --- nselib/ike.lua (revision 30907) +++ nselib/ike.lua (working copy) @@ -36,7 +36,7 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -local enc_methods = { +ENC_METHODS = { ["des"] = 0x80010001, ["3des"] = 0x80010005, ["aes/128"]= { 0x80010007, 0x800E0080 }, @@ -44,24 +44,55 @@ ["aes/256"]= { 0x80010007, 0x800E0100 } } +AUTH_TYPES = { + ["psk"] = 0x80030001, + ["rsa"] = 0x80030003, + ["Hybrid"] = 0x8003FADD, + ["XAUTH"] = 0x8003FDE9 +} -local authentication= { ["psk"] = 0x80030001, ["rsa"] = 0x80030003, ["Hybrid"] = 0x8003FADD, ["XAUTH"] = 0x8003FDE9} +GROUP_DESCRIPTION = { + ["768"] = 0x80040001, + ["1024"] = 0x80040002, + ["1536"] = 0x80040005 +} -local hash_algo = { ["md5"] = 0x80020001, ["sha1"] = 0x80020002} -local group_desc = { ["768"] = 0x80040001, ["1024"] = 0x80040002, ["1536"]= 0x80040005} -local exchange_mode = { ["Main"] = 0x02, ["Aggressive"]= 0x04} -local protocol_ids = { ["tcp"] = "06", ["udp"]= "11"} +EXCHANGE_MODE = { + ["Main"] = 0x02, + ["Aggressive"] = 0x04 +} +HASH_ALGORITHM = { + ["md5"] = 0x80020001, + ["sha1"] = 0x80020002 +} --- Response packet types -local response_exchange_type = { +PROTOCOL_IDS = { + ["tcp"] = "06", + ["udp"] = "11" +} + +EXCHANGE_TYPE = { ["02"] = "Main", ["04"] = "Aggressive", ["05"] = "Informational" } --- Payload names -local payloads = { +ID_TYPES = { + ["01"] = "ID_IPV4_ADDR", + ["02"] = "ID_FQDN", + ["03"] = "ID_USER_FQDN", + ["04"] = "ID_IPV4_ADDR_SUBNET", + ["05"] = "ID_IPV6_ADDR", + ["06"] = "ID_IPV6_ADDR_SUBNET", + ["07"] = "ID_IPV4_ADDR_RANGE", + ["08"] = "ID_IPV6_ADDR_RANGE", + ["09"] = "ID_DER_ASN1_DN", + ["0A"] = "ID_DER_ASN1_GN", + ["0B"] = "ID_KEY_ID" +} + +PAYLOADS = { ["00"] = "None", ["01"] = "SA", ["03"] = "Transform", @@ -125,7 +156,6 @@ -- local function convert_to_hex(id) local hex_str = "" - for c in string.gmatch(id, ".") do hex_str = hex_str .. string.format("%X", c:byte()) end @@ -133,6 +163,44 @@ end +-- convert a hex string to ascii +-- +local function convert_to_str(hex_str) + local str = "" + for c in string.gmatch(hex_str, "..") do + str = str .. string.char("0x" .. c) + end + return str +end + + +function parse_id_type(id_payload) + + -- get id type + local id_type = id_payload:sub(0, 2) + + -- remove the rest of the payload headers + id_payload = id_payload:sub(9, #id_payload) + + local is_ipv4 = (id_type == "01" or id_type == "04" or id_type == "07") + local is_string = (id_type == "02" or id_type == "03") + + if is_ipv4 then + -- convert hex to readable IP address + local a = tonumber(id_payload:sub(1,2), 16) + local b = tonumber(id_payload:sub(3,4), 16) + local c = tonumber(id_payload:sub(5,6), 16) + local d = tonumber(id_payload:sub(7,8), 16) + return {['type'] = ID_TYPES[id_type], ['value'] = a .. '.' .. b .. '.' .. c .. '.' .. d } + elseif is_string then + return {["type"] = ID_TYPES[id_type], ["value"] = convert_to_str(id_payload) } + else + return {["type"] = ID_TYPES[id_type], ["value"] = ''} + end +end + + + -- Extract Payloads local function extract_payloads(packet) @@ -145,22 +213,22 @@ local payload = '' -- loop over packet - while payloads[np] ~= "None" and index <= packet:len() do + while PAYLOADS[np] ~= "None" and index <= packet:len() do local payload_length = tonumber("0x"..packet:sub(index, index+3)) * 2 payload = string.lower(packet:sub(index+4, index+payload_length-5)) -- debug - if payloads[np] == 'VID' then - stdnse.print_debug(2, 'IKE: Found IKE Header: %s: %s - %s', np, payloads[np], payload) + if PAYLOADS[np] == 'VID' then + stdnse.print_debug(2, 'IKE: Found IKE Header: %s: %s - %s', np, PAYLOADS[np], payload) else - stdnse.print_debug(2, 'IKE: Found IKE Header: %s: %s', np, payloads[np]) + stdnse.print_debug(2, 'IKE: Found IKE Header: %s: %s', np, PAYLOADS[np]) end -- Store payload - if ike_headers[payloads[np]] == nil then - ike_headers[payloads[np]] = {payload} + if ike_headers[PAYLOADS[np]] == nil then + ike_headers[PAYLOADS[np]] = {payload} else - table.insert(ike_headers[payloads[np]], payload) + table.insert(ike_headers[PAYLOADS[np]], payload) end -- find the next payload type @@ -197,6 +265,7 @@ local info = { vendor = nil, attribs = {}, + matches = {} } local status, fingerprints @@ -214,23 +283,22 @@ -- if a match is found, check if it's a version detection or attribute if row.category == 'vendor' then + local debug_string = '' + if row.vendor ~= nil then debug_string = debug_string .. row.vendor .. ' ' end + if row.version ~= nil then debug_string = debug_string .. row.version end + stdnse.print_debug(2, "IKE: Fingerprint: %s matches %s", vendor_id, debug_string) + table.insert(info.matches, { ['vid'] = vendor_id, ['match'] = debug_string} ) -- Only store the first match if info.vendor == nil then - -- the fingerprint contains information about the VID info.vendor = row + end - local debug_string = '' - if row.vendor ~= nil then debug_string = debug_string .. row.vendor .. ' ' end - if row.version ~= nil then debug_string = debug_string .. row.version end - - stdnse.print_debug(2, "IKE: Fingerprint: %s matches %s", vendor_id, debug_string) - end - elseif row.category == 'attribute' then info.attribs[ #info.attribs + 1] = row stdnse.print_debug(2, "IKE: Attribute: %s matches %s", vendor_id, row.text) + table.insert(info.matches, { ['vid'] = vendor_id, ['match'] = row.text} ) break end end @@ -304,7 +372,7 @@ if packet:len() > 38 then -- extract the return type - local resp_type = response_exchange_type[packet:sub(37,38)] + local resp_type = EXCHANGE_TYPE[packet:sub(37,38)] local ike_headers = {} -- simple check that the type is something other than 'Informational' @@ -320,6 +388,9 @@ -- search for fingerprints resp["info"] = lookup(resp['vids']) + -- add the complete ike response + resp['response'] = ike_headers + -- indicate that a packet 'useful' packet was returned resp['success'] = true end @@ -368,7 +439,7 @@ -- local function generate_aggressive(port, protocol, id, diffie) local hex_port = string.format("%.4X", port) - local hex_prot = protocol_ids[protocol] + local hex_prot = PROTOCOL_IDS[protocol] local id_len = string.format("%.4X", 8 + id:len()) -- get length of key data based on diffie @@ -413,11 +484,11 @@ -- handle special case of aes if encryption:sub(1,3) == "aes" then trans_length = 0x0028 - enc = enc_methods[encryption][1] - key_length = enc_methods[encryption][2] + enc = ENC_METHODS[encryption][1] + key_length = ENC_METHODS[encryption][2] else trans_length = 0x0024 - enc = enc_methods[encryption] + enc = ENC_METHODS[encryption] key_length = nil end @@ -438,9 +509,9 @@ 0x01 , -- Transform ID (IKE) 0x0000 , -- spacers ? enc , -- Encryption algorithm - hash_algo[hash] , -- Hash algorithm - authentication[auth], -- Authentication method - group_desc[group] -- Group Description + HASH_ALGORITHM[hash], -- Hash algorithm + AUTH_TYPES[auth] ,-- Authentication method + GROUP_DESCRIPTION[group] -- Group Description ) if key_length ~= nil then @@ -502,7 +573,7 @@ 0x0000000000000000 , -- Responder cookie 0x01 , -- Next payload (SA) 0x10 , -- Version - exchange_mode[mode] , -- Exchange type + EXCHANGE_MODE[mode] , -- Exchange type 0x00 , -- Flags 0x00000000 , -- Message id l , -- packet length