def setUp(self): meta = {} run_args = argparse.ArgumentParser() run_args.add_argument("--tanner") run_args.add_argument("--page-dir") self.main_page_path = generate_unique_path() os.makedirs(self.main_page_path) self.page_dir = self.main_page_path.rsplit('/')[-1] args = run_args.parse_args(['--page-dir', self.page_dir]) args_dict = vars(args) args_dict['full_page_path'] = self.main_page_path uuid = '9c10172f-7ce2-4fb4-b1c6-abc70141db56'.encode('utf-8') args.tanner = 'tanner.mushmush.org' args.no_dorks = True args.server_header = "test_server" args.slurp_enabled = True self.handler = HttpRequestHandler(meta, args, uuid) self.request_data = { 'method': 'GET', 'path': '/', 'headers': { 'Host': 'test_host', 'Content-Type': 'test_type', }, 'status': 200, 'cookies': { 'sess_uuid': 'prev_test_uuid', }, } self.loop = asyncio.new_event_loop() self.response_content = '<html><body></body></html>' self.response_headers = multidict.CIMultiDict([("Content-Type", "text/html")]) self.response_status = 200 event_result = dict(response=dict(message=dict(detection={'type': 1}, sess_uuid="test_uuid"))) RequestHandler = Mock() protocol = RequestHandler() message = RawRequestMessage( method='POST', path='/', version=HttpVersion(major=1, minor=1), headers=self.request_data['headers'], raw_headers=None, should_close=None, compression=None, upgrade=None, chunked=None, url=URL('http://test_url/') ) self.request = web.Request( message=message, payload=None, protocol=protocol, payload_writer=None, task='POST', loop=self.loop ) self.handler.tanner_handler.create_data = Mock(return_value=self.request_data) self.handler.tanner_handler.submit_data = AsyncMock(return_value=event_result) self.handler.submit_slurp = AsyncMock() web.Response.add_header = Mock() web.Response.write = Mock() web.Response.send_headers = Mock() web.Response.write_eof = AsyncMock() aiohttp.streams.EmptyStreamReader.read = AsyncMock( return_value=b'con1=test1&con2=test2') self.handler.tanner_handler.parse_tanner_response = AsyncMock( return_value=(self.response_content, self.response_headers, self.response_status))
def test_handler_stop(self): self.handler.runner = AsyncMock() async def test(): await self.handler.stop() self.loop.run_until_complete(test())
def test_get_body_css_validate_scheme(self): aiohttp.ClientResponse._headers = {'Content-Type': 'text/css'} self.css_validate = 'true' self.return_size = 0 self.handler = Cloner(self.root, self.max_depth, self.css_validate) self.content = [ b'''.banner { background: url("data://domain/test.txt") }''', b'''.banner { background: url("file://domain/test.txt") }''' ] self.meta = { '/index.html': { 'hash': 'd1546d731a9f30cc80127d57142a482b', 'headers': [{ 'Content-Type': 'text/css' }], }, } self.expected_content = 'http://example.com/' async def test(): await self.handler.new_urls.put((yarl.URL(self.root), 0)) await self.handler.get_body(self.session) self.q_size = self.handler.new_urls.qsize() for content in self.content: aiohttp.ClientResponse.read = AsyncMock(return_value=content) self.loop.run_until_complete(test()) self.assertEqual(self.return_size, self.q_size) self.assertEqual(self.handler.meta, self.meta) self.assertEqual(self.handler.visited_urls[-1], self.expected_content)
def test_get_body_css_validate(self): aiohttp.ClientResponse._headers = {'Content-Type': 'text/css'} self.css_validate = 'true' self.handler = Cloner(self.root, self.max_depth, self.css_validate) self.content = b'''.banner { background: url("/example.png") }''' aiohttp.ClientResponse.read = AsyncMock(return_value=self.content) self.expected_content = 'http://example.com/example.png' self.return_size = 0 self.meta = { '/example.png': { 'hash': '5a64beebcd2a6f1cbd00b8370debaa72', 'headers': [{ 'Content-Type': 'text/css' }], }, '/index.html': { 'hash': 'd1546d731a9f30cc80127d57142a482b', 'headers': [{ 'Content-Type': 'text/css' }], }, } async def test(): await self.handler.new_urls.put((yarl.URL(self.root), 0)) await self.handler.get_body(self.session) self.q_size = self.handler.new_urls.qsize() self.loop.run_until_complete(test()) self.assertEqual(self.handler.visited_urls[-1], self.expected_content) self.assertEqual(self.q_size, self.return_size) self.assertEqual(self.meta, self.handler.meta)
def test_get_body_css_validate_scheme(self): aiohttp.ClientResponse._headers = {"Content-Type": "text/css"} self.css_validate = "true" self.return_size = 0 self.handler = Cloner(self.root, self.max_depth, self.css_validate) self.content = [ b""".banner { background: url("data://domain/test.txt") }""", b""".banner { background: url("file://domain/test.txt") }""", ] self.meta = { "/index.html": { "hash": "d1546d731a9f30cc80127d57142a482b", "headers": [{"Content-Type": "text/css"}], }, } self.expected_content = "http://example.com/" async def test(): await self.handler.new_urls.put((yarl.URL(self.root), 0)) await self.handler.get_body(self.session) self.q_size = self.handler.new_urls.qsize() for content in self.content: aiohttp.ClientResponse.read = AsyncMock(return_value=content) self.loop.run_until_complete(test()) self.assertEqual(self.return_size, self.q_size) self.assertEqual(self.handler.meta, self.meta) self.assertEqual(self.handler.visited_urls[-1], self.expected_content)
def setUp(self): self.main_page_path = generate_unique_path() os.makedirs(self.main_page_path) self.root = "http://example.com" self.level = 0 self.max_depth = sys.maxsize self.loop = asyncio.new_event_loop() self.css_validate = "false" self.handler = Cloner(self.root, self.max_depth, self.css_validate) self.target_path = "/opt/snare/pages/{}".format(yarl.URL(self.root).host) self.return_content = None self.expected_content = None self.filename = None self.hashname = None self.url = None self.content = None self.return_url = None self.return_level = None self.meta = None self.q_size = None self.session = aiohttp.ClientSession self.session.get = AsyncMock( return_value=aiohttp.ClientResponse( url=yarl.URL("http://www.example.com"), method="GET", writer=None, continue100=1, timer=None, request_info=None, traces=None, loop=self.loop, session=None, ) )
def test_get_body_css_validate(self): aiohttp.ClientResponse._headers = {"Content-Type": "text/css"} self.css_validate = "true" self.handler = Cloner(self.root, self.max_depth, self.css_validate) self.content = b""".banner { background: url("/example.png") }""" aiohttp.ClientResponse.read = AsyncMock(return_value=self.content) self.expected_content = "http://example.com/example.png" self.return_size = 0 self.meta = { "/example.png": { "hash": "5a64beebcd2a6f1cbd00b8370debaa72", "headers": [{"Content-Type": "text/css"}], }, "/index.html": { "hash": "d1546d731a9f30cc80127d57142a482b", "headers": [{"Content-Type": "text/css"}], }, } async def test(): await self.handler.new_urls.put((yarl.URL(self.root), 0)) await self.handler.get_body(self.session) self.q_size = self.handler.new_urls.qsize() self.loop.run_until_complete(test()) self.assertEqual(self.handler.visited_urls[-1], self.expected_content) self.assertEqual(self.q_size, self.return_size) self.assertEqual(self.meta, self.handler.meta)
def test_get_body(self): self.content = b'''<html><body><a href="http://example.com/test"></a></body></html>''' aiohttp.ClientResponse._headers = {'Content-Type': 'text/html'} aiohttp.ClientResponse.read = AsyncMock(return_value=self.content) self.filename, self.hashname = self.handler._make_filename( yarl.URL(self.root)) self.expected_content = '<html><body><a href="/test"></a></body></html>' self.meta = { '/index.html': { 'content_type': 'text/html', 'hash': 'd1546d731a9f30cc80127d57142a482b' }, '/test': { 'content_type': 'text/html', 'hash': '4539330648b80f94ef3bf911f6d77ac9' } } async def test(): await self.handler.new_urls.put((yarl.URL(self.root), 0)) await self.handler.get_body(self.session) self.loop.run_until_complete(test()) with open(os.path.join(self.target_path, self.hashname)) as f: self.return_content = f.read() self.assertEqual(self.return_content, self.expected_content) self.assertEqual(self.handler.visited_urls[-2:], ['http://example.com/', 'http://example.com/test']) self.assertEqual(self.handler.meta, self.meta)
def setUp(self): run_args = argparse.ArgumentParser() run_args.add_argument("--tanner") run_args.add_argument("--page-dir") self.main_page_path = generate_unique_path() os.makedirs(self.main_page_path) page_dir = self.main_page_path.rsplit('/')[-1] meta_content = {"/index.html": {"hash": "hash_name", "content_type": "text/html"}} self.page_content = "<html><body></body></html>" self.content_type = "text/html" with open(os.path.join(self.main_page_path, "hash_name"), 'w') as f: f.write(self.page_content) with open(os.path.join(self.main_page_path, "meta.json"), 'w') as f: json.dump(meta_content, f) args = run_args.parse_args(['--page-dir', page_dir]) args.index_page = '/index.html' args.no_dorks = True args.tanner = "tanner.mushmush.org" uuid = "test_uuid" self.handler = TannerHandler(args, meta_content, uuid) self.requested_name = '/' self.loop = asyncio.get_event_loop() self.handler.html_handler.handle_content = AsyncMock(return_value=self.page_content) self.res1 = None self.res2 = None self.res3 = None self.res4 = None self.detection = None self.expected_content = None self.call_content = None
def test_return_dorks_exception(self): aiohttp.ClientResponse.json = AsyncMock(side_effect=Exception()) async def test(): self.data = await self.handler.get_dorks() with self.assertRaises(Exception): self.loop.run_until_complete(test())
def test_event_result_exception(self): aiohttp.ClientResponse.json = AsyncMock(side_effect=Exception()) async def test(): self.result = await self.handler.submit_data(self.data) with self.assertRaises(Exception): self.loop.run_until_complete(test())
def test_return_dorks(self): aiohttp.ClientResponse.json = AsyncMock(return_value=self.dorks) async def test(): self.data = await self.handler.get_dorks() self.loop.run_until_complete(test()) self.assertEqual(self.data, self.dorks['response']['dorks'])
def test_get_dorks(self): aiohttp.ClientResponse.json = AsyncMock(return_value=dict(response={'dorks': "test_dorks"})) async def test(): self.data = await self.handler.get_dorks() self.loop.run_until_complete(test()) aiohttp.ClientSession.get.assert_called_with('http://tanner.mushmush.org:8090/dorks', timeout=10.0)
def test_logging_error(self): aiohttp.ClientResponse.json = AsyncMock(side_effect=JSONDecodeError('ERROR', '', 0)) async def test(): self.data = await self.handler.get_dorks() with self.assertLogs(level='ERROR') as log: self.loop.run_until_complete(test()) self.assertIn('Error getting dorks: ERROR: line 1 column 1 (char 0)', log.output[0])
def test_logging_timeout(self): aiohttp.ClientResponse.json = AsyncMock(side_effect=asyncio.TimeoutError()) async def test(): self.data = await self.handler.get_dorks() with self.assertLogs(level='INFO') as log: self.loop.run_until_complete(test()) self.assertIn('Dorks timeout', log.output[0])
def test_handle_content_exception(self): self.handler.no_dorks = False self.handler.get_dorks = AsyncMock(return_value=[]) async def test(): self.return_content = await self.handler.handle_content( self.content) with self.assertRaises(IndexError): self.loop.run_until_complete(test())
def test_client_error(self): self.session.get = AsyncMock(side_effect=aiohttp.ClientError) async def test(): await self.handler.new_urls.put((yarl.URL(self.root), 0)) await self.handler.get_body(self.session) with self.assertLogs(level="ERROR") as log: self.loop.run_until_complete(test()) self.assertIn("ERROR:snare.cloner:", "".join(log.output))
def test_event_result(self): aiohttp.ClientResponse.json = AsyncMock( return_value=dict(detection={'type': 1}, sess_uuid="test_uuid")) async def test(): self.result = await self.handler.submit_data(self.data) self.loop.run_until_complete(test()) self.assertEqual(self.result, dict(detection={'type': 1}, sess_uuid="test_uuid"))
def test_handle_content(self): self.handler.no_dorks = False self.handler.get_dorks = AsyncMock(return_value=["test_dork1"]) async def test(): self.return_content = await self.handler.handle_content( self.content) self.loop.run_until_complete(test()) soup = BeautifulSoup(self.return_content, "html.parser") return_content = soup.decode("utf-8") self.assertEqual(return_content, self.expected_content)
def test_post_data(self): aiohttp.ClientResponse.json = AsyncMock( return_value=dict(detection={'type': 1}, sess_uuid="test_uuid")) async def test(): self.result = await self.handler.submit_data(self.data) self.loop.run_until_complete(test()) aiohttp.ClientSession.post.assert_called_with( 'http://tanner.mushmush.org:8090/event', data=json.dumps(self.data), timeout=10.0)
def test_submit_data_error(self): aiohttp.ClientResponse.json = AsyncMock( side_effect=JSONDecodeError('ERROR', '', 0)) async def test(): self.result = await self.handler.submit_data(self.data) with self.assertLogs(level='ERROR') as log: self.loop.run_until_complete(test()) self.assertIn( 'Error submitting data: ERROR: line 1 column 1 (char 0) {}'. format(self.data), log.output[0])
def setUp(self): meta = {} run_args = argparse.ArgumentParser() run_args.add_argument("--tanner") run_args.add_argument("--page-dir") self.main_page_path = generate_unique_path() os.makedirs(self.main_page_path) page_dir = self.main_page_path.rsplit("/")[-1] args = run_args.parse_args(["--page-dir", page_dir]) args_dict = vars(args) args_dict["full_page_path"] = self.main_page_path self.loop = asyncio.new_event_loop() self.data = { "method": "GET", "path": "/", "headers": { "Host": "test_host", "Connection": "keep-alive", "Upgrade-Insecure-Requests": "1", "User-Agent": "test_agent", "Accept": "text/html", "Accept-Encoding": "test_encoding", "Accept-Language": "test_lang", "Cookie": "test_cookie", }, "uuid": "test_uuid", "peer": { "ip": "::1", "port": 80 }, "status": 200, "cookies": "test_cookies", "sess_uuid": "test_uuid", } aiohttp.ClientSession.post = AsyncMock( return_value=aiohttp.ClientResponse( url=yarl.URL("http://www.example.com"), method="GET", writer=None, continue100=1, timer=None, request_info=None, traces=None, loop=self.loop, session=None, )) uuid = "test_uuid" args.tanner = "tanner.mushmush.org" args.no_dorks = True self.handler = TannerHandler(args, meta, uuid) self.result = None
def setUp(self): meta = {} run_args = argparse.ArgumentParser() run_args.add_argument("--tanner") run_args.add_argument("--page-location") self.main_page_path = generate_unique_path() os.makedirs(self.main_page_path) page_location = self.main_page_path.rsplit('/')[-1] args = run_args.parse_args(['--page-location', page_location]) args_dict = vars(args) args_dict['full_page_path'] = self.main_page_path self.loop = asyncio.new_event_loop() self.data = { 'method': 'GET', 'path': '/', 'headers': { 'Host': 'test_host', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'test_agent', 'Accept': 'text/html', 'Accept-Encoding': 'test_encoding', 'Accept-Language': 'test_lang', 'Cookie': 'test_cookie' }, 'uuid': 'test_uuid', 'peer': { 'ip': '::1', 'port': 80 }, 'status': 200, 'cookies': 'test_cookies', 'sess_uuid': 'test_uuid' } aiohttp.ClientSession.post = AsyncMock( return_value=aiohttp.ClientResponse(url=yarl.URL( "http://www.example.com"), method="GET", writer=None, continue100=1, timer=None, request_info=None, traces=None, loop=self.loop, session=None)) uuid = "test_uuid" args.tanner = "tanner.mushmush.org" args.no_dorks = True self.handler = TannerHandlerDirectory(args, meta, uuid) self.result = None
def test_replace_image_links(self): self.handler.process_link = AsyncMock(return_value="/smiley.png") self.root = "http://example.com/smiley.png" self.content = '\n<html>\n<body>\n<img src="http://example.com/smiley.png"/>\n</body>\n</html>\n' self.expected_content = '\n<html>\n<body>\n<img src="/smiley.png"/>\n</body>\n</html>\n' async def test(): self.return_content = await self.handler.replace_links( self.content, self.level) self.loop.run_until_complete(test()) self.assertEqual(str(self.return_content), self.expected_content) self.handler.process_link.assert_called_with(self.root, self.level)
def test_replace_action_links(self): self.handler.process_link = AsyncMock(return_value="/submit.php") self.root = "http://example.com/submit.php" self.content = '\n<html>\n<body>\n<form action="http://example.com/submit.php">\n</form>\n</body>\n</html>\n' self.expected_content = '\n<html>\n<body>\n<form action="/submit.php">\n</form>\n</body>\n</html>\n' async def test(): self.return_content = await self.handler.replace_links( self.content, self.level) self.loop.run_until_complete(test()) self.assertEqual(str(self.return_content), self.expected_content) self.handler.process_link.assert_called_with(self.root, self.level)
def test_replace_relative_links(self): self.handler.process_link = AsyncMock(return_value="/test") self.root = "http://example.com/test" self.content = '\n<html>\n<body>\n<a href="http://example.com/test"></a>\n</body>\n</html>\n' self.expected_content = '\n<html>\n<body>\n<a href="/test"></a>\n</body>\n</html>\n' async def test(): self.return_content = await self.handler.replace_links( self.content, self.level) self.loop.run_until_complete(test()) self.assertEqual(str(self.return_content), self.expected_content) self.handler.process_link.assert_called_with(self.root, self.level, check_host=True)
def setUp(self): self.main_page_path = generate_unique_path() os.makedirs(self.main_page_path) self.dorks = dict(response={'dorks': "test_dorks"}) self.loop = asyncio.new_event_loop() aiohttp.ClientSession.get = AsyncMock( return_value=aiohttp.ClientResponse( url=yarl.URL("http://www.example.com"), method="GET", writer=None, continue100=1, timer=None, request_info=None, traces=None, loop=self.loop, session=None ) ) no_dorks = True tanner = "tanner.mushmush.org" self.handler = HtmlHandler(no_dorks, tanner) self.data = None
def setUp(self): run_args = argparse.ArgumentParser() run_args.add_argument("--tanner") run_args.add_argument("--page-location") self.main_page_path = generate_unique_path() os.makedirs(self.main_page_path) page_location = self.main_page_path.rsplit('/')[-1] meta_content = { "/index.html": { "hash": "hash_name", "headers": [{ "Content-Type": "text/html" }] } } self.page_content = "<html><body></body></html>" self.headers = multidict.CIMultiDict([("Content-Type", "text/html")]) self.status_code = 200 self.content_type = "text/html" with open(os.path.join(self.main_page_path, "hash_name"), 'w') as f: f.write(self.page_content) with open(os.path.join(self.main_page_path, "meta.json"), 'w') as f: json.dump(meta_content, f) self.args = run_args.parse_args(['--page-location', page_location]) args_dict = vars(args) args_dict['full_page_path'] = self.main_page_path self.args.index_page = '/index.html' self.args.no_dorks = True self.args.tanner = "tanner.mushmush.org" self.uuid = "test_uuid" self.handler = TannerHandlerDirectory(self.args, meta_content, self.uuid) self.requested_name = '/' self.loop = asyncio.get_event_loop() self.handler.html_handler.handle_content = AsyncMock( return_value=self.page_content) self.res1 = None self.res2 = None self.res3 = None self.detection = None self.expected_content = None self.call_content = None
def test_get_body(self): self.content = b"""<html><body><a href="http://example.com/test"></a></body></html>""" aiohttp.ClientResponse._headers = {"Content-Type": "text/html"} aiohttp.ClientResponse.read = AsyncMock(return_value=self.content) self.filename, self.hashname = self.handler._make_filename(yarl.URL(self.root)) self.expected_content = '<html><body><a href="/test"></a></body></html>' self.meta = { "/index.html": { "hash": "d1546d731a9f30cc80127d57142a482b", "headers": [{"Content-Type": "text/html"}], }, "/test": { "hash": "4539330648b80f94ef3bf911f6d77ac9", "headers": [{"Content-Type": "text/html"}], }, } async def test(): await self.handler.new_urls.put((yarl.URL(self.root), 0)) await self.handler.get_body(self.session) with self.assertLogs(level="DEBUG") as log: self.loop.run_until_complete(test()) self.assertIn("DEBUG:snare.cloner:Cloned file: /test", "".join(log.output)) with open(os.path.join(self.target_path, self.hashname)) as f: self.return_content = f.read() self.assertEqual(self.return_content, self.expected_content) self.assertEqual( self.handler.visited_urls[-2:], ["http://example.com/", "http://example.com/test"], ) self.assertEqual(self.handler.meta, self.meta)
def setUp(self): meta = {} run_args = argparse.ArgumentParser() run_args.add_argument("--tanner") run_args.add_argument("--page-dir") self.main_page_path = generate_unique_path() os.makedirs(self.main_page_path) self.page_dir = self.main_page_path.rsplit("/")[-1] args = run_args.parse_args(["--page-dir", self.page_dir]) args_dict = vars(args) args_dict["full_page_path"] = self.main_page_path uuid = "9c10172f-7ce2-4fb4-b1c6-abc70141db56".encode("utf-8") args.tanner = "tanner.mushmush.org" args.no_dorks = True args.server_header = "test_server" args.slurp_enabled = True self.handler = HttpRequestHandler(meta, args, uuid) self.request_data = { "method": "GET", "path": "/", "headers": { "Host": "test_host", "Content-Type": "test_type", }, "status": 200, "cookies": { "sess_uuid": "prev_test_uuid", }, } self.loop = asyncio.new_event_loop() self.response_content = "<html><body></body></html>" self.response_headers = multidict.CIMultiDict([("Content-Type", "text/html")]) self.response_status = 200 event_result = dict(response=dict( message=dict(detection={"type": 1}, sess_uuid="test_uuid"))) RequestHandler = Mock() protocol = RequestHandler() message = RawRequestMessage( method="POST", path="/", version=HttpVersion(major=1, minor=1), headers=self.request_data["headers"], raw_headers=None, should_close=None, compression=None, upgrade=None, chunked=None, url=URL("http://test_url/"), ) self.request = web.Request( message=message, payload=None, protocol=protocol, payload_writer=None, task="POST", loop=self.loop, ) self.handler.tanner_handler.create_data = Mock( return_value=self.request_data) self.handler.tanner_handler.submit_data = AsyncMock( return_value=event_result) self.handler.submit_slurp = AsyncMock() web.Response.add_header = Mock() web.Response.write = Mock() web.Response.send_headers = Mock() web.Response.write_eof = AsyncMock() aiohttp.streams.EmptyStreamReader.read = AsyncMock( return_value=b"con1=test1&con2=test2") self.handler.tanner_handler.parse_tanner_response = AsyncMock( return_value=( self.response_content, self.response_headers, self.response_status, ))