-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathhttp-slowloris-check.nse
141 lines (125 loc) · 4.6 KB
/
http-slowloris-check.nse
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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"
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.
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>
--
--
-- @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: Mozilla/5.0 (compatible; Nmap Scripting Engine; http://nmap.org/book/nse.html)\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