HIGH CWE-113 Input Validation

CWE-113 in APIs

CWE ID
CWE-113
Category
Input Validation
Severity
MEDIUM
Short Name
Response Splitting

What is CWE-113

CWE-113: Improper Neutralization of CRLF Sequences in HTTP Headers ("HTTP Response Splitting") is a critical web application vulnerability where untrusted data is not properly neutralized before being included in HTTP headers. The weakness allows attackers to inject Carriage Return (CR) and Line Feed (LF) characters, enabling them to craft malicious HTTP responses that can manipulate browser behavior, perform session fixation, or conduct phishing attacks.

CWE-113 in API Contexts

In API development, CWE-113 manifests when API endpoints construct HTTP responses using untrusted input without proper sanitization. This commonly occurs in:

  • Authorization headers built from user input
  • Custom response headers reflecting user data
  • Redirect URLs constructed from query parameters
  • Error messages or debug information in headers
  • API keys or tokens reflected in response headers

Consider an API that constructs a Location header for redirects using a user-supplied URL parameter. If an attacker provides a URL containing CRLF sequences, they can inject arbitrary headers or even start a new HTTP response entirely. This becomes particularly dangerous in APIs that serve as middleware or proxy services, where malicious headers might be forwarded to downstream services.

Detection

Detecting CWE-113 requires both manual code review and automated testing. Key detection strategies include:

  • Static analysis to identify string concatenation operations that build HTTP headers
  • Dynamic testing with payloads containing %0D%0A sequences to trigger CRLF injection
  • Security scanning tools that specifically test for HTTP response splitting
  • Input validation testing across all API endpoints that construct headers

middleBrick Detection: middleBrick's HTTP Response Splitting check specifically tests for CRLF injection vulnerabilities by injecting payloads containing %0D%0A sequences into HTTP headers. The scanner examines responses for signs of header injection, including unexpected headers, response splitting, or XSS payloads in reflected headers. For APIs with OpenAPI specifications, middleBrick cross-references parameter definitions with runtime testing to identify parameters that might be reflected in headers without proper validation.

Remediation

Fixing CWE-113 requires a defense-in-depth approach with proper input validation and output encoding. Here are practical remediation strategies with code examples:

1. Input Validation and Sanitization

// Vulnerable code
const url = req.query.redirectUrl;
res.setHeader('Location', url);
res.redirect(302);

// Secure implementation
function sanitizeUrl(input) {
  const url = new URL(input);
  
  // Validate scheme
  const allowedSchemes = ['https', 'http'];
  if (!allowedSchemes.includes(url.protocol.slice(0, -1))) {
    throw new Error('Invalid URL scheme');
  }
  
  // Remove CRLF characters
  if (input.includes('
') || input.includes('
')) {
    throw new Error('CRLF injection detected');
  }
  
  return url.toString();
}

// Usage
const redirectUrl = sanitizeUrl(req.query.redirectUrl);
res.setHeader('Location', redirectUrl);
res.redirect(302);

2. Header Construction Best Practices

# Vulnerable code
response_headers = {
    'X-Custom-Header': user_input,
    'Content-Type': 'application/json'
}

# Secure implementation
from urllib.parse import urlparse

def build_secure_headers(user_input):
    # Validate and sanitize user input
    if '\r' in user_input or '\n' in user_input:
        raise ValueError('CRLF characters detected')
    
    # Additional validation based on header context
    if 'X-Custom-Header' in header_name:
        # Apply specific validation rules
        if len(user_input) > 1000:
            raise ValueError('Header value too long')
    
    return user_input

# Usage
user_input = build_secure_headers(user_input)
response_headers = {
    'X-Custom-Header': user_input,
    'Content-Type': 'application/json'
}

3. Using Framework Security Features

// Spring Boot secure header handling
@RestController
@RequestMapping("/api")
public class SecureApiController {
    
    @GetMapping("/redirect")
    public ResponseEntity secureRedirect(@RequestParam String url) {
        // Validate URL
        try {
            URI uri = new URI(url);
            if (uri.getScheme() == null || 
                (!uri.getScheme().equals("https") && !uri.getScheme().equals("http"))) {
                throw new IllegalArgumentException("Invalid URL scheme");
            }
            
            // Check for CRLF injection
            if (url.contains("\r") || url.contains("\n")) {
                throw new IllegalArgumentException("CRLF injection detected");
            }
            
            return ResponseEntity.status(HttpStatus.FOUND)
                    .location(uri)
                    .build();
                    
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException("Invalid URL format");
        }
    }
}

4. Comprehensive Security Testing

# Test for CRLF injection using curl
curl -v "http://your-api.com/redirect?url=http://example.com%0D%0AX-Injected-Header: malicious-value"

# Expected: Server should reject or properly encode the input
# Actual: Server should not include the injected header in the response

Frequently Asked Questions

How does CRLF injection differ from other injection attacks?
CRLF injection specifically targets the structure of HTTP protocol by injecting control characters that break the protocol format. Unlike SQL injection or XSS that target application logic, CRLF injection manipulates the transport layer itself, allowing attackers to inject new headers, split responses, or perform response smuggling attacks.
Can middleBrick detect CRLF injection in APIs that use GraphQL?
Yes, middleBrick tests GraphQL endpoints for CRLF injection by injecting payloads into all string parameters and headers. The scanner examines responses for signs of header manipulation, even in GraphQL contexts where responses are JSON-formatted. This includes testing mutations, queries, and any custom HTTP headers that GraphQL servers might use.