HIGH ssrfexpress

Ssrf in Express

How SSRF Manifests in Express

Server-Side Request Forgery (SSRF) in Express applications typically occurs when user-controlled input is used to construct HTTP requests to internal or external resources without proper validation. In Express, this vulnerability commonly appears in routes that proxy requests, fetch external data, or integrate with third-party services.

The most frequent Express-specific SSRF patterns involve using the request or axios libraries to make outbound requests where the target URL comes directly from query parameters, request bodies, or headers. For example:

app.post('/proxy', (req, res) => {
  const targetUrl = req.body.url;
  axios.get(targetUrl)
    .then(response => res.send(response.data))
    .catch(err => res.status(500).send(err.message));
});

This endpoint is vulnerable because an attacker can supply any URL, including internal IPs like http://localhost:8080, internal APIs like http://internal-api:3000, or even cloud metadata endpoints like http://169.254.169.254/latest/meta-data/.

Express applications often expose SSRF through webhook integrations. A common pattern:

app.post('/webhook', (req, res) => {
  const webhookUrl = req.body.callback_url;
  axios.post(webhookUrl, { event: 'processed' });
  res.status(200).send('ok');
});

Here, an attacker can supply callback_url=http://localhost:8080/admin/reset to trigger internal requests.

Another Express-specific manifestation occurs with file upload handlers that process external URLs:

app.post('/upload-from-url', (req, res) => {
  const imageUrl = req.body.image_url;
  axios.get(imageUrl, { responseType: 'stream' })
    .then(response => {
      response.data.pipe(fs.createWriteStream('uploads/' + uuid()))
        .on('finish', () => res.send('uploaded'));
    });
});

This allows attackers to fetch files from internal servers or cloud metadata services, potentially exposing sensitive data.

Cloud metadata service abuse is particularly dangerous in Express apps deployed on cloud platforms. The AWS metadata service at http://169.254.169.254 can reveal IAM credentials, instance IDs, and configuration data that enables lateral movement or privilege escalation.

Express-Specific Detection

Detecting SSRF in Express applications requires both static analysis and runtime scanning. For static detection, look for patterns where user input flows into HTTP client calls without validation. middleBrick's Express-specific scanning identifies these vulnerabilities by analyzing your API endpoints and testing for SSRF conditions.

middleBrick scans Express applications by submitting test payloads to your endpoints and monitoring for SSRF indicators. The scanner attempts requests to known internal IP ranges (10.x.x.x, 172.16.x.x, 192.168.x.x), localhost, and cloud metadata services. It also tests for blind SSRF by measuring response time differences and error patterns.

For Express apps, middleBrick specifically checks:

  • Endpoints accepting URLs in query parameters (?url=)
  • Body parameters containing URLs ({ "url": "..." })
  • Headers that might contain target URLs
  • Webhook endpoints with callback URLs
  • File upload endpoints accepting external URLs

The scanner uses a 12-check methodology that includes SSRF detection as one of the core security assessments. When middleBrick identifies SSRF vulnerabilities, it provides the exact endpoint, the attack vector used, and the severity level based on the potential impact.

For runtime detection in production, consider implementing middleware that validates outbound requests. Here's an Express middleware example:

const isSafeUrl = (url) => {
  try {
    const parsed = new URL(url);
    const internalNetworks = [
      /^127\./,
      /^localhost$/, 
      /^10\./,
      /^172\.(1[6-9]|2[0-9]|3[0-1])\./,
      /^192\.168\./,
      /^169\.254\.169\.254$/, // AWS metadata
      /^169\.254\.169\.123$/ // AWS time
    ];
    
    return !internalNetworks.some(regex => regex.test(parsed.hostname));
  } catch (e) {
    return false;
  }
};

app.use((req, res, next) => {
  const urlParam = req.query.url || req.body.url;
  if (urlParam && !isSafeUrl(urlParam)) {
    return res.status(400).json({ 
      error: 'Invalid URL - external URLs only' 
    });
  }
  next();
});

This middleware blocks requests containing internal network references before they reach your business logic.

Express-Specific Remediation

Remediating SSRF in Express applications requires a defense-in-depth approach. The primary strategy is input validation combined with allowlisting of permitted domains or services.

