mirror of
https://github.com/nmap/nmap.git
synced 2025-12-17 21:19:01 +00:00
Merged http-slowloris-check
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o [NSE] Added http-slowloris-check script which checks if the server is vulnerable
|
||||||
|
to a Slowloris DoS attack in a safe way. [Aleksandar Nikolic]
|
||||||
|
|
||||||
o Removed pos_scan scan engine as the old implementation of RPC grind was the
|
o Removed pos_scan scan engine as the old implementation of RPC grind was the
|
||||||
last scan type to use it. [Hani Benhabiles]
|
last scan type to use it. [Hani Benhabiles]
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ _ENV = stdnse.module("http", stdnse.seeall)
|
|||||||
---Use ssl if we have it
|
---Use ssl if we have it
|
||||||
local have_ssl, openssl = pcall(require,'openssl')
|
local have_ssl, openssl = pcall(require,'openssl')
|
||||||
|
|
||||||
local USER_AGENT = stdnse.get_script_args('http.useragent') or "Mozilla/5.0 (compatible; Nmap Scripting Engine; http://nmap.org/book/nse.html)"
|
USER_AGENT = stdnse.get_script_args('http.useragent') or "Mozilla/5.0 (compatible; Nmap Scripting Engine; http://nmap.org/book/nse.html)"
|
||||||
local MAX_REDIRECT_COUNT = 5
|
local MAX_REDIRECT_COUNT = 5
|
||||||
|
|
||||||
-- Recursively copy a table.
|
-- Recursively copy a table.
|
||||||
|
|||||||
147
scripts/http-slowloris-check.nse
Normal file
147
scripts/http-slowloris-check.nse
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
local coroutine = require "coroutine"
|
||||||
|
local math = require "math"
|
||||||
|
local nmap = require "nmap"
|
||||||
|
local shortport = require "shortport"
|
||||||
|
local stdnse = require "stdnse"
|
||||||
|
local comm = require "comm"
|
||||||
|
local vulns = require "vulns"
|
||||||
|
local http = require "http"
|
||||||
|
|
||||||
|
|
||||||
|
description = [[
|
||||||
|
Tests a web server for vulnerability to the Slowloris DoS attack.
|
||||||
|
|
||||||
|
Slowloris was described at Defcon 17 by RSnake
|
||||||
|
(see http://ha.ckers.org/slowloris/).
|
||||||
|
|
||||||
|
This script opens two connections to the server, each without
|
||||||
|
the final CRLF. After 10 seconds, second connection sends
|
||||||
|
additional header. Both connections then wait for server timeout.
|
||||||
|
If second connection gets a timeout 10 or more seconds after the
|
||||||
|
first one, we can conclude that sending additional header prolonged
|
||||||
|
it's timeout and that the server is vulnerable to slowloris DoS attack.
|
||||||
|
|
||||||
|
You can specify custom http User-agent field with <code>http.useragent</code>
|
||||||
|
script argument.
|
||||||
|
|
||||||
|
Idea from Qualys blogpost:
|
||||||
|
* https://community.qualys.com/blogs/securitylabs/2011/07/07/identifying-slow-http-attack-vulnerabilities-on-web-applications
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap --script http-slowloris-check <target>
|
||||||
|
--
|
||||||
|
-- @args http.useragent Specifies custom user agent string.
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- PORT STATE SERVICE REASON
|
||||||
|
-- 80/tcp open http syn-ack
|
||||||
|
-- | http-slowloris-check:
|
||||||
|
-- | VULNERABLE:
|
||||||
|
-- | Slowloris DOS attack
|
||||||
|
-- | State: VULNERABLE
|
||||||
|
-- | Description:
|
||||||
|
-- | Slowloris tries to keep many connections to the target web server open and hold them open as long as possible.
|
||||||
|
-- | It accomplishes this by opening connections to the target web server and sending a partial request. By doing
|
||||||
|
-- | so, it starves the http server's resources causing Denial Of Service.
|
||||||
|
-- |
|
||||||
|
-- | Disclosure date: 2009-09-17
|
||||||
|
-- | References:
|
||||||
|
-- |_ http://ha.ckers.org/slowloris/
|
||||||
|
|
||||||
|
author = "Aleksandar Nikolic"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {"vuln", "safe"}
|
||||||
|
|
||||||
|
|
||||||
|
portrule = shortport.http
|
||||||
|
|
||||||
|
local HalfHTTP
|
||||||
|
local Bestopt
|
||||||
|
local TimeWithout -- time without additional headers
|
||||||
|
local TimeWith -- time with additional headers
|
||||||
|
|
||||||
|
-- does a half http request and waits until timeout
|
||||||
|
local function slowThread1(host,port)
|
||||||
|
local socket,status
|
||||||
|
local catch = function()
|
||||||
|
TimeWithout = nmap.clock()
|
||||||
|
end
|
||||||
|
local try = nmap.new_try(catch)
|
||||||
|
socket = nmap.new_socket()
|
||||||
|
socket:set_timeout(500 * 1000)
|
||||||
|
socket:connect(host.ip, port, Bestopt)
|
||||||
|
socket:send(HalfHTTP)
|
||||||
|
try(socket:receive())
|
||||||
|
TimeWithout = nmap.clock()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- does a half http request but sends another
|
||||||
|
-- header value after 10 seconds
|
||||||
|
local function slowThread2(host,port)
|
||||||
|
local socket,status
|
||||||
|
local catch = function()
|
||||||
|
-- note the time the socket timedout
|
||||||
|
TimeWith = nmap.clock()
|
||||||
|
stdnse.print_debug("2 try")
|
||||||
|
end
|
||||||
|
local try = nmap.new_try(catch)
|
||||||
|
socket = nmap.new_socket()
|
||||||
|
socket:set_timeout(500 * 1000)
|
||||||
|
socket:connect(host.ip, port, Bestopt)
|
||||||
|
socket:send(HalfHTTP)
|
||||||
|
stdnse.sleep(10)
|
||||||
|
socket:send("X-a: b\r\n")
|
||||||
|
try(socket:receive())
|
||||||
|
TimeWith = nmap.clock()
|
||||||
|
end
|
||||||
|
|
||||||
|
action = function(host,port)
|
||||||
|
|
||||||
|
local slowloris = {
|
||||||
|
title = "Slowloris DOS attack",
|
||||||
|
description = [[
|
||||||
|
Slowloris tries to keep many connections to the target web server open and hold them open as long as possible.
|
||||||
|
It accomplishes this by opening connections to the target web server and sending a partial request. By doing
|
||||||
|
so, it starves the http server's resources causing Denial Of Service.
|
||||||
|
]],
|
||||||
|
references = {
|
||||||
|
'http://ha.ckers.org/slowloris/',
|
||||||
|
},
|
||||||
|
dates = {
|
||||||
|
disclosure = {year = '2009', month = '09', day = '17'},
|
||||||
|
},
|
||||||
|
exploit_results = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
local report = vulns.Report:new(SCRIPT_NAME, host, port)
|
||||||
|
slowloris.state = vulns.STATE.NOT_VULN
|
||||||
|
|
||||||
|
_, _, Bestopt = comm.tryssl(host, port, "GET / \r\n\r\n", {}) -- first determine if we need ssl
|
||||||
|
HalfHTTP = "POST /" .. tostring(math.random(100000, 900000)) .. " HTTP/1.1\r\n" ..
|
||||||
|
"Host: " .. host.ip .. "\r\n" ..
|
||||||
|
"User-Agent: " .. http.USER_AGENT .. "\r\n; " ..
|
||||||
|
"Content-Length: 42\r\n"
|
||||||
|
-- both threads run at the same time
|
||||||
|
local thread1 = stdnse.new_thread(slowThread1, host, port)
|
||||||
|
local thread2 = stdnse.new_thread(slowThread2, host, port)
|
||||||
|
while true do -- wait for both threads to die
|
||||||
|
if coroutine.status(thread1) == "dead" and coroutine.status(thread2) == "dead" then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
stdnse.sleep(1)
|
||||||
|
end
|
||||||
|
-- compare times
|
||||||
|
local diff = TimeWith - TimeWithout
|
||||||
|
stdnse.print_debug("Time difference is: %d",diff)
|
||||||
|
-- if second connection died 10 or more seconds after the first
|
||||||
|
-- it means that sending additional data prolonged the connection's time
|
||||||
|
-- and the server is vulnerable to slowloris attack
|
||||||
|
if diff >= 10 then
|
||||||
|
stdnse.print_debug("Difference is greater or equal to 10 seconds.")
|
||||||
|
slowloris.state = vulns.STATE.VULN
|
||||||
|
end
|
||||||
|
return report:make_output(slowloris)
|
||||||
|
end
|
||||||
@@ -30,8 +30,8 @@ Entry { filename = "broadcast-dhcp-discover.nse", categories = { "broadcast", "s
|
|||||||
Entry { filename = "broadcast-dhcp6-discover.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-dhcp6-discover.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-dns-service-discovery.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-dns-service-discovery.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-dropbox-listener.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-dropbox-listener.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-eigrp-discovery.nse", categories = { "discovery", "broadcast", "safe", } }
|
Entry { filename = "broadcast-eigrp-discovery.nse", categories = { "broadcast", "discovery", "safe", } }
|
||||||
Entry { filename = "broadcast-igmp-discovery.nse", categories = { "discovery", "safe", "broadcast", } }
|
Entry { filename = "broadcast-igmp-discovery.nse", categories = { "broadcast", "discovery", "safe", } }
|
||||||
Entry { filename = "broadcast-listener.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-listener.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-ms-sql-discover.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-ms-sql-discover.nse", categories = { "broadcast", "safe", } }
|
||||||
Entry { filename = "broadcast-netbios-master-browser.nse", categories = { "broadcast", "safe", } }
|
Entry { filename = "broadcast-netbios-master-browser.nse", categories = { "broadcast", "safe", } }
|
||||||
@@ -180,6 +180,7 @@ Entry { filename = "http-robots.txt.nse", categories = { "default", "discovery",
|
|||||||
Entry { filename = "http-robtex-reverse-ip.nse", categories = { "discovery", "external", "safe", } }
|
Entry { filename = "http-robtex-reverse-ip.nse", categories = { "discovery", "external", "safe", } }
|
||||||
Entry { filename = "http-robtex-shared-ns.nse", categories = { "discovery", "external", "safe", } }
|
Entry { filename = "http-robtex-shared-ns.nse", categories = { "discovery", "external", "safe", } }
|
||||||
Entry { filename = "http-sitemap-generator.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "http-sitemap-generator.nse", categories = { "discovery", "intrusive", } }
|
||||||
|
Entry { filename = "http-slowloris-check.nse", categories = { "safe", "vuln", } }
|
||||||
Entry { filename = "http-slowloris.nse", categories = { "dos", "intrusive", } }
|
Entry { filename = "http-slowloris.nse", categories = { "dos", "intrusive", } }
|
||||||
Entry { filename = "http-sql-injection.nse", categories = { "intrusive", "vuln", } }
|
Entry { filename = "http-sql-injection.nse", categories = { "intrusive", "vuln", } }
|
||||||
Entry { filename = "http-title.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "http-title.nse", categories = { "default", "discovery", "safe", } }
|
||||||
@@ -251,8 +252,8 @@ Entry { filename = "modbus-discover.nse", categories = { "discovery", "intrusive
|
|||||||
Entry { filename = "mongodb-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "mongodb-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } }
|
||||||
Entry { filename = "mongodb-info.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "mongodb-info.nse", categories = { "default", "discovery", "safe", } }
|
||||||
Entry { filename = "mrinfo.nse", categories = { "discovery", "safe", "broadcast"} }
|
Entry { filename = "mrinfo.nse", categories = { "broadcast", "discovery", "safe", } }
|
||||||
Entry { filename = "mtrace.nse", categories = { "discovery", "safe", "broadcast"} }
|
|
||||||
Entry { filename = "ms-sql-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "ms-sql-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
Entry { filename = "ms-sql-config.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "ms-sql-config.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "ms-sql-dac.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "ms-sql-dac.nse", categories = { "discovery", "safe", } }
|
||||||
@@ -263,6 +264,7 @@ Entry { filename = "ms-sql-info.nse", categories = { "default", "discovery", "sa
|
|||||||
Entry { filename = "ms-sql-query.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "ms-sql-query.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "ms-sql-tables.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "ms-sql-tables.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "ms-sql-xp-cmdshell.nse", categories = { "intrusive", } }
|
Entry { filename = "ms-sql-xp-cmdshell.nse", categories = { "intrusive", } }
|
||||||
|
Entry { filename = "mtrace.nse", categories = { "broadcast", "discovery", "safe", } }
|
||||||
Entry { filename = "mysql-audit.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "mysql-audit.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "mysql-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "mysql-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
Entry { filename = "mysql-databases.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "mysql-databases.nse", categories = { "discovery", "intrusive", } }
|
||||||
|
|||||||
Reference in New Issue
Block a user