HIGH crlf injectionaspnetbasic auth

Crlf Injection in Aspnet with Basic Auth

Crlf Injection in Aspnet with Basic Auth

Crlf Injection occurs when an attacker can inject carriage return (CR, \r) and line feed (\n) sequences into an HTTP header, causing the header to be split and additional headers or response content to be injected. In ASP.NET applications that use HTTP Basic Authentication via the Authorization header, this risk arises when user-controlled input is reflected into headers without proper sanitization or validation. Although Basic Authentication credentials are base64-encoded in the Authorization header value, many developers mistakenly believe this prevents header injection. In practice, the vulnerability is not about tampering with credentials but about how the application processes other user-supplied data—such as request parameters, headers, or cookies—and reflects them into outgoing headers.

Consider an ASP.NET Core endpoint that echoes a user-supplied filename into a Content-Disposition header for a file download. If the input is not validated, an attacker can supply a value like report.pdf\r\nX-Content-Type-Options: nosniff. The server may parse this as two separate headers, causing the injected header to be interpreted by the client. When Basic Authentication is in use, the presence of the Authorization header does not mitigate this class of injection; the server must still validate and encode any data that will be placed into headers. The combination of Basic Auth and reflected user input creates a misleading sense of security, as the credentials are separate from the attacker-controlled header values. Attackers exploit this to perform HTTP response splitting, which can lead to cache poisoning, cross-user header injection, or even HTML injection in the browser when the response is rendered.

ASP.NET Core’s request pipeline normalizes headers before they reach application code, but developers are responsible for ensuring that values placed into headers are safe. For example, using Response.Headers["X-Custom"] = userInput without validation allows injection if userInput contains \r\n. The framework does not automatically reject these sequences in header values assigned by application code. In the context of Basic Auth, the runtime does not parse the Authorization header value beyond base64 decoding; any injection must be prevented at the point where the application writes to other headers. Attack patterns such as response splitting, header smuggling, or XSS via injected headers are well documented in the OWASP API Top 10 and CWE mappings, and they apply regardless of the authentication mechanism in use.

Real-world exploitation typically involves sending a crafted request with injected CRLF sequences and observing whether the injected headers appear in the response. Tools that perform automated scanning can detect these issues by sending a probe such as GET /download?file=report.pdf%0D%0AX-Content-Type-Options:%20nosniff and inspecting the parsed headers. In ASP.NET, developers should treat all user input as untrusted, apply strict allowlists for filenames and header values, and use framework-provided encoding functions. The presence of Basic Authentication does not reduce the need for these practices; it only secures the initial request identity, not the integrity of subsequent header manipulation.

Basic Auth-Specific Remediation in Aspnet

Remediation focuses on preventing CRLF characters from being written into HTTP headers and ensuring that Basic Authentication is implemented correctly without creating false confidence. In ASP.NET Core, avoid directly assigning user input to headers. Instead, use strongly typed models and validation to enforce safe values. For example, when generating a Content-Disposition header for file downloads, extract the filename safely and use framework APIs that do not allow header splitting.

Below are concrete code examples demonstrating secure handling in ASP.NET Core with Basic Authentication. The first example shows an insecure approach where user input is naively assigned to a header, followed by a corrected version that sanitizes input.

// Insecure example — do not use
[Authorize(AuthenticationSchemes = "Basic")]
[HttpGet("download")]
public IActionResult DownloadInsecure(string file)
{
    // UNSAFE: user input directly placed into a header
    Response.Headers["Content-Disposition"] = $"attachment; filename={file}";
    return File(GetFileStream(file), "application/octet-stream");
}

// Secure example with input validation and encoding
[Authorize(AuthenticationSchemes = "Basic")]
[HttpGet("download")]
public IActionResult DownloadSecure(string file)
{
    // Validate filename: allow only alphanumeric, dash, underscore, and dot
    if (!System.Text.RegularExpressions.Regex.IsMatch(file, @"^[a-zA-Z0-9._-]+$"))
    {
        return BadRequest("Invalid filename.");
    }

    // Use Path.GetFileName to remove directory traversal attempts
    string safeFileName = Path.GetFileName(file);
    string headerValue = $"attachment; filename=\"{safeFileName}\"";
    Response.Headers["Content-Disposition"] = headerValue;
    return File(GetFileStream(file), "application/octet-stream");
}

These examples use the Basic Authentication scheme configured via authentication middleware. Ensure your Startup or Program configuration includes the necessary services and policies without relying on header values for security decisions.

// Program.cs or Startup.cs configuration
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
    .AddScheme(BasicAuthenticationDefaults.AuthenticationScheme, null);
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();

Additional mitigations include implementing a global filter to validate outgoing headers, using framework features like HeaderNames constants, and avoiding concatenation when building header values. Regular security testing with a scanner that supports CRLF injection checks, such as middleBrick, can help identify overlooked injection points. middleBrick’s scans include checks aligned with OWASP API Top 10 and can be integrated into CI/CD pipelines using the GitHub Action to fail builds if risky headers are detected.

Frequently Asked Questions

Does using Basic Authentication prevent CRLF injection in ASP.NET?
No. Basic Authentication secures the initial request identity by validating credentials in the Authorization header, but it does not prevent an attacker from injecting CRLF sequences into other headers if user input is reflected without validation. Always validate and encode any data placed into HTTP headers.
How can I test my ASP.NET endpoint for CRLF injection?
Send requests with encoded CRLF sequences (e.g., %0D%0A or \r\n) in user-controlled parameters or headers and inspect the response headers for splitting. Automated scanners like middleBrick can perform these checks and map findings to frameworks such as OWASP API Top 10.