Skip to main content
Phisherman accepts arbitrary URLs as input and resolves their hostnames during heuristic analysis. Without safeguards, an attacker could submit URLs pointing to internal services and cause the server to make requests on their behalf — a Server-Side Request Forgery (SSRF) attack. Phisherman blocks SSRF at two levels: a static IP check for URLs that already contain a raw IP address, and a safe DNS resolver that validates resolved addresses before any connection is made.
Phisherman is designed to analyze public URLs only. Submitting URLs that point to internal services, loopback addresses, or cloud metadata endpoints will be blocked and scored accordingly.

Private IP ranges blocked

IPv4

The following ranges are blocked:

IPv6

blockIfPrivate

blockIfPrivate() is a synchronous guard applied before any DNS resolution. It handles the case where the user-supplied URL already contains a raw IP address:
In the heuristics checker, blockIfPrivate is called immediately after the URL is parsed:
If the hostname is a literal private IP, scanning stops immediately and a score of 50 is returned.

safeResolveHost

safeResolveHost() resolves a hostname to its A and AAAA records and validates every returned IP before returning. If any resolved address falls within a private range, an error is thrown.
The function rejects any host where any resolved address is private — not just the first one.

DNS rebinding protection

DNS rebinding is an attack where a hostname first resolves to a public IP (passing the check above), then immediately resolves to a private IP when the actual connection is made. Phisherman mitigates this with a second, independent lookup:
The second lookup uses dns.lookup() — which goes through the OS resolver rather than querying authoritative servers directly — to simulate what a subsequent connection attempt would see. If any address in the second lookup is private, the host is blocked.

DNS result caching

Successful DNS resolutions are cached in the dnsCache HashCache instance for 1 hour:
Caching avoids repeating the full two-lookup sequence for every scan of a recently seen hostname. The HashCache stores results in dns_cache_hash with expiry tracked in dns_cache_expiry, and expired entries are purged on every CacheManager cycle.