# SSRF in https://cards-dev.twitter.com/validator

Twitter card validator fetches arbitrary URLs including localhost/0.0.0.0, enabling SSRF against internal services and port scanning.

- Payout: hidden
- Severity: medium
- Program: X / xAI
- Found by: mindaugas
- Disclosed: 2017-04-06
- Write-up quality: 6/10
- Original: https://hackerone.com/reports/178184
- Library page: https://bugbountylibrary.com/r/h1%3A178184
- Tags: area:web domain:web impact:internal-access kind:bounty platform:hackerone sev:medium technique:incomplete-fix technique:recon technique:regression vuln:ssrf

**Target:** cards-dev.twitter.com/validator URL fetch endpoint
**Root cause:** The card validator fetches user-supplied URLs server-side without blocking loopback/internal addresses; a prior fix was reverted, and 0.0.0.0 bypasses localhost filtering.
**Steps:**
1. Open https://cards-dev.twitter.com/validator
2. Submit `http://0.0.0.0:123` (closed port) -> 'Fetching the page failed because other errors'
3. Submit `http://0.0.0.0:22` (open non-HTTP) -> 'Failed to fetch page due to: ChannelClosed'
4. Submit `http://0.0.0.0:4680` (open HTTP) -> 'Page fetched successfully'
5. Submit `http://0.0.0.0:4680/system/` vs `http://0.0.0.0:4680/test/` to distinguish existing vs non-existing paths via metatag warnings
**How found:** Researcher recalled a prior SSRF report (hackerone.com/reports/30860) and retested, discovering the fix was reverted; used 0.0.0.0 to reach loopback and compared error messages across closed/open ports and existing/non-existing paths.
**Exploitation:** Attacker uses the validator as an SSRF proxy to reach internal HTTP services bound to loopback, enumerate ports/paths, and potentially hit command-execution endpoints like `http://0.0.0.0:4680/system/command.php?command=[ROOT_COMMAND]`.
**Escalation:** Port scanning and path enumeration via differential error messages; chaining to internal command-execution services.
**Insight:** When a localhost SSRF filter exists, try alternate loopback representations like 0.0.0.0; also use differential error strings (ChannelClosed vs fetched successfully, metatag warnings) to fingerprint open ports and existing paths blindly.

