Mass Parameter Injection into Internal Transaction API via BFF

How a Backend-For-Frontend endpoint blindly forwarded all user-supplied fields to an internal transaction service, leaking internal JWTs and enabling parameter injection.

The Target

A large online marketplace platform with multiple regional sites sharing the same codebase. The platform has a "make offer" feature for second-hand items where buyers submit an offer amount through a BFF (Backend-For-Frontend) layer that proxies requests to an internal transaction service.

The Discovery

I started by sending a normal offer request with just the expected fields: an item ID and an amount. The request went through, but the error response was unusually verbose. It included the full internal request that the BFF forwarded to the downstream service, including the Authorization header with a fresh internal JWT token, the internal Kubernetes service URL, and a Node.js stack trace with file paths.

That was already a finding on its own. But the interesting part was in the forwarded request body. The BFF was taking the entire user-supplied JSON and passing it straight through to the internal API, only appending a client field. No filtering, no whitelist.

The Attack

1

Parameter injection: I added extra fields to the request body: sellerId, buyerId, status, paymentMethod, shippingCost. The error response confirmed every single injected field was forwarded to the internal transaction API. The status was set to "COMPLETED", paymentMethod to "FREE", and shippingCost to -100.

2

Internal JWT leak: Every request to the BFF leaked a fresh RS256-signed JWT in the error response. Decoding it revealed the internal Kubernetes service name used as the issuer, the user's internal login ID, session ID, and other identifiers. A new token was generated on every call.

3

Infrastructure disclosure: The error also leaked the internal service URL where transactions are initialized, the Kubernetes namespace structure, and full Node.js stack traces with dependency paths.

4

Cross-platform confirmation: The same vulnerability existed on the platform's regional sister site. Different JWT (different signing key), same BFF code, same parameter forwarding behavior. Both sites shared the same internal transaction service.

Impact

  • Attacker-controlled fields (sellerId, buyerId, status, paymentMethod, shippingCost) forwarded to internal transaction API via trusted internal JWT
  • Fresh internal RS256 JWT leaked on every request, containing user identifiers and session data
  • Internal Kubernetes service names and Node.js stack traces exposed
  • Confirmed on two regional platforms sharing the same BFF codebase

Timeline

Reported with full reproduction steps across both platforms. Awaiting triage.

Takeaway

BFF layers are a common source of parameter injection bugs. They sit between the client and internal services, and developers often forward the request body as-is, trusting that the internal API will validate it. The fix is simple: whitelist the fields you expect and reject everything else before forwarding. Also, never return internal error details to the client. In this case, the verbose error response was what revealed the entire attack surface, including the internal JWT, service URLs, and proof that injected parameters were reaching the downstream API.

← Back to Blog