5 Ways You Could Have Hacked Node.js

Rate this content
Bookmark

All languages are or were vulnerable to some kind of threat. I’m part of the Node.js Security team and during the year 2022, we've performed many Security Releases and some of them were really hard to think about.


Did you know you can make money by finding critical vulnerabilities in Node.js? In this talk, I’ll show you 5 ways you can have hacked Node.js and how the Node.js team deals with vulnerabilities.

22 min
05 Jun, 2023

Video Summary and Transcription

The Node.js security team is responsible for addressing vulnerabilities and receives reports through HackerOne. The Talk discusses various hacking techniques, including DLL injections and DNS rebinding attacks. It also highlights Node.js security vulnerabilities such as HTTP request smuggling and certification validation. The importance of using HTTP proxy tunneling and the experimental permission model in Node.js 20 is emphasized. NearForm, a company specializing in Node.js, offers services for scaling and improving security.

Available in Español

1. Introduction to Node.js Security Team

Short description:

Hello, everybody. My name is Rafael Gonzaga. I'm a staff engineer at Neo4m. I'm a member of a few organizations in the open source, and I'm a Node.js DSC member, a security working group lead. Recently, I started live coding on Twitch. So first of all, all the CVs mentioned here were addressed. Make sure you are using a safe version of Node.js. The Node.js security team consists of the Node.js triage team and the security working group. Did you find a potential security vulnerability? Please do not open a public issue. The process of submitting Node.js vulnerabilities is fairly straightforward. You find a potential vulnerability and you go to the hacker one. The Node.js three-edge team receives your report and assesses it against our threat model.

Hello, everybody. My name is Rafael Gonzaga. I'm a staff engineer at Neo4m. I'm from Brazil. I'm a member of a few organizations in the open source, and I'm a Node.js DSC member, a security working group lead. I'm a Node.js releaser, so if any of Node.js builds break you, probably it was on me, OK?

So recently, I started live coding on Twitch. So if you like this kind of content, follow me there as well. I'm mostly available in all the social medias.

So, OK, first of all, before showing the bad parts of Node.js, I would like to give a disclaimer telling that all languages have it and introduced a concept of security in programming language. So for instance, first of all, all the CVs mentioned here were addressed, OK? Make sure you are using a safe version of Node.js. For instance, I wrote a package called IsMyNodeVulnerable. If you would just call npx is my node vulnerable, you'll be able to see if you are using a vulnerable version of Node.js. If you are, please update, OK?

So first of all, I will present the Node.js security team. Basically, the Node.js security team consists in two groups. The first one is the Node.js triage team. It consists of the Node.js Technical Steering Committee, specific contributors of Node.js with security expertise, the Node.js release team, and the build team, OK? And the second group is the security working group. It's a community working group. We work on several security initiatives, and the experimental permission or the permission model is just one of them. So you can be part of it. Just ping me, send me a message, you can go to the repository, and you'll be able to see it, OK?

So let's go to what matters. Did you find the potential security vulnerability? Please do not open a public issue. You will be disclosing the vulnerability, and that's crucial. That's very bad for maintainers, because we need to hurry. We need to do a lot of things in a short period of time, and it's eventually very bad, actually. So usually, see the security.md in the Node.js file, you'll be able to see it. If you go to the hacker one, you'll be able to see it, as well. So the process of submitting Node.js vulnerabilities is fairly straightforward, okay? You find a potential vulnerability and you go to the hacker one. Hacker one is a platform where you can submit any potential vulnerability and you assess it. And then you fill the form, and the Node.js three-edge team receives your report. And we assess it against our threat model.

2. Hacking Node.js: DLL Injections

Short description:

And if that gets accepted, we will prepare a security fix and a security release. You can make money from it through bug abating programs. I will be presenting five ways you could have hacked Node.js. The first one is DLL injections, a technique used by hackers to inject malicious dynamic link library files into a running process. Let's take this example: you are on Windows, you install a game, and a malicious package containing a providers.dll is installed. This package requires crypto, and when it is initialized, it will search for providers.dll in the current working directory.

