Header Injection in Aspnet
How Header Injection Manifests in Aspnet
Header injection in Aspnet applications occurs when user-controlled data flows into HTTP response headers without proper validation. This vulnerability allows attackers to manipulate headers like Location, Set-Cookie, Content-Type, or custom headers, potentially leading to HTTP response splitting, open redirects, or cookie manipulation.
In Aspnet Core, header injection often appears in controller actions where user input directly populates header values. Consider this vulnerable pattern:
var redirectUrl = Request.Query["returnUrl"];
Response.Redirect(redirectUrl);An attacker could supply a crafted returnUrl like http://evil.com%0d%0aSet-Cookie:%20Hacked=true, causing the server to inject malicious headers. Aspnet Framework applications face similar risks with Response.Redirect and Response.AddHeader methods.
Another common Aspnet-specific scenario involves model binding with header values:
public IActionResult GetUserProfile([FromHeader] string userId) {
var user = _userService.GetById(userId);
return View(user);
}If userId flows into response headers without validation, an attacker could manipulate the HTTP response structure. Aspnet's default model binding makes this particularly dangerous since it automatically converts header values to strongly-typed parameters.
Middleware components in Aspnet Core can also introduce header injection vulnerabilities. Custom middleware that concatenates or manipulates header values without proper sanitization creates attack surfaces:
public class CustomHeaderMiddleware {
public async Task InvokeAsync(HttpContext context) {
var customHeader = context.Request.Headers["X-Custom-Header"];
context.Response.Headers.Add("X-Processed-Header", customHeader);
}
}The vulnerability becomes critical when headers contain CRLF sequences (%0d%0a), allowing attackers to split responses and inject arbitrary headers or even entire response bodies.
Aspnet-Specific Detection
Detecting header injection in Aspnet applications requires examining both code patterns and runtime behavior. Static analysis tools can identify vulnerable code constructs, but runtime scanning with middleBrick provides comprehensive coverage by testing the actual attack surface.
middleBrick's black-box scanning approach is particularly effective for Aspnet applications. The scanner automatically tests for header injection by sending payloads containing CRLF sequences to various endpoints and monitoring responses for unexpected header modifications or response splitting.
Key detection patterns for Aspnet include:
- Controller actions accepting query parameters that flow to Response.Redirect or Response.AddHeader
- Model binding attributes like [FromHeader], [FromQuery] on parameters used in header operations
- Middleware components manipulating header values without validation
- Open redirect endpoints that accept URL parameters
- Custom authentication or authorization middleware that constructs headers from user input
middleBrick scans Aspnet applications in 5-15 seconds, testing the unauthenticated attack surface without requiring credentials. The scanner checks for 12 security categories including Authentication, BOLA/IDOR, and Input Validation, with header injection falling under the Input Validation category.
For OpenAPI/Swagger specifications, middleBrick performs additional analysis by cross-referencing spec definitions with runtime findings. This is particularly valuable for Aspnet applications using Swashbuckle or NSwag, as the scanner can identify discrepancies between documented behavior and actual implementation.
The scanner's LLM/AI security capabilities also detect if Aspnet applications serve AI endpoints vulnerable to prompt injection, which could be chained with header injection attacks for more sophisticated exploitation.
Aspnet-Specific Remediation
Remediating header injection in Aspnet applications requires a defense-in-depth approach using Aspnet's built-in security features. The primary defense is input validation and output encoding, but Aspnet provides several native mechanisms for secure header handling.
For Aspnet Core, use the built-in URL validation when handling redirects:
public IActionResult RedirectToUser([FromQuery] string returnUrl) {
if (string.IsNullOrEmpty(returnUrl) ||
!Url.IsLocalUrl(returnUrl)) {
return RedirectToAction("Index", "Home");
}
return Redirect(returnUrl);
}The Url.IsLocalUrl method validates that the URL is local to your application, preventing open redirect attacks that could lead to header injection.
For header manipulation, Aspnet Core provides the HttpResponse.Headers collection with built-in validation:
public IActionResult SetCustomHeader([FromQuery] string value) {
if (string.IsNullOrWhiteSpace(value) ||
value.Contains("
") || value.Contains("
")) {
return BadRequest("Invalid header value");
}
Response.Headers["X-Custom-Header"] = value;
return Ok();
}Always validate header values for CRLF sequences before adding them to responses. Aspnet Core automatically rejects headers containing control characters, but explicit validation provides defense-in-depth.
For Aspnet Framework applications, use HttpResponse.Redirect with validated URLs:
protected void Page_Load(object sender, EventArgs e) {
string returnUrl = Request.QueryString["returnUrl"];
if (IsValidRedirectUrl(returnUrl)) {
Response.Redirect(returnUrl);
} else {
Response.Redirect("/Default.aspx");
}
}
private bool IsValidRedirectUrl(string url) {
if (string.IsNullOrEmpty(url)) return false;
Uri uri;
return Uri.TryCreate(url, UriKind.Absolute, out uri) &&
(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps);
}Implement a whitelist approach for allowed URLs rather than attempting to block malicious patterns.
For middleware components, use Aspnet's built-in header validation:
public class SecureHeaderMiddleware {
private static readonly HashSet allowedHeaders =
new HashSet { "X-Custom-Header", "X-Processed-Header" };
public async Task InvokeAsync(HttpContext context) {
var headerValues = context.Request.Headers
.Where(h => allowedHeaders.Contains(h.Key))
.ToDictionary(h => h.Key, h => h.Value);
foreach (var header in headerValues) {
context.Response.Headers[header.Key] = header.Value;
}
await _next(context);
}
} This approach validates both header names and values against a whitelist, preventing injection of malicious headers.