Header Injection in Aspnet with Bearer Tokens
Header Injection in Aspnet with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Header Injection in ASP.NET when Bearer Tokens are used centers on improper handling of user-supplied input that reaches HTTP headers, particularly the Authorization header or custom headers that influence authentication flow. When an application builds or forwards headers using unvalidated data, an attacker can inject additional header lines or manipulate token boundaries, leading to token leakage, request smuggling, or authorization bypass.
In ASP.NET, the framework typically parses the Authorization header as Bearer <token>. If developer code concatenates strings to form this header using input from query strings, form fields, or other sources without strict validation, newline characters (e.g., \r\n) can be injected. For example, an attacker may supply a token value containing \r\nX-Forwarded-For: bad.example.com, causing the server to treat injected lines as additional headers. This can change routing, enable host header poisoning, or expose the token to downstream services that process the forwarded request.
Another scenario involves logging or diagnostic code that echoes the Authorization header. If the header value is reflected in responses or logs without sanitization, an injected newline can be used to break out of log formats and inject fake entries or even script content in log viewers that render output in a browser. Because Bearer Tokens often carry high privileges, leakage via header injection can lead to account compromise or lateral movement within a microservice architecture where tokens are passed between components.
ASP.NET Core’s use of the AuthenticationHandler<TOptions> pipeline means developers may inadvertently trust headers set by reverse proxies or API gateways. If the application does not explicitly validate the format of the Authorization header and relies on the presence of the Bearer prefix, malformed tokens or injected control characters may bypass intended validation logic. The framework’s default behavior does not automatically reject newline characters in header values when they come from untrusted sources, so it is up to the developer to enforce strict input rules.
OpenAPI/Swagger specifications that define security schemes as type: http with scheme: bearer can give a false sense of safety if runtime validation is weak. The spec may declare that a Bearer token is required, but if the application does not sanitize incoming headers before constructing outgoing requests to downstream services, injection remains possible. Cross-referencing spec definitions with runtime findings is important to detect mismatches between declared authentication flows and actual behavior, a capability offered by scanners that map such findings to frameworks like OWASP API Top 10.
Real-world impact includes token exfiltration via injected headers that forward credentials to an attacker-controlled endpoint, or session fixation when an injected header alters the routing path of authorized requests. Because Bearer Tokens are often reused across multiple services, a single injection point can have wide-reaching consequences. Effective mitigation requires canonicalizing headers, rejecting unexpected control characters, and validating the entire Authorization header format rather than only the token portion.
Bearer Tokens-Specific Remediation in Aspnet — concrete code fixes
Remediation focuses on strict validation and canonicalization of the Authorization header in ASP.NET. Never construct Authorization headers by concatenating user input. Instead, use the framework’s built-in authentication mechanisms and validate token format before use.
1. Validate Bearer Token format explicitly
Ensure the Authorization header strictly follows Bearer <token> and reject any header containing newline or carriage return characters. Use regular expressions to enforce a safe token character set and length.
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Http;
public static class HeaderValidation
{
private static readonly Regex BearerTokenRegex = new Regex(@"^Bearer [A-Za-z0-9\-._~+/=]+$", RegexOptions.Compiled);
public static bool IsValidBearerHeader(string authorization)
{
if (string.IsNullOrWhiteSpace(authorization))
return false;
// Reject newlines or carriage returns which enable header injection
if (authorization.Contains("\r") || authorization.Contains("\n"))
return false;
return BearerTokenRegex.IsMatch(authorization);
}
}
Use this validator in middleware or within a custom authentication handler before processing the token.
2. Reject unexpected headers and canonicalize forwarded headers
If your ASP.NET application forwards requests to downstream services, do not forward headers derived from untrusted input. Explicitly build the outgoing Authorization header using a validated token only.
using System.Net.Http;
using System.Threading.Tasks;
public async Task<HttpResponseMessage> ForwardRequestAsync(string userSuppliedToken, HttpClient client)
{
if (!HeaderValidation.IsValidBearerHeader($"Bearer {userSuppliedToken}"))
{
throw new HttpRequestException("Invalid Authorization header");
}
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.example.com/resource");
// Use the validated token directly; do not concatenate or forward other headers from the original request
request.Headers.Add("Authorization", $"Bearer {userSuppliedToken}");
return await client.SendAsync(request);
}
3. Avoid echoing Authorization headers in responses or logs
Ensure logging frameworks do not accidentally include the full Authorization header. Redact or omit the header when recording diagnostics.
logger.LogInformation("Request received for userId {UserId}", userId);
// Do NOT log authorizationHeader variable
4. Use ASP.NET Core built-in authentication when possible
Rely on AddAuthentication and AddJwtBearer so the framework handles Bearer token validation and rejects malformed headers automatically.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "https://auth.example.com",
ValidateAudience = true,
ValidAudience = "api-resource",
ValidateLifetime = true
};
});
5. Reject control characters at the edge
Configure Kestrel or your reverse proxy to reject requests containing newline characters in header names or values. This complements application-level validation and reduces reliance on developer discipline alone.