x509util: fix SSRF hostname bypass in rejectPrivateHost() - #1776
x509util: fix SSRF hostname bypass in rejectPrivateHost()#1776MrINVISO wants to merge 2 commits into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
PR google#1761 introduced rejectPrivateHost() to block SSRF via private IP addresses, but only checked net.ParseIP() which returns nil for hostnames. DNS hostnames resolving to private or loopback addresses bypassed the fix entirely. This change resolves hostnames via net.LookupHost() before IP validation, blocking bypasses such as: - localhost → 127.0.0.1 (loopback) - metadata.google.internal → 169.254.169.254 (GCP) - kubernetes.default.svc → 10.x.x.x (k8s) Also adds: - rejectPrivateHost() to ReadFileOrURL() and GetIssuer() - defer rsp.Body.Close() to prevent resource leaks - Tests for hostname bypass and SSRF protection Fixes incomplete fix in PR google#1761 (Issue google#1759)
d39a98c to
d87e609
Compare
|
This PR extends the fix from #1761 by also resolving hostnames before IP validation. Gap in #1761:
Validated PoC: This PR adds |
|
Update: Google Bug Hunter Team reviewed this via issuetracker and marked as Infeasible (below security escalation threshold), but noted the issue is valid and suggested public disclosure. The fix in this PR remains valuable for hardening purposes. |
Summary
PR #1761 introduced
rejectPrivateHost()to fix SSRF inx509util/files.go, but the fix is incomplete. It only blocks private IP addresses vianet.ParseIP(), which returnsnilfor hostnames. DNS hostnames resolving to private or loopback addresses bypass the fix entirely.Root Cause
Bypasses Confirmed
http://localhost/http://metadata.google.internal/http://kubernetes.default.svc/http://127.0.0.1/Fix
Resolve hostname via
net.LookupHost()before IP validation.Changes
rejectPrivateHost()to resolve hostnames before checkingrejectPrivateHost()toReadFileOrURL()andGetIssuer()defer rsp.Body.Close()to prevent resource leaksTesting
Related: #1759
Fixes incomplete fix in: #1761