mirror of
https://github.com/nmap/nmap.git
synced 2025-12-22 07:29:01 +00:00
Added http-webdav-scan
This commit is contained in:
@@ -52,7 +52,7 @@ o Integrated all of your service/version detection fingerprints submitted from
|
|||||||
telnet, and ftp to jute, bgp, and slurm. Highlights:
|
telnet, and ftp to jute, bgp, and slurm. Highlights:
|
||||||
http://seclists.org/nmap-dev/2015/q2/171 [Daniel Miller]
|
http://seclists.org/nmap-dev/2015/q2/171 [Daniel Miller]
|
||||||
|
|
||||||
o [NSE] Added 25 NSE scripts from 17 authors, bringing the total up to 495.
|
o [NSE] Added 26 NSE scripts from 17 authors, bringing the total up to 495.
|
||||||
They are all listed at http://nmap.org/nsedoc/, and the summaries are below
|
They are all listed at http://nmap.org/nsedoc/, and the summaries are below
|
||||||
(authors are listed in brackets):
|
(authors are listed in brackets):
|
||||||
|
|
||||||
@@ -89,6 +89,8 @@ o [NSE] Added 25 NSE scripts from 17 authors, bringing the total up to 495.
|
|||||||
+ http-vuln-cve2015-1427 detects Elasticsearch servers vulnerable to remote
|
+ http-vuln-cve2015-1427 detects Elasticsearch servers vulnerable to remote
|
||||||
code execution. [Gyanendra Mishra]
|
code execution. [Gyanendra Mishra]
|
||||||
|
|
||||||
|
+ http-webdav-scan detects WebDAV installations. [Gyanendra Mishra]
|
||||||
|
|
||||||
+ http-vuln-cve2015-1635 detects Microsoft Windows systems vulnerable to
|
+ http-vuln-cve2015-1635 detects Microsoft Windows systems vulnerable to
|
||||||
MS15-034. [Paulino Calderon]
|
MS15-034. [Paulino Calderon]
|
||||||
|
|
||||||
|
|||||||
195
scripts/http-webdav-scan.nse
Normal file
195
scripts/http-webdav-scan.nse
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
local http = require "http"
|
||||||
|
local table = require "table"
|
||||||
|
local shortport = require "shortport"
|
||||||
|
local stdnse = require "stdnse"
|
||||||
|
local string = require "string"
|
||||||
|
|
||||||
|
description = [[
|
||||||
|
A script to detect WebDAV installations. Uses the OPTIONS and PROPFIND methods.
|
||||||
|
|
||||||
|
The script sends an OPTIONS request which lists the dav type, server type, date
|
||||||
|
and allowed methods. It then sends a PROPFIND request and tries to fetch exposed
|
||||||
|
directories and internal ip addresses by doing pattern matching in the response body.
|
||||||
|
|
||||||
|
This script takes inspiration from the various scripts listed here:
|
||||||
|
*http://carnal0wnage.attackresearch.com/2010/05/more-with-metasploit-and-webdav.html
|
||||||
|
*https://github.com/sussurro/Metasploit-Tools/blob/master/modules/auxiliary/scanner/http/webdav_test.rb
|
||||||
|
*http://code.google.com/p/davtest/
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap --script http-webdav-scan -p80,8080 <target>
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- PORT STATE SERVICE
|
||||||
|
-- 8008/tcp open http
|
||||||
|
-- | http-webdav-scan:
|
||||||
|
-- | Allowed Methods: GET, HEAD, COPY, MOVE, POST, PUT, PROPFIND, PROPPATCH, OPTIONS, MKCOL, DELETE, TRACE, REPORT
|
||||||
|
-- | Server Type: DAV/0.9.8 Python/2.7.6
|
||||||
|
-- | Server Date: Fri, 22 May 2015 19:28:00 GMT
|
||||||
|
-- | WebDAV type: unkown
|
||||||
|
-- | Directory Listing:
|
||||||
|
-- | http://localhosft
|
||||||
|
-- | http://localhost:8008/WebDAVTest_b1tqTWeyRR
|
||||||
|
-- | http://localhost:8008/WebDAVTest_A0QWJb7hcK
|
||||||
|
-- | http://localhost:8008/WebDAVTest_hf9Mqqpi1M
|
||||||
|
-- | http://localhost:8008/WebDAVTest_Ds5KBFywDq
|
||||||
|
--
|
||||||
|
-- @args path The path to start in; eg, <code>"/web/"</code> will try <code>"/web/xxx"</code>.
|
||||||
|
--
|
||||||
|
-- @xmloutput
|
||||||
|
-- <elem key="Allowed Methods">GET, HEAD, COPY, MOVE, POST, PUT,
|
||||||
|
-- PROPFIND, PROPPATCH, OPTIONS, MKCOL, DELETE, TRACE, REPORT</elem>
|
||||||
|
-- <elem key="Server Type">DAV/0.9.8 Python/2.7.6</elem>
|
||||||
|
-- <elem key="Server Date">Fri, 22 May 2015 19:28:00 GMT</elem>
|
||||||
|
-- <elem key="WebDAV type">unkown</elem>
|
||||||
|
-- <table key="Directory Listing">
|
||||||
|
-- <elem>http://localhost</elem>
|
||||||
|
-- <elem>http://localhost:8008/WebDAVTest_b1tqTWeyRR</elem>
|
||||||
|
-- <elem>http://localhost:8008/WebDAVTest_A0QWJb7hcK</elem>
|
||||||
|
-- <elem>http://localhost:8008/WebDAVTest_hf9Mqqpi1M</elem>
|
||||||
|
-- <elem>http://localhost:8008/WebDAVTest_Ds5KBFywDq</elem>
|
||||||
|
-- </table>
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
author = "Gyanendra Mishra"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {
|
||||||
|
"safe",
|
||||||
|
"discovery",
|
||||||
|
"default",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
portrule = shortport.http
|
||||||
|
|
||||||
|
-- a function to test the OPTIONS method.
|
||||||
|
local function get_options (host, port, path)
|
||||||
|
-- check if WebDAV is installed or not.
|
||||||
|
local response = http.generic_request(host, port, "OPTIONS", path)
|
||||||
|
if response and response.status == 200 then
|
||||||
|
local ret = {}
|
||||||
|
ret['Server Type'] = response.header['server']
|
||||||
|
ret['Allowed Methods'] = response.header['allow']
|
||||||
|
ret['Public Options'] = response.header['public']
|
||||||
|
ret['WebDAV'] = false
|
||||||
|
ret['Server Date'] = response.header['date']
|
||||||
|
|
||||||
|
if response.header['dav'] and response.header['dav']:find('1') then
|
||||||
|
ret['WebDAV'] = true
|
||||||
|
ret['WebDAV type'] = 'Unkown'
|
||||||
|
if response.header['X-MSDAVEXT'] then
|
||||||
|
ret['WebDAV type'] = 'SHAREPOINT DAV'
|
||||||
|
end
|
||||||
|
if response.header['dav']:match 'apache' then
|
||||||
|
ret['WebDAV type'] = 'Apache DAV'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function validateIP(matched_ip)
|
||||||
|
local oct_1, oct_2, oct_3, oct_4 = matched_ip:match('(%d%d?%d?)%.(%d%d?%d?)%.(%d%d?%d)%.(%d%d?%d?)')
|
||||||
|
if tonumber(oct_1) > 255 or tonumber(oct_2) > 255 or tonumber(oct_3) > 255 or tonumber(oct_4) > 255 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- a function to extract internal ip addresses from PROPFIND response.
|
||||||
|
local function getIPs(body)
|
||||||
|
local ip_pat1 = '192%.168%.%d+%.%d+'
|
||||||
|
local ip_pat2 = '10%.%d+%.%d+%.%d+'
|
||||||
|
local ip_pat3 = '172%.%d+%.%d+%.%d+'
|
||||||
|
local ip_pats = {
|
||||||
|
ip_pat1,
|
||||||
|
ip_pat2,
|
||||||
|
ip_pat3,
|
||||||
|
}
|
||||||
|
local result = {}
|
||||||
|
for _, ip_pat in pairs(ip_pats) do
|
||||||
|
for ip in body:gmatch(ip_pat) do
|
||||||
|
if validateIP(ip) then
|
||||||
|
result[ip] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return stdnse.keys(result)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- a function to test the PROPFIND method.
|
||||||
|
local function check_propfind (host, port, path)
|
||||||
|
local options = {
|
||||||
|
header = {
|
||||||
|
["Depth"] = 1,
|
||||||
|
["Content-Length"] = 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
local response = http.generic_request(host, port, "PROPFIND", path, options)
|
||||||
|
if response and response.status ~= 207 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local ret = {}
|
||||||
|
ret['WebDAV'] = false
|
||||||
|
local dir_pat = '<.-[hH][rR][eE][fF][^>]->(.-)</.-[hH][rR][eE][fF]>'
|
||||||
|
if response.body:find '<D:status>HTTP/1.1 200 OK</D:status>' then
|
||||||
|
ret['WebDAV'] = true
|
||||||
|
end
|
||||||
|
ret['Server Type'] = response.header['server']
|
||||||
|
ret['Server Date'] = response.header['date']
|
||||||
|
local ips = getIPs(response.body)
|
||||||
|
if next(ips) then ret['Exposed Internal IPs'] = getIPs(response.body) end
|
||||||
|
if response.body:gmatch(dir_pat) then
|
||||||
|
ret['Directory Listing'] = {}
|
||||||
|
for dir in response.body:gmatch(dir_pat) do
|
||||||
|
table.insert(ret['Directory Listing'], dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
function action (host, port)
|
||||||
|
|
||||||
|
local path = stdnse.get_script_args(SCRIPT_NAME .. ".path") or '/'
|
||||||
|
local enabled = false
|
||||||
|
local output = stdnse.output_table()
|
||||||
|
|
||||||
|
local info = get_options(host, port, path)
|
||||||
|
if info then
|
||||||
|
if info['WebDAV'] then
|
||||||
|
enabled = true
|
||||||
|
stdnse.debug1("Target has WebDAV enabled.")
|
||||||
|
for name, data in pairs(info) do
|
||||||
|
if name ~= 'WebDAV' then
|
||||||
|
output[name] = data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
stdnse.debug1 "Target isn't reporting WebDAV"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local davinfo = check_propfind(host, port, path)
|
||||||
|
if davinfo then
|
||||||
|
if davinfo['WebDAV'] then
|
||||||
|
for name, data in pairs(davinfo) do
|
||||||
|
if not output[name] and name ~= 'WebDAV' then
|
||||||
|
output[name] = data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not enabled then
|
||||||
|
stdnse.debug1 "Target has WebDAV enabled."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #output > 0 then return output else return nil end
|
||||||
|
end
|
||||||
|
|
||||||
@@ -242,6 +242,7 @@ Entry { filename = "http-vuln-misfortune-cookie.nse", categories = { "intrusive"
|
|||||||
Entry { filename = "http-vuln-wnr1000-creds.nse", categories = { "exploit", "intrusive", "vuln", } }
|
Entry { filename = "http-vuln-wnr1000-creds.nse", categories = { "exploit", "intrusive", "vuln", } }
|
||||||
Entry { filename = "http-waf-detect.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "http-waf-detect.nse", categories = { "discovery", "intrusive", } }
|
||||||
Entry { filename = "http-waf-fingerprint.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "http-waf-fingerprint.nse", categories = { "discovery", "intrusive", } }
|
||||||
|
Entry { filename = "http-webdav-scan.nse", categories = { "default", "discovery", "safe" } }
|
||||||
Entry { filename = "http-wordpress-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "http-wordpress-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
Entry { filename = "http-wordpress-enum.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "http-wordpress-enum.nse", categories = { "discovery", "intrusive", } }
|
||||||
Entry { filename = "http-wordpress-users.nse", categories = { "auth", "intrusive", "vuln", } }
|
Entry { filename = "http-wordpress-users.nse", categories = { "auth", "intrusive", "vuln", } }
|
||||||
|
|||||||
Reference in New Issue
Block a user