# SSRF in Search.gov via ?url= parameter

SSRF in Search.gov help_docs url parameter bypassed via LF injection, letting an attacker port-scan internal hosts and probe EC2 metadata endpoints.

- Payout: $150
- Severity: low
- Program: GSA Bounty
- Credited: niwasaki
- Disclosed: 2019-08-26
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/514224
- Library page: https://bugbountylibrary.com/r/h1%3A514224
- Tags: domain:web impact:internal-access kind:bounty platform:hackerone sev:low tech:aws technique:blind vuln:info-disclosure vuln:ssrf

**Target:** search.usa.gov /help_docs endpoint (url parameter)
**Root cause:** The url parameter's allowlist/validation is bypassed by injecting a newline (%0A) so the server fetches an attacker-controlled internal URL before the appended legitimate URL.
**Steps:**
1. Authenticate to Search.gov and open the help manual to capture the /help_docs?url= request.
2. Send `GET /help_docs?url=http://127.0.0.1:21/?%0Ahttps%3A%2F%2Fsearch.gov%2Fmanual%2Faccount.html` and observe ~450ms response (closed port).
3. Send same with `http://127.0.0.1:22/?%0A...` and observe ~10,468ms (open port) to confirm port scanning.
4. Probe `http://169.254.169.254/latest/meta-data/iam/security-credentials/?%0A...` returns empty body (exists) vs `security-credentialx` returns 'Unable to retrieve' (does not exist).
**How found:** Noticed the url parameter was validated but suspected the check could be bypassed; tried injecting a newline (%0A) before the URL to break out of the validation and prepend an internal target, then used timing and body differences to confirm SSRF.
**Exploitation:** Attacker uses the LF-injected url parameter to make the server issue requests to arbitrary internal hosts, using response timing to distinguish open/closed ports and response body differences to enumerate existing paths on the EC2 metadata service.
**Insight:** When a URL parameter is 'protected', try injecting control characters like %0A/%0D before the value to split the validated string from the fetched URL, and use response timing plus body-content differences (empty vs error) as blind SSRF oracles for port and path enumeration.
