- by x32x01 ||
Server-Side Request Forgery, also known as SSRF, is one of the most dangerous web security vulnerabilities developers can accidentally introduce into their applications.
In this article, you'll learn how SSRF works in Node.js, how attackers abuse it, popular bypass techniques, and the right way to secure your code 🔥
In simple words: The attacker tricks your server into making requests on their behalf.
Here’s a vulnerable Node.js example:
At first glance, this code looks harmless.
The server receives a URL from the user and fetches its content.
The real problem?
The application blindly trusts user input.
That trust creates an SSRF vulnerability.
Completely normal.
But attackers think differently.
They know the server sends requests from inside your infrastructure.
That means it can access resources that external users normally cannot reach.
The server sends a request to its own internal /admin endpoint.
If the admin dashboard is hidden from public access, the server may still retrieve it and send the response back to the attacker.
This could expose:
This is called Blind SSRF.
You don't see anything useful in the browser.
So how do security researchers confirm the bug?
They use external interaction services like:
If your collaborator server receives:
Blind SSRF frequently appears inside features such as:
That approach is weak.
Attackers rarely send
Instead, they may use domains that resolve to internal IP addresses.
A stronger defense starts with DNS resolution validation.
Example:
This technique helps detect the real IP address before performing the request.
It also reduces the risk of DNS rebinding attacks.
Let's explore common tricks.
Attackers can represent localhost in multiple ways:
Some libraries interpret these values as the exact same localhost address.
Example:
This address is extremely important in cloud environments.
It often points to cloud metadata services.
In some scenarios, attackers can retrieve temporary cloud credentials from it ☁️
Attackers may abuse alternative prefixes:
Weak IPv6 validation can allow these requests to bypass security controls.
If a trusted site has an Open Redirect vulnerability, attackers can chain requests through it.
Example:
Validation approves the trusted hostname.
The server then automatically follows the redirect to the malicious destination.
Attackers abuse parsing edge cases involving:
Attackers constantly discover new bypass methods.
A stronger SSRF defense should include:
Secure example:
This implementation improves security by:
If your application fetches external content, SSRF protection should be a core part of your security strategy 🚀
In this article, you'll learn how SSRF works in Node.js, how attackers abuse it, popular bypass techniques, and the right way to secure your code 🔥
What is SSRF in Node.js?
SSRF (Server-Side Request Forgery) happens when an application accepts a URL from a user and lets the server request it without proper validation.In simple words: The attacker tricks your server into making requests on their behalf.
Here’s a vulnerable Node.js example:
PHP:
app.get('/fetch', async (req, res) => {
const { url } = req.query;
const response = await fetch(url);
const data = await response.text();
res.send(data);
}); The server receives a URL from the user and fetches its content.
The real problem?
The application blindly trusts user input.
That trust creates an SSRF vulnerability.
How SSRF Attacks Work 🎯
A regular user might send a request like this: Code:
GET /fetch?url=https://example.com But attackers think differently.
They know the server sends requests from inside your infrastructure.
That means it can access resources that external users normally cannot reach.
Accessing Internal Admin Panels
An attacker may try: Code:
GET /fetch?url=http://localhost/admin If the admin dashboard is hidden from public access, the server may still retrieve it and send the response back to the attacker.
Reaching Internal Services
Attackers can also target internal network services: Code:
GET /fetch?url=http://192.168.1.105:8080/internal-api - Internal APIs
- Monitoring dashboards
- Database tools
- Private microservices
- Internal management systems
Understanding Blind SSRF 👀
Sometimes the server performs the request but does not return the response.This is called Blind SSRF.
You don't see anything useful in the browser.
So how do security researchers confirm the bug?
They use external interaction services like:
- Burp Collaborator
- interact.sh
Code:
GET /fetch?url=https://YOUR-ID.burpcollaborator.net If your collaborator server receives:
- DNS lookups
- HTTP requests
- Connection callbacks
Blind SSRF frequently appears inside features such as:
- Webhooks
- Link preview generators
- PDF export systems
- Import tools
- Notification services
A Better SSRF Defense Strategy in Node.js 🛡️
Many developers try to block dangerous IP strings directly.That approach is weak.
Attackers rarely send
127.0.0.1 in plain form.Instead, they may use domains that resolve to internal IP addresses.
A stronger defense starts with DNS resolution validation.
Example:
PHP:
const dns = require('dns').promises;
const ipRangesPrivate = [
'127.',
'192.168.',
'10.',
'172.16.',
'169.254.',
'0.0.0.0'
];
const isPrivateIP = (ip) =>
ipRangesPrivate.some(range => ip.startsWith(range));
app.get('/fetch', async (req, res) => {
const { url } = req.query;
const parsedUrl = new URL(url);
const { address } =
await dns.lookup(parsedUrl.hostname);
if (isPrivateIP(address)) {
return res.status(403).json({
message: "Access Denied"
});
}
const safeUrl =
url.replace(parsedUrl.hostname, address);
const response = await fetch(safeUrl, {
headers: {
Host: parsedUrl.hostname
}
});
res.send(await response.text());
}); It also reduces the risk of DNS rebinding attacks.
Popular SSRF Bypass Techniques Attackers Use ⚡
Many SSRF protections fail because attackers know how to bypass weak filters.Let's explore common tricks.
1. Alternative IP Formats
Blocking 127.0.0.1 alone is not enough.Attackers can represent localhost in multiple ways:
Code:
http://127.1/admin
http://2130706433/admin
http://0x7f000001/admin
http://0177.0.0.1/admin
http://[::1]/admin
http://[::ffff:127.0.0.1]/admin 2. Link-Local Address Abuse
Some developers block private ranges but forget link-local addresses.Example:
http://169.254.169.254/This address is extremely important in cloud environments.
It often points to cloud metadata services.
In some scenarios, attackers can retrieve temporary cloud credentials from it ☁️
3. NAT64 IPv6 Bypass
Some filters only block standard NAT64 ranges.Attackers may abuse alternative prefixes:
http://64:ff9b:1::7f00:1/adminWeak IPv6 validation can allow these requests to bypass security controls.
4. Open Redirect Abuse
Whitelisting trusted domains is not always enough.If a trusted site has an Open Redirect vulnerability, attackers can chain requests through it.
Example:
GET /fetch?url=https://trusted-site.com/redirect?next=http://169.254.169.254/Validation approves the trusted hostname.
The server then automatically follows the redirect to the malicious destination.
5. URL Parsing Confusion
Different parsers sometimes interpret URLs differently.Attackers abuse parsing edge cases involving:
- Credentials
- Special characters
- Encoding tricks
- @ symbols
The Correct Way to Prevent SSRF in Node.js ✅
Blacklists alone are not enough.Attackers constantly discover new bypass methods.
A stronger SSRF defense should include:
✅ DNS resolution validation
✅ Internal IP filtering
✅ Direct IP requests
✅ Redirect blocking
✅ Strict URL validation
✅ Internal IP filtering
✅ Direct IP requests
✅ Redirect blocking
✅ Strict URL validation
Secure example:
PHP:
const dns = require('dns').promises;
const ipRangesPrivate = [
'127.',
'192.168.',
'10.',
'172.16.',
'169.254.',
'0.0.0.0'
];
const isPrivateIP = (ip) =>
ipRangesPrivate.some(range =>
ip.startsWith(range));
app.get('/fetch', async (req, res) => {
const { url } = req.query;
const parsedUrl = new URL(url);
const { address } =
await dns.lookup(parsedUrl.hostname);
if (isPrivateIP(address)) {
return res.status(403).json({
message: "Access Denied"
});
}
const safeUrl =
url.replace(parsedUrl.hostname, address);
const response = await fetch(safeUrl, {
headers: {
Host: parsedUrl.hostname
},
redirect: 'manual'
});
res.send(await response.text());
}); This implementation improves security by:
- Resolving hostnames before requests
- Blocking private network access
- Preventing DNS rebinding
- Disabling automatic redirects
- Using safer request handling practices 🔒
Final Thoughts
SSRF vulnerabilities in Node.js can lead to serious security issues, including:- Internal network discovery
- Hidden admin panel access
- Cloud credential exposure
- Infrastructure compromise
If your application fetches external content, SSRF protection should be a core part of your security strategy 🚀