HIGH symlink attackexpresshmac signatures

Symlink Attack in Express with Hmac Signatures

Symlink Attack in Express with Hmac Signatures — how this specific combination creates or exposes the vulnerability

A symlink attack in an Express application that uses Hmac signatures occurs when an attacker leverages file system trust boundaries to cause the server to sign or serve content it should not. This typically happens when user-influenced paths are used to locate files that are then read and included in responses, such as static assets or configuration files, while the server also uses Hmac signatures to authorize or verify those resources.

Consider an Express route that serves a file based on a user-supplied identifier and validates integrity using an Hmac. If the identifier is resolved to a file path without canonicalization and the application follows symbolic links, an attacker can place a symlink that points to a sensitive file outside the intended directory. When the server reads the file to compute or verify the Hmac, it may inadvertently process or expose data that should remain protected. For example, an attacker could trick the server into signing or returning contents of /etc/passwd or application secrets if the path traversal is possible through symlink resolution.

In this context, the Hmac signature does not protect against unauthorized file access because the signature is computed over data the attacker can influence indirectly through the filesystem. The vulnerability is not in the Hmac algorithm itself, but in the way file paths are resolved before the Hmac is applied. If the server uses a predictable naming scheme and symlinks are allowed in the document root or temporary directories, an attacker can create a symlink with a name that results in a valid Hmac signature for a malicious file. This can lead to data exposure or unauthorized actions being authenticated as legitimate by the server.

Real-world attack patterns such as CVE-2022-24999-style path traversal and symlink races highlight the risk when file system operations are not strictly confined. Even when Express middleware enforces some level of path validation, permissive symlink handling can bypass intended directory restrictions. The server’s trust in the filesystem location, combined with the assumption that an Hmac signature guarantees authenticity, creates a scenario where an attacker can manipulate which file is signed or returned, undermining the integrity guarantees the signature is meant to provide.

Hmac Signatures-Specific Remediation in Express — concrete code fixes

To mitigate symlink risks in Express when using Hmac signatures, ensure that file paths are resolved to their canonical form before any I/O or signing operation. Use Node.js built-in methods to eliminate symlinks and prevent directory traversal. Below are concrete, working examples that demonstrate secure handling of files with Hmac verification in Express.

Secure file serving with canonical paths and Hmac verification

const express = require('express');
const fs = require('fs').promises;
const crypto = require('crypto');
const path = require('path');

const app = express();
const SECRET = process.env.HMAC_SECRET || 'replace-with-strong-secret';

function computeHmac(filePath) {
  const hmac = crypto.createHmac('sha256', SECRET);
  hmac.update(filePath);
  return hmac.digest('hex');
}

async function serveFileSafe(req, res) {
  // User input should be treated as untrusted
  const requested = req.query.file;
  if (!requested) {
    return res.status(400).send('Missing file parameter');
  }

  // Build a path confined to a specific directory
  const baseDir = path.resolve(__dirname, 'public');
  const unsafePath = path.join(baseDir, requested);

  // Canonicalize: resolve symlinks and normalize
  let canonicalPath;
  try {
    canonicalPath = path.resolve(unsafePath);
  } catch (err) {
    return res.status(400).send('Invalid path');
  }

  // Ensure the canonical path is still inside the allowed directory
  if (!canonicalPath.startsWith(baseDir)) {
    return res.status(403).send('Path traversal detected');
  }

  // Verify no symlinks remain within the resolved path
  const normalized = path.normalize(canonicalPath);
  if (normalized !== canonicalPath) {
    return res.status(403).send('Path contains unsafe segments');
  }

  // Perform filesystem operations only after validation
  try {
    const data = await fs.readFile(canonicalPath);
    const expectedSignature = computeHmac(canonicalPath);
    const receivedSignature = req.query.signature;

    // Constant-time comparison to avoid timing attacks
    const isValid = crypto.timingSafeEqual(
      Buffer.from(expectedSignature, 'hex'),
      Buffer.from(receivedSignature || '', 'hex')
    );

    if (!isValid) {
      return res.status(401).send('Invalid signature');
    }

    res.set('Content-Type', 'text/plain');
    res.send(data);
  } catch (err) {
    if (err.code === 'ENOENT') {
      return res.status(404).send('File not found');
    }
    res.status(500).send('Server error');
  }
}

app.get('/files', serveFileSafe);

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Key remediation practices

  • Always resolve paths with path.resolve() and validate against a strict base directory.
  • Use fs.stat or similar checks if you need to explicitly reject symlinks (e.g., stat(path).then(stats => stats.isSymbolicLink())).
  • Apply constant-time comparisons (e.g., crypto.timingSafeEqual) when verifying Hmac signatures to prevent timing attacks.
  • Avoid serving files directly based on user input; prefer serving files by mapped identifiers or IDs that are translated server-side to filesystem locations.

By combining strict path canonicalization with robust Hmac verification, you reduce the risk that symlink-based attacks can bypass authentication or integrity checks in Express applications.

Frequently Asked Questions

How can I detect symlink risks during an API scan with middleBrick?
middleBrick scans unauthenticated attack surfaces and includes checks for unsafe file operations and path traversal; review its findings for indicators of symlink exposure and follow the provided remediation guidance to harden path handling and file access in Express.
Does middleBrick test Hmac signature implementation weaknesses?
Yes, as part of its Input Validation and Property Authorization checks, middleBrick examines how signatures are generated and verified, highlighting issues such as missing canonicalization and timing comparison weaknesses that could be exploited alongside symlink vectors.