HIGH header injectionaspnetbasic auth

Header Injection in Aspnet with Basic Auth

Header Injection in Aspnet with Basic Auth — how this combination creates or exposes the vulnerability

Header Injection in an ASP.NET context occurs when user-controlled data is placed directly into HTTP headers without validation or sanitization. When Basic Authentication is used, the credentials are transmitted in the Authorization header as a base64-encoded string of username:password. While the encoding is not encryption, improper handling of header values on the server can still lead to security issues. For example, if an ASP.NET application reads the Authorization header and reuses it in outgoing requests or logs it without care, an attacker may inject additional header lines such as X-Forwarded-For, Set-Cookie, or other custom headers by providing a crafted payload in the original header or in other request inputs that are concatenated into headers.

In ASP.NET, the server pipeline parses headers early in the request lifecycle. If application code constructs response headers using unsanitized input—for instance, taking a query parameter or form field and assigning it to a header like X-Custom-Header—an attacker can inject newline characters (\r\n) to append or override headers. This is commonly referred to as CRLF injection. With Basic Auth, the initial Authorization header itself is typically provided by the client; however, if the server mirrors values from the request (such as a token or username) into other headers, the risk increases. For instance, reflecting the username into a custom header without validation can allow an attacker to inject control characters that split the header into multiple lines, potentially smuggling requests through proxies, bypassing access controls, or poisoning downstream caches.

Another angle specific to Basic Auth in ASP.NET is the handling of malformed or unexpected header formats. Because the Authorization header follows the scheme Basic {base64}, if the application performs string manipulation to extract the token or username (e.g., splitting on whitespace or base64 decoding without length checks), an attacker might supply newlines within the encoded string or in other parameters that later influence header construction. When the server builds outbound messages or logs, unsanitized header values can disclose sensitive information or be leveraged in HTTP response splitting, which may facilitate cross-user tampering or cache poisoning. The vulnerability is not in Basic Auth itself but in how the application treats header values derived from user input, especially when those values are concatenated into other headers or logged in raw form.

Consider an ASP.NET Core middleware that copies a custom header from the incoming request to the response without validation:

// Risky example: directly reflecting a header value
var customValue = Request.Headers["X-Custom-Input"];
Response.Headers["X-Custom-Output"] = customValue.ToString();

If an attacker sends X-Custom-Input: value\r\nSet-Cookie: session=attacker, the server may reflect this into the response, injecting a new Set-Cookie header. Even when using Basic Auth, if the application extracts the username via AuthenticationHeaderValue and then echoes part of it into another header without sanitizing line breaks, similar injection becomes possible. Proper validation, such as rejecting or stripping newline characters and using structured header APIs, is essential to prevent header manipulation.

Basic Auth-Specific Remediation in Aspnet — concrete code fixes

To mitigate Header Injection when using Basic Authentication in ASP.NET, focus on strict validation of header construction and avoiding the direct reflection of user-controlled values into headers. Always use framework-provided types for parsing authorization headers instead of manual string splitting. For outgoing requests, ensure that any values placed into headers are sanitized by disallowing carriage return and line feed characters. Below are concrete code examples demonstrating secure approaches.

1. Parsing Basic Auth safely on the server

Use AuthenticationHeaderValue from System.Net.Http.Headers to parse the Authorization header. This type handles format validation and base64 decoding without exposing raw string manipulation that could be abused.

using System;
using System.Net.Http.Headers;
using System.Text;

public bool TryParseBasicAuth(string authHeader, out string username, out string password)
{
    username = null;
    password = null;
    if (string.IsNullOrWhiteSpace(authHeader))
        return false;

    var header = AuthenticationHeaderValue.Parse(authHeader);
    if (header.Scheme != "Basic")
        return false;

    var token = Encoding.UTF8.GetString(Convert.FromBase64String(header.Parameter));
    var separatorIndex = token.IndexOf(':');
    if (separatorIndex == -1)
        return false;

    username = token.Substring(0, separatorIndex);
    password = token.Substring(separatorIndex + 1);
    return true;
}

This approach ensures the header conforms to the Basic scheme and prevents newline characters from being interpreted as header delimiters because AuthenticationHeaderValue enforces proper formatting.

2. Setting response headers safely

When assigning values to response headers, avoid concatenating raw input. Use typed APIs and explicitly disallow control characters. For example, in ASP.NET Core, prefer Response.Headers["HeaderName"] = value with validated strings, or use Add with sanitization.

public IActionResult SetCustomHeader(string userValue)
{
    // Reject or sanitize newline characters
    if (userValue.Contains("\r") || userValue.Contains("\n"))
    {
        return BadRequest("Invalid header value.");
    }

    Response.Headers["X-Safe-Custom"] = userValue;
    return Ok();
}

3. Making outbound requests with Basic Auth without leaking headers

If your ASP.NET service calls another API using Basic Auth, construct the Authorization header via AuthenticationHeaderValue and avoid injecting external data into the header format. Here is an example using HttpClient:

using System.Net.Http.Headers;

public async Task CallProtectedApiAsync(string username, string password)
{
    using var client = new HttpClient();
    var authToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}"));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authToken);

    var response = await client.GetAsync("https://api.example.com/secure");
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadAsStringAsync();
}

4. Logging and diagnostics

When logging request information, avoid dumping raw headers that may contain sensitive or injection-prone values. Redact or hash credentials and filter out newline characters.

// Safely log only necessary parts
string safeUsername = username?.Replace("\r", "").Replace("\n", "");
_logger.LogInformation("Authenticated user: {Username}", safeUsername);

By combining proper parsing with strict validation on any user-influenced data that reaches headers, you reduce the risk of Header Injection while still using Basic Authentication within ASP.NET.

Frequently Asked Questions

Can CRLF injection via headers affect APIs using Basic Auth even if credentials are base64-encoded?
Yes. The risk is not with the encoding but with how the server constructs and logs headers. If application code takes user-controlled values—including those derived from the request—and places them into other headers without stripping \r\n, an attacker can inject additional header lines regardless of the Basic Auth encoding.
Does middleBrick test for header injection in scanned APIs?
middleBrick runs a set of 12 security checks in parallel, including checks related to input validation and data exposure that can surface header manipulation risks. For details, you can scan an endpoint with the middlebrick CLI or dashboard and review prioritized findings with remediation guidance.