And if that gets accepted, we will prepare a security fix and a security release. Okay? So, well, you can make money from it through bug abating programs. Okay?

So, in this talk, I will be presenting five ways you could have hacked Node.js. However, it's important to mention that all the vulnerabilities were a threat. So don't worry.

The first one is DLL injections, okay? Hello, Windows users. DLL injection is a technique used by hackers to inject malicious dynamic link library files into a running process, thereby modifying its behavior or gaining unauthorized access to its resources.

So let's take this example, okay? You are on Windows. Again, sorry, Windows users. Then let's say that you install any kind of game. You install most of the games nowadays need to open SSL. So you have opened SSL in your machine. And then you are following a blog post, but you mistyped Fastify. And then you install Fastify, okay? And then this package, this is a malicious package that contains a providers.dll. And the content of this dll is basically the most dangerous thing you can do on Windows, that is, to open the calculator, okay? And then, okay, this package requires crypto, actually, in the beginning. Whenever you require crypto, HTTPS or TLS module on Node.js, we'll initialize open SSL. And when it is initialized, it will search for providers.dll in the current working directory. And for instance, if the package, malicious package, contains just a post-install script that calls NPM versions that, under the hood, require crypto, it will initialize open SSL and will load the providers.dll and then the attack happens. Now it thinks that it doesn't load providers.dll in the current working directory anymore.

3. DNS Rebinding Attack

Short description:

Let's talk about DNS rebinding. DNS rebinding is a technique used to trick users into visiting a bad website instead of the intended one. An attacker can use DNS rebinding to redirect users to an invalid IP address. The attacker can then exploit the DNS server, which is not protected by SSL or TLS, to perform a man-in-the-middle attack. By mapping the request to their attacker IP with a short time to live, the attacker can intercept the page's request and load malicious content. The time to live ensures that messages don't get stuck in a loop and works like a timer for message delivery.

So let's go to the second one. Let's talk about DNS rebinding. So when you want to visit a website like xample.com or jsnation.com, your computer needs to know the IP address of that website. So the DNS is like a phone book. For the internet that helps your computer to find the right IP address to the DNS.

So imagine that someone wants to trick you into visiting a bad website instead of the one that you intended to go to. They could use something called DNS rebinding attack to do this. So let's assume that there's a user using node-inspect. This will open the Node.js debugger. And then you access the attacker.com. And the attacker.com redirects you to an invalid IP address. So the Node.js was not validating that IP address correctly. So it was going to the browser. And then the browser says, OK, this is not a real IP address, I will ask to the DNS server. The DNS server goes to a DNS server with a compromised connection, which means, OK, I want the DNS or the IP address for the 10.0.2.555 in the port 9229. And then, well, you may think, OK, the attacker would need to get access to the DNS server and that's hard, actually not. DNS is not protected by SSL or TLS. So if you are in the same network, it can just perform a man-in-the-middle attack.

So OK. Let's assume the attacker now has access to the DNS server. And then, when you require, when you request the IP address for that invalid IP address, it maps the request to their attacker IP with a short time to live. OK? And then the page tries to load a slash JSON. The time to live is basically a special number that is used to make sure that the message sent over the Internet don't get stuck in a loop or keep going forever. It works like a timer that tells the computer in charge of sending the message when to stop, try to deliver it if it takes too long. OK? So, for instance, I request to the web server the IP address of axample.com, and I receive a time to live, a time to live of, I don't know, 60 seconds. And then if I request the IP address of that DNS in that short period of time, before 60 seconds, I receive the same IP. If I request the IP address after the 60 seconds, it will perform another DNS call. OK? So, OK. Then it's loading the SlashJSON under attack IP, and then the tll expires. And this time, it requires the DNS server again, and the attacker sends it to the local host.

4. Node.js Security Vulnerabilities

Short description:

