HIGH crlf injectionexpress

Crlf Injection in Express

How Crlf Injection Manifests in Express

Crlf Injection in Express applications typically occurs when user-controlled data flows into HTTP headers, response splitting, or log files without proper sanitization. Express's middleware architecture and flexible request/response handling create specific attack vectors that developers must understand.

The most common Express-specific manifestation appears in custom middleware that processes request headers. Consider this vulnerable pattern:

app.use((req, res, next) => {
  const customHeader = req.get('X-Custom-Header');
  res.setHeader('X-Processed-Header', customHeader);
  next();
});

An attacker can inject CRLF sequences (%0D%0A or %0D%0A%0D%0A) into the X-Custom-Header value, allowing them to add arbitrary headers or split responses. This becomes particularly dangerous when combined with Express's res.redirect() or res.download() methods.

Another Express-specific vector involves the res.append() method, which concatenates values without sanitization:

app.get('/report', (req, res) => {
  const filename = req.query.filename || 'report.pdf';
  res.append('Content-Disposition', `attachment; filename="${filename}"`);
  res.download(`./reports/${filename}`);
});

If an attacker requests /report?filename=foo.pdf%0A%0ASet-Cookie:%20evil=true, they can inject headers into the response.

Express's logging middleware also creates CRLF injection opportunities. The default morgan logger writes raw request data to logs:

const accessLogStream = fs.createWriteStream('access.log', { flags: 'a' });
app.use(morgan('combined', { stream: accessLogStream }));

Malicious User-Agent headers containing CRLF can corrupt log files and potentially execute commands if logs are processed by vulnerable systems.

Body parsing middleware presents another vector. Express's express.urlencoded() and express.json() parsers don't inherently sanitize CRLF in header-like fields within request bodies, particularly in form submissions that mimic HTTP headers.

The res.cookie() method can also be exploited when cookie values contain CRLF sequences, allowing attackers to set multiple cookies or manipulate Set-Cookie headers in ways that bypass security controls.

Express-Specific Detection

Detecting CRLF injection in Express requires both static analysis and dynamic testing. Static analysis should focus on code patterns where user input flows to headers or logs.

Manual code review should examine:

# Search for dangerous patterns
grep -r "req\.get\|req\.header\|req\.query\|req\.params" routes/ \
  | grep -E "(res\.set|res\.header|res\.append|res\.cookie)"

Look specifically for concatenation without sanitization, especially around user-controlled variables in header construction.

Dynamic testing with middleBrick provides comprehensive coverage for Express applications. middleBrick's black-box scanning tests unauthenticated endpoints for CRLF injection across 12 security categories, including header injection patterns specific to Express's middleware chain.

For Express applications, middleBrick scans:

  • Request header injection points in custom middleware
  • Response splitting vulnerabilities in redirect and download handlers
  • Logging injection in morgan and custom loggers
  • Cookie manipulation through res.cookie() calls
  • Body parsing edge cases with form-encoded data
  • WebSocket handshake header injection

middleBrick's scanning takes 5-15 seconds and requires no authentication or configuration. Simply provide your Express app's URL and receive an A-F security score with specific findings about CRLF injection vulnerabilities, including the exact request patterns that trigger them.

Additional Express-specific detection involves testing middleware ordering. Since Express executes middleware sequentially, CRLF payloads might only work when certain middleware runs before others. Test with different authentication states and request paths to uncover conditional vulnerabilities.

Monitor your application logs for suspicious patterns like multiple Set-Cookie headers from single requests, unexpected header values containing newlines, or log entries with embedded CRLF sequences that break log formatting.

Express-Specific Remediation

Express provides several native approaches for CRLF injection prevention. The most effective strategy combines input validation, proper header handling, and secure middleware patterns.

For header processing, always sanitize user input before using it in HTTP headers:

const sanitizeHeader = (input) => {
  return input.replace(/[
]+/g, ' ').trim();
};

app.use((req, res, next) => {
  const customHeader = sanitizeHeader(req.get('X-Custom-Header'));
  res.setHeader('X-Processed-Header', customHeader);
  next();
});

Apply this sanitization pattern consistently across all header operations, including res.set(), res.append(), and res.cookie().

For response splitting prevention in Express, use the built-in res.location() method instead of manual header manipulation:

// Vulnerable
app.get('/redirect', (req, res) => {
  const url = req.query.url || '/';
  res.set('Location', url);
  res.status(302).end();
});

// Secure
app.get('/redirect', (req, res) => {
  const url = req.query.url || '/';
  res.location(url).redirect(302);
});

Express's res.location() automatically validates and encodes URLs, preventing CRLF injection through location headers.

For file downloads, validate and sanitize filenames before using them in Content-Disposition headers:

app.get('/download', (req, res) => {
  const filename = path.basename(req.query.filename || 'file.txt');
  const sanitized = filename.replace(/[^a-zA-Z0-9._-]/g, '_');
  
  res.download(`./files/${sanitized}`, sanitized, (err) => {
    if (err) {
      res.status(404).send('File not found');
    }
  });
});

This approach prevents directory traversal and CRLF injection while maintaining usability.

For logging middleware, use Express's built-in security features or configure third-party loggers to escape special characters:

const escapeCRLF = (str) => str.replace(/[
]/g, ' ');

const secureMorgan = morgan((tokens, req, res) => {
  return {
    ip: escapeCRLF(tokens['remote-addr'](req, res)),
    method: escapeCRLF(tokens.method(req, res)),
    url: escapeCRLF(tokens.url(req, res)),
    status: tokens.status(req, res),
    'user-agent': escapeCRLF(tokens['user-agent'](req, res))
  };
});

app.use(secureMorgan);

// Or use helmet for comprehensive header security
app.use(helmet({
  hsts: false // disable if not needed
}));

The helmet middleware provides additional protections against header injection and other Express-specific vulnerabilities.

For WebSocket applications built with Express, validate all handshake headers and upgrade requests:

const wss = new WebSocket.Server({ noServer: true });

server.on('upgrade', (req, socket, head) => {
  if (!req.headers['sec-websocket-key']) {
    socket.destroy();
    return;
  }
  
  const sanitizedHeaders = Object.keys(req.headers).reduce((acc, key) => {
    acc[key] = req.headers[key].replace(/[
]/g, ' ');
    return acc;
  }, {});
  
  wss.handleUpgrade(req, socket, head, (ws) => {
    wss.emit('connection', ws, req);
  });
});

This ensures WebSocket upgrade requests cannot contain malicious CRLF sequences that might compromise the Express application.

Frequently Asked Questions

How does CRLF injection differ between Express and other Node.js frameworks?
Express's middleware-based architecture creates unique CRLF injection patterns. Unlike Koa or Fastify, Express allows arbitrary header manipulation through res.set() and res.append() without built-in sanitization. Express's flexible request/response cycle means CRLF payloads can affect middleware ordering, making some vulnerabilities conditional on which middleware executes first. Additionally, Express's extensive ecosystem of third-party middleware increases the attack surface, as each middleware might handle headers differently.
Can CRLF injection in Express lead to more severe attacks?
Yes, CRLF injection in Express can escalate to critical vulnerabilities. Successful header injection can enable response splitting attacks, allowing attackers to steal session cookies or perform phishing by injecting malicious content into responses. In applications that log request data to files or databases, CRLF injection can corrupt log integrity or enable log injection attacks. When combined with Express's file serving capabilities, attackers might manipulate Content-Disposition headers to trick users into downloading malicious files with crafted names.