async def test_fetch_session_cookies_on_scan_start_if_no_user_supplied_cookies(self, loop): engine = FakeHammerTimeEngine() hammertime = HammerTime(request_engine=engine, loop=loop) hammertime.collect_successful_requests() await tachyon.scan(hammertime, cookies=None, accumulator=self.accumulator) tachyon.get_session_cookies.assert_called_once_with(hammertime)
async def test_scan_file_only(self, loop): engine = FakeHammerTimeEngine() hammertime = HammerTime(request_engine=engine, loop=loop) hammertime.collect_successful_requests() await tachyon.scan(hammertime, files_only=True, accumulator=self.accumulator) tachyon.test_file_exists.assert_called_with(hammertime, accumulator=self.accumulator) tachyon.test_paths_exists.assert_not_called()
async def test_fetch_session_cookies_on_scan_start_if_no_user_supplied_cookies( self, loop): engine = FakeHammerTimeEngine() hammertime = HammerTime(request_engine=engine, loop=loop) hammertime.collect_successful_requests() await tachyon.scan(hammertime, cookies=None, accumulator=self.accumulator) tachyon.get_session_cookies.assert_called_once_with(hammertime)
async def test_successful_requests_return_if_no_pending_requests( self, loop): h = HammerTime(loop=loop, request_engine=FakeEngine()) h.collect_successful_requests() try: with async_timeout.timeout(0.001): async for entry in h.successful_requests(): entry.request except asyncio.TimeoutError: self.fail("Function blocked.")
async def test_use_user_supplied_cookies_if_available(self, loop): database.session_cookie = "my-cookies=123" cookies = "test-cookie=true" engine = FakeHammerTimeEngine() hammertime = HammerTime(request_engine=engine, loop=loop) hammertime.collect_successful_requests() with patch("tachyon.config.add_http_header") as add_http_header: await tachyon.scan(hammertime, cookies=cookies, accumulator=self.accumulator) add_http_header.assert_any_call(ANY, "Cookie", "test-cookie=true")
async def test_scan_plugins_only(self, loop): engine = FakeHammerTimeEngine() hammertime = HammerTime(request_engine=engine, loop=loop) hammertime.collect_successful_requests() await tachyon.scan(hammertime, plugins_only=True, accumulator=self.accumulator) tachyon.load_execute_host_plugins.assert_called_once_with(hammertime) tachyon.test_file_exists.assert_not_called() tachyon.test_paths_exists.assert_not_called()
async def test_loop_over_results(self, loop): h = HammerTime(loop=loop, request_engine=FakeEngine()) h.collect_successful_requests() h.request("http://example.com/1") h.request("http://example.com/2") out = set() async for entry in h.successful_requests(): out.add(entry.response.content) self.assertEqual(out, {"http://example.com/1", "http://example.com/2"}) self.assertEqual(h.completed_count, 2)
async def test_no_successful_request_returned_when_requests_are_cancelled( self, loop): engine = MagicMock() engine.perform = make_mocked_coro( raise_exception=asyncio.CancelledError) hammertime = HammerTime(loop=loop, request_engine=engine) hammertime.collect_successful_requests() for i in range(5): hammertime.request("http://example.com") successful_requests = [] async for request in hammertime.successful_requests(): successful_requests.append(request) self.assertEqual(successful_requests, [])
class TestDirectoryFetcher(TestCase): def setUp(self): valid_paths.clear() self.host = "http://example.com" def async_setup(self, loop): self.hammertime = HammerTime(loop=loop, request_engine=FakeHammerTimeEngine()) self.hammertime.collect_successful_requests() self.hammertime.heuristics.add_multiple([SetFlagInResult("soft404", False), SetFlagInResult("error_behavior", False)]) self.directory_fetcher = DirectoryFetcher(self.host, self.hammertime) @async_test() async def test_fetch_paths_add_valid_path_to_database(self, output_result, loop): valid = ["/a", "b", "/c", "/1", "/2", "/3"] invalid = ["/d", "/e", "/4", "/5"] paths = valid + invalid self.async_setup(loop) self.hammertime.heuristics.add(RaiseForPaths(invalid, RejectRequest("Invalid path"))) await self.directory_fetcher.fetch_paths(create_json_data(paths)) self.assertEqual(len(valid), len(valid_paths)) for path in valid_paths: self.assertIn(path["url"], valid) self.assertNotIn(path["url"], invalid) @async_test() async def test_fetch_paths_dont_add_path_if_response_code_is_401(self, output_result, loop): paths = ["/401"] self.async_setup(loop) self.hammertime.heuristics.add(SetResponseCode(401)) await self.directory_fetcher.fetch_paths(create_json_data(paths)) self.assertEqual(len(database.valid_paths), 0) @async_test() async def test_fetch_paths_output_found_directory(self, output_result, loop): found = ["/%d" % i for i in range(10)] not_found = ["/1%d" % i for i in range(10)] paths = found + not_found self.async_setup(loop) self.hammertime.heuristics.add(RaiseForPaths(not_found, RejectRequest("404 not found"))) await self.directory_fetcher.fetch_paths(create_json_data(paths)) calls = [] for path in create_json_data(found): message, data = self.expected_output(path) calls.append(call(message, data=data)) output_result.assert_has_calls(calls, any_order=True) @async_test() async def test_fetch_paths_does_not_output_root_path(self, output_result, loop): paths = create_json_data(["/"]) self.async_setup(loop) await self.directory_fetcher.fetch_paths(paths) self.assertEqual(database.valid_paths, paths) output_result.assert_not_called() @async_test() async def test_fetch_paths_output_401_directory(self, output_result, loop): self.async_setup(loop) self.hammertime.heuristics.add(SetResponseCode(401)) path_list = create_json_data(["/admin"]) await self.directory_fetcher.fetch_paths(path_list) message, data = self.expected_output(path_list[0], code=401, message_prefix="Password Protected - ") output_result.assert_called_once_with(message, data=data) @async_test() async def test_fetch_paths_output_500_response(self, output_result, loop): self.async_setup(loop) self.hammertime.heuristics.add(SetResponseCode(500)) path_list = create_json_data(["/server-error"]) await self.directory_fetcher.fetch_paths(path_list) message, data = self.expected_output(path_list[0], message_prefix="ISE, ", code=500) output_result.assert_called_once_with(message, data=data) @async_test() async def test_fetch_paths_output_403_directory(self, output_result, loop): self.async_setup(loop) self.hammertime.heuristics.add(SetResponseCode(403)) path_list = create_json_data(["/forbidden"]) await self.directory_fetcher.fetch_paths(path_list) message, data = self.expected_output(path_list[0], message_prefix="*Forbidden* ", code=403) output_result.assert_called_once_with(message, data=data) @async_test() async def test_fetch_paths_append_slash_to_path(self, output_result, loop): paths = ["/a", "/b", "/c", "/1", "/2", "/3"] self.async_setup(loop) await self.directory_fetcher.fetch_paths(create_json_data(paths)) requested = [url for url in self.hammertime.request_engine.request_engine.get_requested_urls()] self.assertEqual(len(paths), len(requested)) for url, path in zip(requested, paths): self.assertEqual(url, "{}{}/".format(self.host, path)) @async_test() async def test_fetch_paths_does_not_append_slash_to_root_path(self, output_result, loop): paths = ["/"] self.async_setup(loop) await self.directory_fetcher.fetch_paths(create_json_data(paths)) requested = list(self.hammertime.request_engine.request_engine.get_requested_urls())[0] self.assertEqual(requested, self.host + "/") def expected_output(self, path, *, code=200, message_prefix=""): url = "{}{}/".format(self.host, path["url"]) data = {"description": path["description"], "url": url, "severity": path["severity"], "code": code} message = "{prefix}{desc} at: {url}".format(prefix=message_prefix, desc=data["description"], url=url) return message, data