So it will expose the SlashJSON under your local host to the attacker IP, which means that it will show the WebSocketDebugger URL, and then the attacker will get access to your machine. And well, it can run whatever you want, or she wants in your compromised Node.js instance. The third one is 80PS request smuggling. Let's do an analogy here. Imagine you are in a restaurant, and you want to order a burger. But now imagine that someone else at the table wants to order a soda. So they write a note with the soda order and hide it inside your burger order, like a secret message. Let's do it in a technical way now. Let's assume you just request and then you have a CDN. And then you have a private network under, let's say that I have a microservice called users. And to make it happen in the Node.js vulnerability, basically the transfer encoding was a header required to exploit it. Imagine there is a malicious user sends a request with the following content, post today slash. And then one of the headers is the X semicolon slash n. That is the new line. But an invalid header is sent using only LF, the slash n. But it is still being processed by Node.js, OK? So what was happening behind the scene is that, this request goes to the CDN, the CDN sends it to the server, the server interprets it as two requests, a POST to the slash and a GET to the admin stuff, even though I sent just one request.

So it will expose the SlashJSON under your local host to the attacker IP, which means that it will show the WebSocketDebugger URL, and then the attacker will get access to your machine. And well, it can run whatever you want, or she wants in your compromised Node.js instance. So that's very bad. It's difficult to replicate, OK? But it's still a good attack. And after solving this, we received another report that, OK, DNS rebinding was fixed, but there's an Edge case on Apple, and then we fixed it again. It happens.

The third one is 80PS request smuggling. So let's do an analogy here. Imagine you are in a restaurant, and you want to order a burger. You give your order to the waiter, who takes it to the kitchen. But now imagine that someone else at the table wants to order a soda. And they want to do it in a sneaky way. So you don't not see. So they write a note with the soda order and hide it inside your burger order, like a secret message, OK? So the waiter takes your burger's order and sees the note for the soda hidden inside. But because the note is hidden, the waiter does not realize that there's two separate orders. And then the waiter brings you a burger and a soda, even though you only ordered a burger, OK? Let's do that. Let's do it in a technical way now, OK? Let's assume you just request and then you have a CDN. And then you have a private network under, let's say that I have a microservice called users, OK? And then you can have, I don't know, several servers. You have a load balancer, reverse, proxy. It really doesn't matter. And to make it happen in the Node.js vulnerability, basically the transfer encoding was a header required to exploit it. So basically, transfer encoding is a header that serves to tell the server how to interpret the bytes on the header request, OK, on the header body as well. So imagine there is a malicious user sends a request with the following content, post today slash. And then one of the headers is the X semicolon slash n. That is the new line. This was by passing the Node.js LLTP validation. So, Node.js was expecting a CLLF, that is carry-return-line-feed, to properly separate the headers. But an invalid header is sent using only LF, the slash n. But it is still being processed by Node.js, OK? So what was happening behind the scene is that, this request goes to the CDN, the CDN sends it to the server, the server interprets it as two requests, a POST to the slash and a GET to the admin stuff, even though I sent just one request.

5. Navigating Node.js Security Vulnerabilities

Short description:

But it is still being processed by Node.js, OK? So what was happening behind the scene is that, this request goes to the CDN, the CDN sends it to the server, the server interprets it as two requests, a POST to the slash and a GET to the admin stuff, even though I sent just one request. So maybe the admin stuff was not exposed to the network, to the web, even though I could make this request. So that's terrible, okay? The other one is attempt read from arbitrary paths. Let's assume you are on a Linux based host with multiple users and one of the users is a malicious one. A malicious user creates a fake openSSL.cnf file containing the malicious configuration. The attacker can modify the key generator, alter the default settings, and more. Node.js in the startup was trying to read a file called openSSL.cnf in that specific location. The attacker could figure it out using Linux utility tools like strace. We have addressed this issue and created a test to solve it. The last one is certification validation. Let's assume you perform a GET request to the server with a client IP address that is different, like a PROC server. You can use a man-in-the-middle proxy tool like HTTP Toolkit Proxy to intercept debugger requests.

