Spoofing In github.com/gofiber/fiber/v3
Description
GoFiber Vulnerable to X-Real-IP Spoofing via Header.Add() in BalancerForward
Summary
The BalancerForward proxy helper in GoFiber uses Header.Add() instead of Header.Set() when injecting the X-Real-IP header. This appends the real client IP as a second header value rather than replacing any attacker-supplied value. Upstream servers that read the first X-Real-IP header (nginx, Express, most HTTP servers) use the attacker's spoofed IP for logging, rate limiting, and access control.
Vulnerable Code
File: middleware/proxy/proxy.go, lines 270-285
func BalancerForward(servers []string, clients ...*fasthttp.Client) fiber.Handler { r := &roundrobin{ current: 0, pool: servers, } return func(c fiber.Ctx) error { server := r.get() if !strings.HasPrefix(server, "http") {...
Data Flow
Attacker sends request with X-Real-IP: 10.0.0.1 (spoofed internal IP)
BalancerForward handler executes at line 282
c.Request().Header.Add("X-Real-IP", c.IP()) APPENDS the real IP as a second header
Upstream server receives: X-Real-IP: 10.0.0.1 AND X-Real-IP: <real-attacker-ip>
Most HTTP servers (nginx, Node.js, Apache) read the FIRST value
Upstream uses 10.0.0.1 for all IP-dependent logic
Impact
Rate limit bypass: IP-based rate limiting at the upstream uses the spoofed IP, allowing unlimited requests
IP ACL bypass: Internal IP allowlists (e.g., admin panels restricted to 10.0.0.0/8) can be bypassed
Audit log poisoning: Security logs record the spoofed IP, making incident investigation unreliable
Geolocation bypass: IP-based geofencing or region restrictions are circumvented
Fix
Replace Header.Add() with Header.Set() at line 282:
c.Request().Header.Set("X-Real-IP", c.IP())
Header.Set() replaces any existing header value, ensuring only the real client IP is forwarded.
Mitigation
Update Impact
Minimal update. May introduce new vulnerabilities or breaking changes.
Ecosystem | Component | Affected version | Patched versions |
|---|---|---|---|
go | 3.3.0 | ||
go | 2.52.14 |
Aliases
References