# GitLab::UrlBlocker validation bypass leading to full Server Side Request Forgery

GitLab::UrlBlocker resolves DNS twice (check then request), so a low-TTL alternating DNS record bypasses SSRF blocklists and lets webhooks hit localhost/metadata.

- Payout: hidden
- Severity: high
- Program: GitLab
- Found by: ajxchapman
- Disclosed: 2019-12-12
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/541169
- Library page: https://bugbountylibrary.com/r/h1%3A541169
- Tags: area:web domain:web impact:data-leak impact:internal-access kind:bounty platform:hackerone sev:high tech:ruby technique:race-window technique:source-review vuln:race-condition vuln:ssrf

**Target:** GitLab web hook integration / GitLab::UrlBlocker SSRF validation
**Root cause:** UrlBlocker resolves the hostname and validates IPs, but GitLab::HTTP/HTTParty re-resolves the hostname when making the request, so a DNS server returning alternating addresses with TTL 0 passes validation then connects to a forbidden IP.
**Steps:**
1. Configure attacker DNS to alternate a domain between a public IP and 127.0.0.1 with TTL 0 (e.g. `gitlabextssrf.webhooks.pw` -> 198.211.125.160 / 127.0.0.1)
2. Create repo, add commit, create Web Hook with URL `http://gitlabextssrf.webhooks.pw:9999` (retry on 500 until accepted)
3. Start TCP listener on target port 9999 (`nc -vvn -l -p 9999`)
4. Fire many parallel requests to the hook test endpoint: `wfuzz -X POST -b "_gitlab_session=<session_id>;" -d "_method=post&authenticity_token=<token>" -z range,0-1000 "https://<domain>/<user>/<repo>/hooks/<hook_id>/test?trigger=push_events&test=FUZZ"`
5. Eventually a connection lands on the local listener, confirming SSRF
**How found:** Code review of `/lib/gitlab/url_blocker.rb` showed Addrinfo.getaddrinfo validation separate from the later HTTParty request; recognized the double DNS resolution as a ToCToU window and built an alternating low-TTL DNS server to exploit it.
**Exploitation:** Authenticated user abuses web hook test endpoint to make server-side GET/POST to arbitrary hosts/paths; demonstrated reading DigitalOcean metadata `http://169.254.169.254/metadata/v1.json`, enabling token theft and internal network recon.
**Escalation:** Chain SSRF to cloud metadata service to leak credentials, then pivot to internal network hosts.
**Insight:** When a validator resolves DNS and the HTTP client resolves again, look for a ToCToU window; a TTL-0 DNS server alternating between allowed and forbidden IPs reliably wins the race across retries.

