Repository navigation
Block NAT64 and IPv4-compatible embedded addresses in load_web_page SSRF guard - #6486
herdiyana256 wants to merge 5 commits into
Conversation
…SRF guard _is_blocked_address rejected any address that is not global, which correctly blocks IPv4 private/loopback/link-local literals and their IPv4-mapped IPv6 form. It did not block the NAT64 well-known prefix (64:ff9b::/96) or the deprecated IPv4-compatible form (::a.b.c.d): ipaddress classifies both as globally routable even though they embed an internal IPv4 address. On a NAT64-enabled network a request to 64:ff9b::169.254.169.254 is translated to the IPv4 link-local metadata endpoint, so the guard could be bypassed to reach internal or metadata addresses. Unwrap the embedded IPv4 address from these forms and re-check it, so a target is blocked when either the IPv6 address or its embedded IPv4 address is non-global. NAT64 to a genuinely public IPv4 (for example 64:ff9b::8.8.8.8) is still allowed.
602a5c7 to
4cc8fed
Compare
|
Hi @herdiyana256 , Thank you for your contribution! We appreciate you taking the time to submit this pull request. |
|
Thanks @rohityan! Added unit tests in
All pass locally ( |
|
Merged @xuanyang15 this one is assigned to you and the review comments from @rohityan (unit tests + CI) are already addressed. Would you mind taking a look when you have a moment? |
|
@herdiyana256 Thanks for creating this PR! This change appears to be a duplicate of earlier PR #6347, which addresses the same NAT64 and IPv4-compatible SSRF vulnerability in load_web_page and was submitted on 2026-07-08 (18 days prior to PR #6486). We will proceed with #6347 to credit the earlier PR. |
load_web_page validates fetch targets through _is_blocked_address, which rejects any address that is not global. That correctly blocks IPv4 private, loopback, and link-local literals, hostnames that resolve to them, and the IPv4-mapped IPv6 form ::ffff:a.b.c.d.
It does not block two other IPv6 encodings that carry an internal IPv4 address. The NAT64 well-known prefix 64:ff9b::/96 (RFC 6052) and the deprecated IPv4-compatible form ::a.b.c.d both embed an IPv4 address in their low 32 bits, but the standard library classifies them as globally routable, so is_global is True and the guard allows them. As a result 64:ff9b::169.254.169.254 and ::169.254.169.254 pass the check, and the same holds for private and loopback ranges.
On a NAT64-enabled network (common in IPv6-only environments) a connection to 64:ff9b::169.254.169.254 is translated by the NAT64 gateway to the IPv4 link-local metadata endpoint 169.254.169.254, so an attacker who can influence the URL passed to the tool can reach cloud metadata or other internal services despite the guard. The target can also be delivered through DNS by publishing an AAAA record inside the prefix.
This change unwraps the embedded IPv4 address from the IPv4-mapped, NAT64 well-known, and IPv4-compatible forms and re-checks it, so a target is blocked when either the IPv6 address or its embedded IPv4 address is non-global. NAT64 to a genuinely public IPv4 such as 64:ff9b::8.8.8.8 is still allowed, and the existing load_web_page test suite continues to pass.