But it is still being processed by Node.js, OK? So what was happening behind the scene is that, this request goes to the CDN, the CDN sends it to the server, the server interprets it as two requests, a POST to the slash and a GET to the admin stuff, even though I sent just one request.

So maybe the admin stuff was not exposed to the network, to the web, even though I could make this request. So that's terrible, okay?

So well, the other one is attempt read from arbitrary paths. Basically, let's assume you are on a Linux based host with multiple users and one of the users is a malicious one, okay? It happens very often in universities, okay? So let's assume that a malicious user creates a fake openSSL file, openSSL.cnf file configuration containing the malicious configuration. The openSSL.cnf is just a file containing the security configuration for the openSSL, okay? So the attacker can do a lot of things like modify the key generator, alter the default settings, and so on. And then the malicious user create this fake openSSL.cnf at this specific file, io.js build ws.out.release and so on and go to that long file. And then Node.js in the startup was trying to read a file called openSSL.cnf in that specific location. It was a mistake from our side. So the attacker could figure out it using the Linux utility tools like strace. It used it to trace system calls, OK, so it just called a strace and then it was able to see, OK, this is the open calls that this program specific does. And then I create this file because it will try to read this file specific and then I can hack it. OK, so we have addressed it, as I said, and I have created a test addressing this problem. So if you want to see the PR 46150, you'll be able to see how I solve it.

So OK and then OK, once the node.js loads it, the attacker will get access to that open ssl and with a custom configuration. So the attacker now controls it. And OK, that's bad. OK, it's very hard to explain, but that's bad.

The last one, certification validation. Personally, I did this mistake and I fixed it, but it was hard. So let's assume that you do a normal request. You perform a GET request to the server and the client IP is xsx because it's your IP address. But then you want to use a PROC server. It's fairly common because let's say that you want to intercept a request, normally a PROC server, a PROC ATP debugger, is good to do that. And then the client IP address is like different, is the III, the PROC server one. You can use it for a man-in-the-middle proxies. There is another tool called HTTP Toolkit Proxy. You can intercept debugger requests. That's very useful for developers. This is just an example of the man-in-the-middle proxy. And then let's say that you are in an interview, and the interviewer asks you to implement an HTTP proxy client, okay? And you end up with the following example.

6. HTTP Proxy Tunneling and Permission Model

Short description:

Performing HTTP requests through a proxy without TLS encryption can expose your data to network sniffing. HTTP PROXY tunneling creates a secure SSL tunnel between the proxy and the server, protecting your data. Use a good HTTP client library like Onduchi. Node.js 20 introduces the experimental permission model, which allows fine-grained control over file access. An example demonstrates how the permission model can prevent unauthorized access to sensitive files.

I have the HTTP GET and the hostname is basically the PROC's URL. And the request of the server is the server I want to perform the request under the PROC's client. Basically in a query request, it's basically like this. The local host is my PROC's server. However, don't do that. I did that for Undici, one of the Node.js backers. And that's, how can I say that, is dramatic.

Okay, let me explain the problem. When you perform that kind of approach, all the HTTP connection is, all the connection, all the server, all the data you want to send to the server, will send first to the PROC's server on the other HTTP connection without TLS. So when there's no TLS, it means that anyone in your network, in your local network, will be able to sniff the network and read all the traffic without any encryption, regardless if your requested server is HTTPS or not. And that's very bad, because in that case, for instance, in that case of the UNDG. It was using the PROXY agent, ok? And whenever you send a request to the XSample.com using the PROXY URL as a localhost HTTP, it's like a default address for AmandaMiddleProx or HTTP2Kit, if someone goes to your network and sniffs using Wireshark, for instance, as you can see in the blue line, it is displaying my user and my password under the network, even though the XSample.com is a TLS ender server. That's bad. That's why HTTP PROXY tunneling comes in. Basically you create a PROXY, SSL tunnel between the PROXY and the server. So it means that the PROXY won't be able to read your data. It will only create the tunnel to you between the server and the PROXY. So that's the safer approach.

