HIGH crlf injectionbasic auth

Crlf Injection with Basic Auth

How Crlf Injection Manifests in Basic Auth

CRLF injection in Basic Auth contexts occurs when attackers manipulate line endings to inject additional HTTP headers or control characters into authentication flows. This attack exploits how Basic Auth credentials are encoded and transmitted, particularly in scenarios where user input is concatenated into HTTP headers or Authorization headers are constructed dynamically.

The most common Basic Auth CRLF injection vector appears when applications construct Authorization headers using user-controlled input. Consider this vulnerable pattern:

const username = req.body.username; // User input
const password = req.body.password; // User input
const authHeader = 'Basic ' + Buffer.from(username + ':' + password).toString('base64');
res.setHeader('Authorization', authHeader);

If an attacker submits a username containing newline characters like admin%0D%0ABasic%20YWRtaW46cGFzc3dvcmQ%3D, the server might interpret this as two separate headers, potentially bypassing authentication or injecting malicious headers.

Another Basic Auth-specific scenario involves proxy servers or middleware that log or forward authentication headers. When these systems concatenate or manipulate Basic Auth strings without proper sanitization, CRLF characters can break the intended header structure:

// Vulnerable proxy logging
const logEntry = `${timestamp} - ${authHeader} - ${requestPath}`;
// If authHeader contains CRLF, log format breaks

API gateways that perform Basic Auth validation on behalf of downstream services are also susceptible. A malformed Authorization header with embedded CRLF sequences might cause the gateway to validate one set of credentials while the downstream service receives different headers entirely.

Rate limiting mechanisms that track Basic Auth credentials are vulnerable too. If rate limit keys are constructed from username:password combinations without proper encoding, an attacker could manipulate the key structure using CRLF characters, potentially bypassing rate limits or causing denial of service to other users sharing similar credential patterns.

Basic Auth-Specific Detection

Detecting CRLF injection in Basic Auth requires understanding how credentials are parsed and validated. The first step is examining how your application constructs Authorization headers from user input. Look for patterns where username or password values are directly concatenated without validation or encoding.

Effective detection involves scanning for newline characters in authentication contexts. Here's a Node.js example using middleware to detect CRLF injection attempts:

function detectCrlfInjection(req, res, next) {
  const authHeader = req.get('Authorization');
  if (authHeader && /\r|\n/.test(authHeader)) {
    console.warn('Potential CRLF injection detected:', authHeader);
    return res.status(400).json({ error: 'Invalid header format' });
  }
  next();
}

For Basic Auth specifically, you need to decode and inspect the credentials themselves. Since Basic Auth credentials are base64-encoded, CRLF characters might appear as encoded sequences like %0D%0A in the URL-encoded form or as literal line breaks in the decoded form:

function validateBasicAuthCredentials(authHeader) {
  if (!authHeader.startsWith('Basic ')) return false;
  
  const encodedCreds = authHeader.substring(6);
  let decodedCreds;
  try {
    decodedCreds = Buffer.from(encodedCreds, 'base64').toString('utf8');
  } catch (e) {
    return false;
  }
  
  // Check for CRLF in decoded credentials
  if (/\r|\n/.test(decodedCreds)) {
    return false; // Reject credentials containing line breaks
  }
  
  return true;
}

Automated scanning tools like middleBrick can detect these vulnerabilities by testing for CRLF injection in Basic Auth endpoints. The scanner attempts to inject newline characters into username and password fields, then analyzes responses for signs of header injection or authentication bypass. middleBrick's black-box scanning approach tests the actual runtime behavior without requiring source code access.

Runtime detection should also monitor for unusual Authorization header patterns. Log analysis can reveal repeated attempts with encoded newline characters or credentials that decode to contain unexpected line breaks. Setting up alerts for such patterns helps identify ongoing CRLF injection attempts.

Basic Auth-Specific Remediation

Remediating CRLF injection in Basic Auth contexts requires a defense-in-depth approach. The most fundamental fix is proper input validation and sanitization of all user-controlled values that contribute to HTTP headers or authentication data.

Here's a secure Basic Auth implementation that prevents CRLF injection:

const crypto = require('crypto');

function createSecureAuthHeader(username, password) {
  // Validate input - reject any strings containing control characters
  if (/[\x00-\x1F\x7F]/.test(username) || /[\x00-\x1F\x7F]/.test(password)) {
    throw new Error('Invalid characters in credentials');
  }
  
  // Construct credentials safely
  const credentials = `${username}:${password}`;
  const encodedCreds = Buffer.from(credentials).toString('base64');
  
  // Return properly formatted header
  return `Basic ${encodedCreds}`;
}

// Usage
const authHeader = createSecureAuthHeader('user', 'pass');
res.setHeader('Authorization', authHeader);

For applications that need to handle Basic Auth credentials, implement strict decoding and validation:

function parseBasicAuthHeader(authHeader) {
  if (!authHeader || !authHeader.startsWith('Basic ')) {
    return null;
  }
  
  const encodedCreds = authHeader.substring(6);
  let decodedCreds;
  
  try {
    decodedCreds = Buffer.from(encodedCreds, 'base64').toString('utf8');
  } catch (e) {
    return null; // Invalid base64 encoding
  }
  
  // Check for CRLF injection
  if (/\r|\n/.test(decodedCreds)) {
    return null; // Reject credentials with line breaks
  }
  
  const [username, password] = decodedCreds.split(':', 2);
  if (!username || !password) {
    return null; // Invalid format
  }
  
  return { username, password };
}

Framework-specific protections are also important. In Express.js, use built-in middleware that properly handles Basic Auth:

const express = require('express');
const basicAuth = require('express-basic-auth');

const app = express();

app.use(basicAuth({
  users: { 'admin': 'password' },
  challenge: true,
  unauthorizedResponse: 'Authentication required'
}));

The key remediation principles are: validate all user input for control characters, use framework-provided authentication mechanisms rather than custom implementations, and implement runtime detection for suspicious patterns. middleBrick's scanning can verify these protections by attempting CRLF injection attacks and confirming they're properly blocked.

For production environments, combine these code-level fixes with monitoring that alerts on authentication anomalies, such as repeated attempts with encoded newline characters or credentials that decode to contain unexpected patterns.

Frequently Asked Questions

How can I test if my Basic Auth implementation is vulnerable to CRLF injection?
Test by attempting to authenticate with credentials containing newline characters, either as literal line breaks or URL-encoded (%0D%0A). Use tools like curl with encoded newlines: curl -H "Authorization: Basic $(echo -n 'user%0D%0Aadmin:pass' | base64)" https://your-api.com. A secure implementation should reject these credentials. You can also use middleBrick's automated scanning to test for CRLF vulnerabilities without manual testing.
Does middleBrick detect CRLF injection vulnerabilities in Basic Auth endpoints?
Yes, middleBrick's black-box scanning tests Basic Auth endpoints for CRLF injection by attempting to inject newline characters into authentication credentials and analyzing responses for signs of header injection or authentication bypass. The scanner runs 12 security checks including authentication bypass testing, and provides specific findings with severity levels and remediation guidance. middleBrick tests the actual runtime behavior of your API without requiring source code access or credentials.