Ssrf Server Side in Express (Javascript)
Ssrf Server Side in Express with Javascript — how this specific combination creates or exposes the vulnerability
Server-side request forgery (SSRF) in Express with JavaScript occurs when an Express application uses attacker-controlled input to form HTTP requests to internal or external services. In JavaScript/Node.js, common patterns such as http.request, https.request, or libraries like axios and node-fetch are often invoked with URLs derived from query parameters, headers, or request bodies. If these values are not strictly validated and constrained, an attacker can coerce the server to make requests to internal metadata services (e.g., http://169.254.169.254 on cloud environments), internal ports on the host (e.g., http://localhost:22), or sensitive internal endpoints that are not exposed to the public internet.
Express applications that directly pass user input into request configurations are vulnerable. For example, using req.query.url to drive an outbound HTTP call without validating the host or scheme enables network-based SSRF. The SSRF attack surface is expanded when the server performs DNS resolution internally, follows redirects automatically, or trusts non-routable IP addresses (e.g., 0.0.0.0 or private RFC1918 ranges). In cloud and containerized environments, SSRF can lead to metadata service credential harvesting, internal service enumeration, or access to instance metadata that should never be exposed.
Because SSRF is frequently an unauthenticated attack surface, an Express endpoint that does not require authentication for certain routes can be exploited at scale. Attack patterns include probing internal infrastructure, bypassing firewall rules, and leveraging the server as a proxy for external scanning or data exfiltration. MiddleBrick’s unauthenticated black-box scans include SSRF among its 12 parallel security checks, detecting indicators such as unexpected outbound connections to internal IP ranges, missing network-level restrictions, and unsafe handling of redirects. These findings are surfaced in the scan report with severity, contextual risk notes, and remediation guidance, without the tool making changes to your application.
Javascript-Specific Remediation in Express — concrete code fixes
To remediate SSRF in Express with JavaScript, validate and sanitize all inputs that influence outbound requests. Use an allowlist approach for URLs, enforce strict schemes (e.g., https), and avoid passing raw user input to HTTP clients. Prefer robust libraries with built-in safeguards, and explicitly disable redirects and internal IP destinations.
Example of a vulnerable Express route:
const express = require('express');
const axios = require('axios');
const app = express();
app.get('/proxy', async (req, res) => {
const targetUrl = req.query.url; // user-controlled
const response = await axios.get(targetUrl);
res.send(response.data);
});
app.listen(3000);
This pattern is unsafe because targetUrl can point to internal services or metadata endpoints. An attacker can supply http://169.254.169.254/latest/meta-data/ or http://localhost:27017 to probe internal resources.
Secure version with validation and safe defaults:
const express = require('express');
const axios = require('axios');
const { URL } = require('url');
function isValidEndpoint(url) {
let parsed;
try {
parsed = new URL(url);
} catch (err) {
return false;
}
// Allow only HTTPS to prevent SSRF via malicious redirects
if (parsed.protocol !== 'https:') return false;
// Block private and non-routable IPs
const privateRanges = /^10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\./;
if (privateRanges.test(parsed.hostname)) return false;
// Optionally restrict to a specific set of hostnames
const allowedHosts = ['api.example.com', 'data.example.com'];
if (!allowedHosts.includes(parsed.hostname)) return false;
return true;
}
app.get('/proxy', async (req, res) => {
const targetUrl = req.query.url;
if (!isValidEndpoint(targetUrl)) {
return res.status(400).send('Invalid endpoint');
}
try {
const response = await axios.get(targetUrl, {
maxRedirects: 0, // prevent SSRF via open redirects
validateStatus: null,
});
// Inspect response cautiously; avoid passing raw responses to clients
res.json({ status: response.status });
} catch (err) {
res.status(502).send('Bad Gateway');
}
});
app.listen(3000);
Key practices:
- Use
new URL(input)to normalize and parse user input. - Restrict schemes to
httpsunless explicitly required and safe. - Block private IP ranges and loopback addresses programmatically.
- Pin allowed hostnames or use DNS allowlisting when possible.
- Disable automatic redirects in HTTP clients (e.g.,
maxRedirects: 0for axios). - Avoid forwarding raw server responses; instead, extract and pass only necessary data.
- Apply network-level controls (firewall rules, service mesh policies) to restrict egress destinations.
These measures reduce the risk of SSRF while preserving functionality. Continuous scanning with tools like MiddleBrick can help detect regressions and ensure that new endpoints adhere to these protections.