So I know that most of you won't pass by something related because I don't think that interviewers will ask you to do that. So make sure to use a good HTTP client library. Onduchi is now safe. So what do we learn from all this? The target is often you. And the Node.js 20 comes with an exciting feature called permission model, dash, dash experimental permission. Just a final example. Let's assume that there is a humble dev trying to solve a problem. It goes to the tutorial, it finds a problem solver package. The problem solver package looks like this. It was trying to read the etc.passwd that is basically the password file. But this humble dev decides to be cautious and use the experimental permission to allow read only in the files he wants. And then the humble dev got saved by the permission model, because it was trying to access the etc.passwd and it was denied because this permission was not explicitly granted to the process.

7. NearForm and Experimental Feature

Short description:

This is a good feature, please make use of it. It is experimental, so you might expect some bugs for now. Don't use it in production until it gets stable, considering that a security feature. NearForm is a professional service company with core contributions to Node.js. They can help your business scale under Node.js infrastructure, covering security, performance, and more.

This is a good feature, please make use of it. It is experimental, so you might expect some bugs for now. Don't use it in production until it gets stable, considering that a security feature. So there is a lot of other flags like AllowRead, Write, Child Process, Worker, and a lot of things.

And well, that's it from my side. A bit about NearForm. NearForm is a professional service company. We are distributed worldwide. We have core contribution to Node.js. I'm a member of the Node.js TSE, but we have two other folks on the Node.js core team as well. So we can certainly help your business scale under Node.js infrastructure. Regardless, security, performance, a lot of things we cover.

And that's it from me.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Node Congress 2022Node Congress 2022
26 min
It's a Jungle Out There: What's Really Going on Inside Your Node_Modules Folder
Top Content
Do you know what’s really going on in your node_modules folder? Software supply chain attacks have exploded over the past 12 months and they’re only accelerating in 2022 and beyond. We’ll dive into examples of recent supply chain attacks and what concrete steps you can take to protect your team from this emerging threat.
You can check the slides for Feross' talk here.
Node Congress 2022Node Congress 2022
34 min
Out of the Box Node.js Diagnostics
In the early years of Node.js, diagnostics and debugging were considerable pain points. Modern versions of Node have improved considerably in these areas. Features like async stack traces, heap snapshots, and CPU profiling no longer require third party modules or modifications to application source code. This talk explores the various diagnostic features that have recently been built into Node.
You can check the slides for Colin's talk here. 
JSNation 2023JSNation 2023
22 min
ESM Loaders: Enhancing Module Loading in Node.js
Native ESM support for Node.js was a chance for the Node.js project to release official support for enhancing the module loading experience, to enable use cases such as on the fly transpilation, module stubbing, support for loading modules from HTTP, and monitoring.
While CommonJS has support for all this, it was never officially supported and was done by hacking into the Node.js runtime code. ESM has fixed all this. We will look at the architecture of ESM loading in Node.js, and discuss the loader API that supports enhancing it. We will also look into advanced features such as loader chaining and off thread execution.
JSNation 2023JSNation 2023
30 min
The State of Passwordless Auth on the Web
Can we get rid of passwords yet? They make for a poor user experience and users are notoriously bad with them. The advent of WebAuthn has brought a passwordless world closer, but where do we really stand?
In this talk we'll explore the current user experience of WebAuthn and the requirements a user has to fulfill for them to authenticate without a password. We'll also explore the fallbacks and safeguards we can use to make the password experience better and more secure. By the end of the session you'll have a vision for how authentication could look in the future and a blueprint for how to build the best auth experience today.

Workshops on related topic

