google / google/certificate-transparency-go

SSRF via unvalidated AIA/CRL URLs in certificate extensions (sctcheck, certcheck, crlcheck, fixchain)

Open
#1,775 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
1.2k
Forks
322
Avg merge
3d 4h
Merged PRs (30d)
5

Description

## Summary

The `certificate-transparency-go` operator tooling (`sctcheck`, `certcheck`, `crlcheck`, and the `fixchain` preloader) fetches URLs from certificate extensions (AIA CA Issuers, CRL Distribution Points) without any SSRF protection.

## Vulnerable Code

**Root cause: `x509util/files.go:97-115` — `GetIssuer()` fetches AIA URL with no validation**
```go
func GetIssuer(cert *x509.Certificate, client *http.Client) (*x509.Certificate, error) {
issuerURL := cert.IssuingCertificateURL[0] // raw string from cert's AIA extension
rsp, err := client.Get(issuerURL) // HTTP GET with no scheme/host/IP validation
body, err := io.ReadAll(rsp.Body) // no response size limit — OOM possible
```

**Same vulnerability in five additional callsites:**

1. `ctutil/sctcheck/sctcheck.go:131` — triggers `GetIssuer()` during SCT checking
2. `x509util/crlcheck/crlcheck.go:170-174` — directly calls `client.Get(crldp)` on CRL Distribution Points
3. `x509util/files.go:48-56` — `ReadPossiblePEMURL` uses bare `http.Get()` with no timeout
4. `x509util/certcheck/certcheck.go:226-227` — `checkRevocation()` calls `ReadPossiblePEMURL` on CRL Distribution Points
5. `fixchain/url_cache.go:67` — `fixchain` preloader calls `client.Get(url)` on AIA URLs from every cert in a CT log

Additionally, `InsecureSkipVerify: true` is set in tooling (`sctcheck`, `certcheck`), disabling TLS certificate validation.

## Attack Scenario

An attacker submits a certificate with an AIA CA Issuers URL of `http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token` to a CT log operator who then runs `sctcheck`, `certcheck --check_revocation`, or `crlcheck`. The tool makes an outbound HTTP request to the GCP instance metadata endpoint from the operator's cloud VM.

## Suggested Fix

Add URL validation before fetching AIA/CRL URLs: reject private IP ranges, cloud metadata endpoints, and loopback addresses. Add response size limits to `io.ReadAll` calls. Add timeouts to `http.Get` calls.

Contributor guide

Open the contributing guide

Research direction

Start with x509util/files.go:48-56 and 97-115, then trace the callers in sctutil/sctcheck/sctcheck.go, x509util/crlcheck/crlcheck.go, x509util/certcheck/certcheck.go, and fixchain/url_cache.go. Done means AIA and CRL URL fetches validate destinations, responses are size-limited, HTTP fetches have timeouts, and the tooling's TLS behavior is reviewed without leaving the listed callsites exposed.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.