Spaces:
Runtime error
Runtime error
| """Tests for the Injector target-resolution logic (no live HTTP).""" | |
| from __future__ import annotations | |
| from intelliscan.modules.crawler import CrawlResult, Form, UrlParam | |
| from intelliscan.modules.injector import Injector | |
| class _FakeHttp: | |
| """Minimal stand-in; target resolution never performs requests.""" | |
| def get_csrf_token(self, url): # pragma: no cover - unused in these tests | |
| return None | |
| def _make_injector(crawl_result=None) -> Injector: | |
| return Injector(_FakeHttp(), "http://localhost:8080", crawl_result=crawl_result) | |
| def test_falls_back_to_dvwa_when_no_crawl(): | |
| inj = _make_injector(crawl_result=None) | |
| targets = inj._resolve_targets() | |
| assert targets, "expected DVWA fallback targets" | |
| assert all(t.source.startswith("dvwa") for t in targets) | |
| def test_skips_state_mutating_forms(): | |
| # security.php (changes the security level) and a password-change form must | |
| # never be injected — doing so corrupts the scan/session state mid-run. | |
| crawl = CrawlResult( | |
| target="http://localhost:8080", | |
| pages_visited=3, | |
| forms=[ | |
| Form( | |
| url="http://localhost:8080/security.php", | |
| action="http://localhost:8080/security.php", | |
| method="POST", | |
| inputs=[{"name": "security", "type": "text", "value": ""}], | |
| ), | |
| Form( | |
| url="http://localhost:8080/vulnerabilities/csrf/", | |
| action="http://localhost:8080/vulnerabilities/csrf/", | |
| method="GET", | |
| inputs=[ | |
| {"name": "password_new", "type": "password", "value": ""}, | |
| {"name": "password_conf", "type": "password", "value": ""}, | |
| ], | |
| ), | |
| Form( | |
| url="http://localhost:8080/vulnerabilities/sqli/", | |
| action="http://localhost:8080/vulnerabilities/sqli/", | |
| method="GET", | |
| inputs=[{"name": "id", "type": "text", "value": ""}], | |
| ), | |
| ], | |
| url_params=[], | |
| ) | |
| inj = _make_injector(crawl) | |
| targets = inj._resolve_targets() | |
| urls = {t.url for t in targets} | |
| assert urls == {"http://localhost:8080/vulnerabilities/sqli/"} | |
| def test_empty_crawl_does_not_fall_back_to_dvwa(): | |
| # A supplied-but-empty crawl (blocked/unreachable target) must NOT fabricate | |
| # DVWA targets — that produced phantom findings from WAF/error pages. | |
| crawl = CrawlResult( | |
| target="https://blocked.example", | |
| pages_visited=0, | |
| forms=[], | |
| url_params=[], | |
| blocked_responses=1, | |
| start_reachable=False, | |
| ) | |
| inj = _make_injector(crawl) | |
| assert inj._resolve_targets() == [] | |
| def test_resolves_form_inputs_and_skips_submit(): | |
| crawl = CrawlResult( | |
| target="http://localhost:8080", | |
| pages_visited=1, | |
| forms=[ | |
| Form( | |
| url="http://localhost:8080/login", | |
| action="http://localhost:8080/login", | |
| method="POST", | |
| inputs=[ | |
| {"name": "username", "type": "text", "value": ""}, | |
| {"name": "password", "type": "password", "value": ""}, | |
| {"name": "Login", "type": "submit", "value": "Login"}, | |
| ], | |
| ) | |
| ], | |
| url_params=[], | |
| ) | |
| inj = _make_injector(crawl) | |
| targets = inj._resolve_targets() | |
| assert len(targets) == 1 | |
| t = targets[0] | |
| assert t.source == "crawl-form" | |
| assert set(t.inject_params) == {"username", "password"} # text fields | |
| assert t.static_fields == {"Login": "Login"} # submit preserved | |
| def test_resolves_url_params(): | |
| crawl = CrawlResult( | |
| target="http://localhost:8080", | |
| pages_visited=1, | |
| forms=[], | |
| url_params=[UrlParam(url="http://localhost:8080/item?id=3&cat=2", params=["id", "cat"])], | |
| ) | |
| inj = _make_injector(crawl) | |
| targets = inj._resolve_targets() | |
| assert len(targets) == 1 | |
| t = targets[0] | |
| assert t.source == "crawl-param" | |
| assert t.method == "GET" | |
| assert t.url == "http://localhost:8080/item" # query stripped | |
| assert "lfi" in t.vuln_types # params probe LFI too | |
| def test_build_tasks_pairs_payloads_with_targets(): | |
| crawl = CrawlResult( | |
| target="http://localhost:8080", | |
| pages_visited=1, | |
| forms=[], | |
| url_params=[UrlParam(url="http://localhost:8080/x?q=1", params=["q"])], | |
| ) | |
| inj = _make_injector(crawl) | |
| tasks = list(inj._build_tasks(inj._resolve_targets())) | |
| # Every task is (target, vuln_type, payload) and only uses loaded vuln types. | |
| assert tasks | |
| for target, vuln_type, payload in tasks: | |
| assert vuln_type in target.vuln_types | |
| assert isinstance(payload, str) and payload | |