Request Smuggling in Aspnet with Bearer Tokens
Request Smuggling in Aspnet with Bearer Tokens
Request smuggling occurs when an attacker can cause a front-end (e.g., a load balancer or reverse proxy) and a back-end server to interpret HTTP message boundaries differently. In ASP.NET applications that rely on Bearer Tokens for authorization, this mismatch can allow an attacker to smuggle a request so that a trusted backend processes it in the context of a different user or without proper authentication checks.
Consider an ASP.NET Core API that expects an Authorization header with a Bearer Token and also parses message bodies for JSON. A common pattern is to forward an incoming request to a backend service while preserving headers. If the front-end and ASP.NET handle Transfer-Encoding and Content-Length differently, an attacker can craft a request such as:
POST /api/transfer HTTP/1.1
Content-Length: 72
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoidGVzdCJ9.XXXXXXXX
Transfer-Encoding: chunked
0
POST /api/admin HTTP/1.1
Content-Length: 13
{"action":"reset"}
A vulnerable ASP.NET pipeline configured with UseForwardedHeaders and permissive message size limits may interpret the message boundary such that the second request appears to be part of the first chunked body, while the backend processes it as a separate request under the original Bearer Token. This can lead to privilege escalation (BOLA/IDOR) when the back-end trusts the token presented on the first request and applies it to the smuggled request.
Another scenario involves HTTP/2 request smuggling where request routing and header transformations differ between the edge and ASP.NET. Because ASP.NET Core may normalize headers differently than the front-end, an attacker can inject an extra request that bypasses intended authorization checks associated with the Bearer Token, effectively allowing actions to be performed under another identity.
These smuggling vectors are especially risky when Bearer Tokens are used for authorization because the token may be accepted even though the request path or method was not intended by the token holder. The API may pass authentication checks but fail authorization due to mismatched routing or body parsing, enabling BOLA/IDOR or privilege escalation.
Bearer Tokens-Specific Remediation in Aspnet
To mitigate request smuggling in ASP.NET applications using Bearer Tokens, align how headers and bodies are processed between the front-end and the ASP.NET pipeline. Below are concrete code-focused practices and examples.
1. Explicitly configure Forwarded Headers
Limit which headers and hosts are trusted to reduce header confusion. Avoid a broad enable-wildcard approach.
// Program.cs builder.Services.Configure(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; // Do not forward the Host header from untrusted sources options.KnownNetworks.Clear(); options.KnownProxies.Clear(); // Only trust your specific reverse proxy IPs options.ForwardLimit = 2; }); app.UseForwardedHeaders();
2. Disable buffering for large or untrusted bodies when not needed
Avoid enabling buffering that can obscure message boundaries. If you must buffer, ensure content-length or transfer-encoding are not both present in a way that can be manipulated.
// Example: do not enable AllowInputBufferBodyReading for untrusted endpoints
// Configure Kestrel to limit request limits in appsettings.json
{
"Kestrel": {
"Limits": {
"MaxRequestBodySize": 32000,
"MinRequestBodyDataRate": {
"BytesPerSecond": 100,
"PollInterval": "5s"
}
}
}
}
3. Enforce strict host and header canonicalization
Ensure the application validates the Host header and does not rely on forwarded values for security decisions unless explicitly required and validated.
// Program.cs
builder.Services.AddHttpContextAccessor();
app.Use(async (context, next) =>
{
// Example: reject requests with an unexpected host when behind a proxy
var allowedHost = "api.example.com";
if (!string.Equals(context.Request.Host.Host, allowedHost, StringComparison.OrdinalIgnoreCase))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Bad Request");
return;
}
await next(context);
});
4. Use authentication and authorization consistently after request is fully parsed
Place Bearer Token validation after body reading and routing to ensure the token is evaluated in the correct context. Avoid early authentication that might be bypassed by smuggling.
// Example middleware ordering in Program.cs
app.UseRouting();
// Validate Bearer Token after routing so the target endpoint is known
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
// Sample controller requiring Bearer Token
[ApiController]
[Route("api/[controller]")]
public class TransferController : ControllerBase
{
[HttpPost("transfer")]
[Authorize(AuthenticationSchemes = "Bearer")]
public IActionResult Transfer([FromBody] TransferModel model)
{
// business logic
return Ok();
}
}
public class TransferModel
{
public string Action { get; set; }
}
// Sample controller for admin operations with the same token validation
[ApiController]
[Route("api/[controller]")]
public class AdminController : ControllerBase
{
[HttpPost("admin")]
[Authorize(AuthenticationSchemes = "Bearer")]
public IActionResult Admin([FromBody] AdminModel model)
{
// business logic
return Ok();
}
}
public class AdminModel
{
public string Action { get; set; }
}