Post

X-Forwarded-For Spoofing – Internal Staff Portal Access Control Bypass | Brackish Brewing Co.

X-Forwarded-For Spoofing – Internal Staff Portal Access Control Bypass | Brackish Brewing Co.

Lab Link

Lab: Brackish Brewing Co.

Overview

The Brackish Brewing Co. challenge demonstrates an access control flaw caused by trusting client-controlled headers.

The staff portal was designed to permit access only from internal systems. The application relied on information supposedly added by a load balancer to determine whether requests originated from the internal network.

After infrastructure changes, the assumptions behind the implementation no longer matched reality. The application still trusted network information supplied through HTTP headers.

By spoofing the expected header value, it became possible to impersonate an internal request and bypass access restrictions.

Objective

Gain access to the staff-only portal and retrieve the flag.

Vulnerability Classification Hierarchy

1
2
3
4
5
OWASP Category
└── A01: Broken Access Control
    └── Trust Boundary Violation
        └── Header-Based Authentication Bypass
            └── X-Forwarded-For Spoofing

Reconnaissance

Initial application mapping revealed:

1
2
3
/tap-list

/visit

Additional directory enumeration identified:

1
/staff

Visiting:

1
/staff

returned:

1
2
3
4
5
6
7
403 · Forbidden · staff-portal

Staff portal — internal network access only.

This portal is internal-network only. If you're seeing this from a personal device, you'll need to access it from the Coalridge office VPN or hit it from the LB hostname — the cloud load balancer is supposed to mark the request as a trusted hop before it gets here.

If you are on the office VPN and still seeing this, grab Hollis. The new load balancer changed how it labels in-network requests after the migration, and the staff handler may be looking for the old loopback marker.

The error message disclosed several important details:

  • Internal access restrictions existed
  • Traffic relied on load balancer information
  • Migration changes affected request handling
  • The application expected a loopback marker

The message strongly suggested the application was trusting request metadata.

Analysis

Applications behind reverse proxies frequently use headers such as:

1
X-Forwarded-For

to identify client IP addresses.

Typical flow:

1
2
3
4
5
User
   ↓
Load Balancer
   ↓
Application

The application appeared to assume:

1
Requests with loopback IP = internal users

However:

1
HTTP headers are client controlled

unless explicitly rewritten and validated by a trusted proxy.

Exploitation

Burp Suite interception was enabled.

The request to:

1
GET /staff HTTP/2

was modified by adding:

1
X-Forwarded-For: 127.0.0.1

Modified request:

1
2
3
4
GET /staff HTTP/2
Host: target.com

X-Forwarded-For: 127.0.0.1

The modified request was forwarded to the server.

Proof of Exploitation

The application accepted the spoofed value and treated the request as internal traffic.

Request flow became:

1
2
3
4
5
6
7
Attacker Request
        ↓
X-Forwarded-For: 127.0.0.1
        ↓
Application trusts header
        ↓
Access granted

The browser displayed the staff portal successfully.

Scrolling through the page revealed:

1
WEBVERSE{.....}

Access restrictions were completely bypassed.

Root Cause

The application likely implemented logic similar to:

1
2
3
4
5
if request.headers.get(
    "X-Forwarded-For"
) == "127.0.0.1":

    allow_staff_access()

The problem:

1
X-Forwarded-For

is supplied through HTTP requests and can be modified by users.

The application failed to:

  • Verify trusted proxy sources
  • Validate request origin
  • Separate user input from infrastructure metadata
  • Establish a secure trust boundary

Impact

In real-world environments this issue can lead to:

  • Administrative portal access
  • Authentication bypass
  • Internal API exposure
  • Sensitive information disclosure
  • Privilege escalation
  • Complete application compromise

Internal panels frequently assume network location equals trust.

Attackers can exploit that assumption.

Mitigation

Never trust client-supplied forwarding headers directly

Bad:

1
2
if request.headers["X-Forwarded-For"]=="127.0.0.1":
    allow()

Secure:

1
2
if request.remote_addr in trusted_proxies:
    client_ip = extract_verified_ip()

Configure trusted proxy chains

Only accept forwarding information from known infrastructure components.

Use authentication instead of network assumptions

Replace:

1
Internal IP = trusted user

with:

1
Authenticated user + authorization checks

Strip untrusted forwarding headers

Reverse proxies should overwrite:

1
2
3
X-Forwarded-For
X-Real-IP
Forwarded

rather than preserving user-supplied values.

Real-World Insight

Header spoofing issues commonly appear during penetration tests involving:

  • Internal dashboards
  • Administrative portals
  • Legacy applications
  • Reverse proxy migrations
  • VPN-restricted systems

A frequent assumption is:

1
Nobody can modify X-Forwarded-For

Attackers interact directly with requests.

Anything originating from the client should be considered untrusted until validated.

This post is licensed under CC BY 4.0 by the author.