For basic SSRF prevention, implement strict URL validation using the built-in URL class and allowlisting:

const allowedDomains = ['api.example.com', 'cdn.example.com'];

const validateUrl = (url) => {
  try {
    const parsed = new URL(url);
    return allowedDomains.includes(parsed.hostname);
  } catch (e) {
    return false;
  }
};

app.post('/safe-proxy', (req, res) => {
  const targetUrl = req.body.url;
  if (!validateUrl(targetUrl)) {
    return res.status(400).json({ 
      error: 'URL not in allowlist' 
    });
  }
  
  axios.get(targetUrl)
    .then(response => res.send(response.data))
    .catch(err => res.status(502).send('Proxy error'));
});

This approach ensures only pre-approved domains can be accessed, eliminating the ability to target internal resources.

For more sophisticated scenarios, use a dedicated SSRF prevention library like ssrf-filter:

const SSRF = require('ssrf-filter');
const ssrf = new SSRF({
  defaultPort: 443,
  defaultProtocol: 'https',
  allowHttp: false,
  allowFtp: false,
  allowFile: false,
  allowLocal: false,
  allowPrivate: false,
  timeout: 5000
});

app.post('/filtered-proxy', async (req, res) => {
  const targetUrl = req.body.url;
  
  try {
    await ssrf.check(targetUrl);
    const response = await axios.get(targetUrl);
    res.send(response.data);
  } catch (err) {
    if (err.message.includes('disallowed')) {
      return res.status(400).json({ error: 'Invalid URL' });
    }
    res.status(502).send('Proxy error');
  }
});

The ssrf-filter library provides comprehensive protection against various SSRF vectors including DNS rebinding, IDN homograph attacks, and malformed URLs.

For webhook endpoints, implement a verification system that only allows URLs from trusted sources:

const webhookWhitelist = new Set([
  'https://api.stripe.com',
  'https://webhook.site'
]);

app.post('/secure-webhook', (req, res) => {
  const callbackUrl = req.body.callback_url;
  
  if (!webhookWhitelist.has(callbackUrl)) {
    return res.status(400).json({ error: 'Untrusted webhook URL' });
  }
  
  // Process webhook and send to callback
  axios.post(callbackUrl, { status: 'processed' });
  res.status(200).send('ok');
});

For file upload scenarios, use a dedicated service like AWS S3 presigned URLs instead of allowing arbitrary URL fetching:

const AWS = require('aws-sdk');
const s3 = new AWS.S3();

app.post('/upload-secure', async (req, res) => {
  const fileName = req.body.file_name;
  const mimeType = req.body.mime_type;
  
  const params = {
    Bucket: 'your-upload-bucket',
    Key: fileName,
    ContentType: mimeType,
    ACL: 'private'
  };
  
  try {
    const uploadUrl = await s3.getSignedUrl('putObject', params);
    res.json({ upload_url: uploadUrl });
  } catch (err) {
    res.status(500).send('Upload preparation failed');
  }
});

This approach eliminates SSRF risk by using pre-signed URLs that only allow uploads to your specific S3 bucket.

Related CWEs: ssrf

CWE IDNameSeverity
CWE-918Server-Side Request Forgery (SSRF) CRITICAL
CWE-441Unintended Proxy or Intermediary (Confused Deputy) HIGH

Frequently Asked Questions

How does SSRF differ from other injection attacks in Express?

SSRF specifically targets the server's ability to make outbound requests, while other injection attacks target the server's processing of input. In Express, SSRF vulnerabilities occur when user input is used to construct URLs for axios, fetch, or other HTTP clients. Unlike SQL injection or XSS, SSRF doesn't modify application logic but instead exploits the server's network access to reach internal resources or external services on behalf of the attacker.

Can SSRF lead to data exfiltration in Express applications?

Yes, SSRF can enable data exfiltration through several Express-specific mechanisms. Attackers can use SSRF to access cloud metadata services (like AWS's 169.254.169.254) to retrieve IAM credentials, instance IDs, and configuration data. They can also target internal APIs to extract database credentials, API keys, or user data. Additionally, SSRF can be combined with blind techniques where the server's response time or error messages reveal information about internal systems.