The Header That Says Where You Are: Spoofing a Trusted Source Address

Privilege Escalation & Post-Exploitation Level 3/4 ~4 min October 6, 2026

The challenge

Thornbury manages the access control for a few dozen buildings, and the door schedules are read-only to anyone outside the management network. That restriction is real: the API refuses you from the internet and says so. It is also enforced by asking the caller where the caller is. Get the Leeds site schedule, read the overrides at the bottom of it, and name the door that a facilities ticket has left open to anyone who walks up to it for the next two months.

What you'll learn

  • Explain what X-Forwarded-For is for and why its value is attacker controlled
  • Use an error body's own disclosure to construct the bypass
  • Understand that proxies disagree about which entry of the list is the client
  • Recognise network location as authentication and why that fails at layer seven
  • Trace an API authorisation flaw through to a physical security consequence

Skills tested

HTTP header manipulationAccess control analysisAPI reconnaissance

Prerequisites

  • The shape of an HTTP request
  • What a private IP range is

How it works

When a request passes through a load balancer or a CDN, the application behind it sees the proxy's address instead of the user's. X-Forwarded-For exists to fix that: the proxy writes down the address it saw and appends to the list as the request travels. It is a hint, recorded by intermediaries, in a header field.

Treating it as proof of location inverts the trust. Anything reaching the application directly, or through a proxy that appends rather than replaces, can set the value to whatever it likes, and the check that was supposed to mean on the corporate network becomes says it is on the corporate network. The only value you may trust is the one your own outermost proxy wrote, and only if that proxy overwrites rather than appends.

The parsing detail is a whole bug class of its own. Some implementations read the first entry, some the last, some the last untrusted one. Two components in the same estate reading opposite ends is how a request gets allowed by one and logged as something else by the other, and it is why the error body here mentions which end it uses at all.

Common mistakes

  • Appending the internal address. 203.0.113.45, 10.12.0.9 is refused, because this API reads the first entry. The response says so.
  • Trying 127.0.0.1. Loopback is a different trust zone and this allowlist wants one specific management address.
  • Answering goods-in. OVR-2288 extends a delivery window by one day and still requires a card.
  • Answering plant-room. OVR-2294 is a single day and keeps card plus PIN.
  • Answering lobby. Its normal schedule is the busiest, but a scheduled open door with card and PIN during office hours is not the finding.
  • Editing the token or the path. The bearer token is valid and the endpoint is correct. Only the location check is broken.

How to defend against it

Decide network location from the connection, not from a header.

  • Have the outermost proxy strip any inbound X-Forwarded-For and write its own. If the application is reachable without passing through that proxy, the header is meaningless and so is the control.
  • Do not use source address as authorisation at all. This endpoint already carries a bearer token; scope the token to what the caller may read and the location check becomes unnecessary.
  • Stop printing the address the allowlist expects. The 403 body turns a guessing problem into a copy and paste.
  • Fix the override too. A door set to unlocked for eight weeks should require a named approver, an expiry measured in days, and an alert while it is active.

Full solution

Pro and Max members unlock the complete step-by-step walkthrough.

Go Pro

Community stats

213 completions
91% success rate
M2F14M3 First blood

Related Daily Hacks

31,000+ Hackers Real labs Free
Start Hacking Free or solve today's hack, no account needed