Node Congress 2023Node Congress 2023
109 min
Node.js Masterclass
Top Content
Workshop
Have you ever struggled with designing and structuring your Node.js applications? Building applications that are well organised, testable and extendable is not always easy. It can often turn out to be a lot more complicated than you expect it to be. In this live event Matteo will show you how he builds Node.js applications from scratch. You’ll learn how he approaches application design, and the philosophies that he applies to create modular, maintainable and effective applications.

Level: intermediate
React Summit 2023React Summit 2023
56 min
0 to Auth in an hour with ReactJS
WorkshopFree
Passwordless authentication may seem complex, but it is simple to add it to any app using the right tool. There are multiple alternatives that are much better than passwords to identify and authenticate your users - including SSO, SAML, OAuth, Magic Links, One-Time Passwords, and Authenticator Apps.
While addressing security aspects and avoiding common pitfalls, we will enhance a full-stack JS application (Node.js backend + React frontend) to authenticate users with OAuth (social login) and One Time Passwords (email), including:- User authentication - Managing user interactions, returning session / refresh JWTs- Session management and validation - Storing the session securely for subsequent client requests, validating / refreshing sessions- Basic Authorization - extracting and validating claims from the session token JWT and handling authorization in backend flows
At the end of the workshop, we will also touch other approaches of authentication implementation with Descope - using frontend or backend SDKs.
Node Congress 2023Node Congress 2023
63 min
0 to Auth in an Hour Using NodeJS SDK
WorkshopFree
Passwordless authentication may seem complex, but it is simple to add it to any app using the right tool.
We will enhance a full-stack JS application (Node.JS backend + React frontend) to authenticate users with OAuth (social login) and One Time Passwords (email), including:- User authentication - Managing user interactions, returning session / refresh JWTs- Session management and validation - Storing the session for subsequent client requests, validating / refreshing sessions
At the end of the workshop, we will also touch on another approach to code authentication using frontend Descope Flows (drag-and-drop workflows), while keeping only session validation in the backend. With this, we will also show how easy it is to enable biometrics and other passwordless authentication methods.
Table of contents- A quick intro to core authentication concepts- Coding- Why passwordless matters
Prerequisites- IDE for your choice- Node 18 or higher
JSNation 2023JSNation 2023
104 min
Build and Deploy a Backend With Fastify & Platformatic
WorkshopFree
Platformatic allows you to rapidly develop GraphQL and REST APIs with minimal effort. The best part is that it also allows you to unleash the full potential of Node.js and Fastify whenever you need to. You can fully customise a Platformatic application by writing your own additional features and plugins. In the workshop, we’ll cover both our Open Source modules and our Cloud offering:- Platformatic OSS (open-source software) — Tools and libraries for rapidly building robust applications with Node.js (https://oss.platformatic.dev/).- Platformatic Cloud (currently in beta) — Our hosting platform that includes features such as preview apps, built-in metrics and integration with your Git flow (https://platformatic.dev/). 
In this workshop you'll learn how to develop APIs with Fastify and deploy them to the Platformatic Cloud.
JSNation Live 2021JSNation Live 2021
156 min
Building a Hyper Fast Web Server with Deno
WorkshopFree
Deno 1.9 introduced a new web server API that takes advantage of Hyper, a fast and correct HTTP implementation for Rust. Using this API instead of the std/http implementation increases performance and provides support for HTTP2. In this workshop, learn how to create a web server utilizing Hyper under the hood and boost the performance for your web apps.
React Summit 2022React Summit 2022
164 min
GraphQL - From Zero to Hero in 3 hours
Workshop
How to build a fullstack GraphQL application (Postgres + NestJs + React) in the shortest time possible.
All beginnings are hard. Even harder than choosing the technology is often developing a suitable architecture. Especially when it comes to GraphQL.
In this workshop, you will get a variety of best practices that you would normally have to work through over a number of projects - all in just three hours.
If you've always wanted to participate in a hackathon to get something up and running in the shortest amount of time - then take an active part in this workshop, and participate in the thought processes of the trainer.