|
| 1 | +#!/usr/bin/env python |
| 2 | + |
| 3 | +""" |
| 4 | +Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org) |
| 5 | +See the file 'LICENSE' for copying permission |
| 6 | +
|
| 7 | +Unit tests for lib/utils/search.py (dork search), exercising the engine loop by |
| 8 | +MOCKING the network layer (_fetch). |
| 9 | +
|
| 10 | +No network is involved: _fetch is patched to return canned search engine result |
| 11 | +pages, so we can assert both on the links extracted per engine and on the |
| 12 | +abuse/captcha detection that triggers proxy rotation (SEARCH_ABUSE_MARKERS). |
| 13 | +""" |
| 14 | + |
| 15 | +import os |
| 16 | +import sys |
| 17 | +import unittest |
| 18 | + |
| 19 | +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) |
| 20 | +from _testutils import bootstrap |
| 21 | + |
| 22 | +bootstrap() |
| 23 | + |
| 24 | +from lib.core.data import conf |
| 25 | +from lib.core.exception import SqlmapBaseException |
| 26 | +from lib.core.settings import SEARCH_ABUSE_MARKERS |
| 27 | +import lib.utils.search as smod |
| 28 | + |
| 29 | +BING_PAGE = '<h2><a target="_blank" href="https://www.bing.com/ck/a?!&&p=1&u=a1aHR0cHM6Ly93d3cuZXhhbXBsZS5jb20vYS5waHA_aWQ9MQ&ntb=1">a</a></h2>' |
| 30 | +DUCKDUCKGO_PAGE = '<a class="result__url" href="https://www.example.com/b.php?id=2">b</a>' |
| 31 | + |
| 32 | +class TestDorkSearch(unittest.TestCase): |
| 33 | + def setUp(self): |
| 34 | + conf.googlePage = 1 |
| 35 | + conf.proxyList = None |
| 36 | + self._fetch = smod._fetch |
| 37 | + |
| 38 | + def tearDown(self): |
| 39 | + smod._fetch = self._fetch |
| 40 | + |
| 41 | + def _pages(self, *pages): |
| 42 | + """Patches _fetch to serve `pages` in engine order (None meaning no reply)""" |
| 43 | + |
| 44 | + served = list(pages) |
| 45 | + smod._fetch = lambda *args, **kwargs: served.pop(0) if served else None |
| 46 | + |
| 47 | + def test_duckduckgo_results(self): |
| 48 | + self._pages(DUCKDUCKGO_PAGE) |
| 49 | + self.assertEqual(smod._search("dork"), ["https://www.example.com/b.php?id=2"]) |
| 50 | + |
| 51 | + def test_bing_fallback_decodes_redirect(self): |
| 52 | + self._pages(None, BING_PAGE) |
| 53 | + self.assertEqual(smod._search("dork"), ["https://www.example.com/a.php?id=1"]) |
| 54 | + |
| 55 | + def test_abuse_page_switches_proxy(self): |
| 56 | + # Note: without '--proxy-list' there is nothing to switch to, hence no exception |
| 57 | + for marker in SEARCH_ABUSE_MARKERS: |
| 58 | + self._pages("<html>%s</html>" % marker) |
| 59 | + conf.proxyList = None |
| 60 | + self.assertEqual(smod._search("dork"), []) |
| 61 | + |
| 62 | + self._pages("<html>%s</html>" % marker) |
| 63 | + conf.proxyList = ["http://127.0.0.1:8080"] |
| 64 | + self.assertRaises(SqlmapBaseException, smod._search, "dork") |
| 65 | + |
| 66 | + def test_results_page_is_not_mistaken_for_abuse(self): |
| 67 | + self._pages(DUCKDUCKGO_PAGE) |
| 68 | + conf.proxyList = ["http://127.0.0.1:8080"] |
| 69 | + self.assertEqual(smod._search("dork"), ["https://www.example.com/b.php?id=2"]) |
| 70 | + |
| 71 | +if __name__ == "__main__": |
| 72 | + unittest.main() |
0 commit comments