A problem in DreamHack
Understanding IP Trust and the Dangers of X-Forwarded-For
While practicing some web challenges on DreamHack, I came across a beginner-level challenge called whoami – Level 1.
Although the difficulty is low, this challenge highlights a very common and dangerous mistake in real-world web applications: blindly trusting client-controlled headers.
Challenge Overview
The challenge provides:
A simple single-page web application
Two backend API endpoints:
/whoami/admin
The backend source code, written in Express (Node.js)
The objective is straightforward:
Gain admin privileges and retrieve the flag.
At first glance, this looks trivial. However, the interesting part lies in how the backend determines whether a user is an admin or not.
Backend Code Analysis
After reviewing the Express backend source code, one thing immediately stood out:
Admin access is determined based on the client's IP address.
More specifically, the application relies on the value of the X-Forwarded-For HTTP header to identify the requester.
This is a classic red flag in web security.
What Is X-Forwarded-For?
X-Forwarded-For is a non-standard HTTP header commonly used by:
Reverse proxies (Nginx, HAProxy)
Load balancers
CDNs (Cloudflare, AWS ALB, etc.)
Its original purpose is to preserve the original client IP address when requests pass through one or more proxies.
Example:
X-Forwarded-For: 203.0.113.42
With multiple proxies involved:
X-Forwarded-For: 203.0.113.42, 10.0.0.1, 172.16.0.5
By convention:
The first IP is the original client
The remaining IPs are intermediate proxies
The Core Issue: Client-Controlled Headers
Here is the critical mistake made by the application:
X-Forwarded-Forcan be fully controlled by the client.
Any user can manually set this header using tools such as:
curlBurp Suite
Postman
For example:
curl -H "X-Forwarded-For: 127.0.0.1" https://target/admin
If the backend blindly trusts this header without verifying that the request actually came through a trusted proxy, the access control logic is completely broken.
This type of mistake is frequently exploited to bypass:
IP-based access control
Rate limiting
Geo-restrictions
Anti-bot mechanisms
Exploitation
In the whoami challenge, exploitation is extremely simple:
Send a request to the
/adminendpointManually set the
X-Forwarded-Forheader to a trusted IP (e.g.,127.0.0.1)The backend assumes the request is from an internal or admin user
Admin access is granted
The flag is returned
No brute force.
No race condition.
Just a logic flaw caused by misplaced trust.
Retrieved Flag
DH{5c36de0d635aef1f7f3002163e7d9cca005b7fb470c93d68188d48d9f317a017}
Lessons Learned
This challenge reinforces several important security lessons:
1. Never Trust Client-Supplied Headers
Headers such as X-Forwarded-For, X-Real-IP, or custom headers should never be trusted by default.
2. Proxy Awareness Is Essential
X-Forwarded-For should only be used if:
Requests come from trusted proxy IPs
The backend explicitly validates the request source
3. Simple Bugs Can Have Serious Impact
Even though this is a Level 1 challenge, the same vulnerability appears frequently in production systems.
Final Thoughts
The whoami challenge is a great reminder that security is often about correct assumptions rather than complex exploits.
If you are developing or auditing web applications, always ask yourself:
“Who controls this data?”
Because if the user controls it — you should never trust it.
Stay Updated
Get the latest posts, security insights, and tech updates delivered straight to your inbox. No spam, unsubscribe anytime.
Comments
💬 No account required — Just drop your thoughts below!