5 Ways You Could Have Hacked Node js - Rafael Gonzaga, Michele Riva

Rafael Gonzaga and Michele Riva break down five real Node.js security flaws: DLL injection via typo-squatted npm packages, DNS rebinding attacks on the inspector, HTTP request smuggling, arbitrary file reads, and man-in-the-middle exploits. They explain how each was discovered and fixed, plus Node's coming permission model.
Chapters
Yeah, all right. Welcome everyone to our first session together.
First session, yeah.
We've been working together for a year now. That's the first time we actually speak together on a stage, so it's gonna be interesting, I guess.
Yeah, I think so.
Yeah, so we will be discussing 5 ways you could have hacked Node.js. Um, so before we start, maybe you want to introduce yourself?
Yeah, my name is Rafael. I'm a staff engineer at NearForm. I'm from Brazil. I'm not Italian, as you can see, okay? But I'm trying. I'm a member of a few organizations in the open source. I'm a member of the Node.js Technical Steering Committee. I'm also doing some livestreams, so if you like this kind of content, consider following me there. Twitter, GitHub, every place, I will be there, I guess. And I'm also a Node.js Security Working Group lead and a Node.js releaser, so, If any of the Node.js versions break you, probably I push it. So sorry.
Amazing. So I'm Michele. I'm the co-founder and CTO of Orama Searching. And I'm from Italy. And yeah, I'm basically building with my team the next generation of full-text search engines. So if you're interested in learning more about how full-text search works, especially in JavaScript, that's something we can discuss. And I contributed to many open source projects in the past, mainly from Meta, Google, been on TC39, etc. So we're both highly into the JavaScript ecosystem. So with that being said, we would like to discuss 5 ways you could have been hacked in Node.js, starting from the fact that all languages and all the runtimes you can find out there have vulnerabilities. So whatever you see here, it's not explicit to Node.js only. That can happen in other runtimes. But whatever we are looking at today, it's something that has been fixed by the good old Rafael and his team. So you don't have to worry anymore. But we will see later on what's going on.
Yeah, so one thing we need to make sure here— I normally fix the things, but I normally break the things too. So I just do the work. So to talk about the Node.js security team, we are split in two groups. The first one is the triaging. It's normally members of the organization with security expertise and members of the technical steering committee that receives your report and analyze, evaluate, assess it, and see, okay, these are real vulnerability or this is not. And we have the release team and the build team also looking to the reports because some vulnerabilities are crazy, very difficult to replicate and Sometimes it just happens if the moon is aligned with you. I don't know. And the second one is the Security Working Group. It's a community working group. So we have several initiatives. And you can be part of it. If you just ping me on Twitter, if you just look to the Security Working Group repository in the Node.js project, you'll be able to participate in our meetings, understand how Node.js works, perhaps make your first contribution to Node.js. It's okay. It's easy. Just ask and we will help you. Okay? So, one thing that is important to mention before we start, okay? If you are looking for some exploits, if you like this kind of thing, I hate you. I'm kidding. If you find a potential security vulnerability, please do not open a public issue. This will disclose the problem. This is terrible for us because we need to hurry to run to fix the problem as soon as possible. You normally need to look to the security.md in every project. And, well, how can you submit vulnerabilities to Node.js? You normally look for the vulnerability and go to the HackerOne. Node.js uses HackerOne, okay? And then when you go there, you you will view your form and, okay, this is how I can exploit it. I feel this is a vulnerability or not. And then the Node.js team will look to your report and the triaging will look to your report and will look against our threat model if that's a vulnerability or not. Sometimes you feel that, okay, this is a vulnerability, but this is just the design of Node.js. You need to look to all the documents to make sure that you are, um, looking to the right place. Okay? And if it gets accepted, yes, uh, we will perform a security release as soon as possible and fix it.
Yeah, and one last thing to know is that you can actually make money out of this because there is a bounty program. So if you find a vulnerability that no one else has found yet, you can submit it and you're eligible for earning something. So it's good to know and it's good for the ecosystem and the community. Community. Now, we promised to talk about 5 ways you could have hacked Node.js in the past. So we might start with the first one, which is called DLL injection. So how many of you are familiar with the DLL concept here? Wow. A lot of people actually. So, okay. Okay. So for those who don't know, DLL injection is a technique used by attackers to inject malicious dynamic link libraries. Files into running process, thereby modifying the process itself behavior and gaining unauthorized access to whatever resources, etc. So we can make an easy example. So first of all, first thing to know is that it happens on Windows. And let's say the attacker want to exploit OpenSSL, for example. At this point, let's say you're following a blog post and the blog post says install fastify. How many of you are using fastify here? Amazing. Good, good. For those who don't know, that's a beautiful web framework. I highly recommend using that. But as you can see, you're mistyping something here. So fastify should end with a Y. Here it's ending with an I. So you're actually installing fastify.
Fastify. Fastify.
Fastify.
Yeah.
Awesome. So you are installing a malicious package. The problem is that the The Fastify package contains a DLL script that is called providers.dll. And whenever you call Fastify, then you load this very nice C++ script, uh, which will open the calculator. That's, that's a very bad vulnerability.
A very dangerous thing.
Yeah, exactly. So they force you doing math. So it's pretty bad, right? Yeah. But, okay, how does it work? So let's say for this particular, uh, DLL vulnerability, vulnerability. Whenever you call the crypto or HTTPS TLS modules that all uses crypto underneath, um, it initialize OpenSSL. Then Node.js initialize the OpenSSL, uh, that searches providers.dll in the current working directory as soon as it initialize. And the problem is that if you have a package that has a post install script that uses, for example, crypto module, in that case npm version uses the crypto modules to checksum the package itself, then you're actually calling the malicious script and you're hacked. And that's basically it.
Yes, that's it. You are hacked in 5 minutes. Very easy. Just installing the wrong package. Okay.
So that basically means I can open your calculator on your computer whenever I want.
Yes, but don't do that because I don't use Windows.
Okay. That's also true. We could go on. Maybe I'll explain the next one and I'll give you the next one. We can also talk about DNS rebinding. Again, how many of you are familiar with the concept of DNS rebinding? Awesome. And what is DNS? Do anyone know what DNS is? Because it's always DNS's fault, right? And that's the case again. So I can explain DNS rebinding like I'm 5. So let's say I'm from Italy, Rafael is from Brazil. I want to make a phone call to Rafael. But in order to— I don't know your phone number because we are not that friends anymore because I've opened too many times your calculator. So I need a phone book to understand which is the number to call Rafael. So in that case, what happens is that if a malicious person wants to sneak into the process and listen to my calls, for example, or pretending to be Rafael, Instead of modifying my phone book manually because I would notice that someone is changing something inside the phone book, picking up the wrong number, they could give me a fake phone book instead, which is new. I couldn't notice any modification, but Raphael's name will be the same, but the phone number will be someone else's phone number. So whenever I make a call and I want to talk with Raphael, I will be actually talking with someone else. So I think, Rafael, you're better than me at explaining how it works with DNS.
All right. So I will be quickly on that because it's too much content in a few minutes. So if you have any questions after that, please ask. Ping me. Ping Michele. Ping Michele. Doesn't matter. Just don't make a phone call to me, OK? So let's say that you are using Node.js with --inspect because you are using Inspector protocol. You can use it on JavaScript directly in the browser. Okay? And you will access the attacker.com. It's any malicious website. Okay? When you perform this, this website was redirecting you to 10.0.2.555 in the port 9229. And 555 is not a correct IP address, right? This does— goes up to 255. And then Node.js was not recognizing it as, okay, this is an invalid IP. So, it was proceeding the thing. And okay, so it goes to the browser and the browser says, okay, I don't know it. I don't know— it's not a real IP address. I will ask you a DNS server. And then, if you are using a compromised DNS server connection, you can use it in different ways. Okay, if you are using a public network, You'll be compromised. Oh, one step.
Oh, sorry.
Yes, you can suffer from man-in-the-middle attack because DNS is not protected by SSL or TLS. So it's not so rare, okay, to happen. And then keep going, it will go. The attacker maps the request to the attacker IP, their website, their IP address, with a short time to live. Uh, and then, with this short time to live, the page tries to load the /json under attacker IP address. Okay? And then, uh, just a brief explanation about TTL. Uh, um, basically, when you ask for a DNS, you normally, uh, you, you ask for IP address from a DNS, you receive a time to live, which means that, okay, after this time of is timeout, I will ask again because it might have changed. Okay? And the first, the first request got the attacker IP with a short time to live. It means that when I call the same IP address again, I will call the DNS again. Okay? So, in the second call to the DNS, okay, I want to know which IP, which IP address is the.555. Now it will get your own IP, your localhost. Okay? And then when it got the localhost, you'll be able to see the Node.js debugger information. So the— go ahead. So it will show the /json/websocket/debugger URL with the password to the attacker. So the attacker can just step in, run malicious code in your Node.js instance, and that's everything that they can do. They can do everything, actually.
Yeah, that's pretty bad. And that probably brings us to a totally different type of attack, which is actually kind of similar if you sneak into the middle of the process. So we can talk about HTTP request smuggling. We were discussing this in the speaker's room because it actually happened at least to me in the past. That's how I'm familiar with it, but I can try to explain this to you with an analogy. So again, I will be explaining like I'm 5, then you do the adult stuff.
I'm the bad cop here.
Perfect. You're the grown-up here. Awesome. And so let's say basically you're at the party and you're a kid and you want to eat everything. That's typically me. And you have two tables. On one table we have like sodas and on another table we have cake. So in order to get either cake or soda, you have— you can only take one, but you have to bring a piece of paper with written soda or cake on it. But the malicious kid, which is me again, typically takes a piece of paper, writes soda on one side, folds it, and writes cake on the other one. And when I bring my first piece of paper to the soda desk, they will give me some soda. Then will turn it, give it to the cake desk, and they will also give me some cake because they couldn't check the back of my ticket. So as you can see, I tricked the desks basically to gain access to all the resources I could find. And while this is easy to understand with an analogy on food, because as an Italian I need to talk about food, right? I think it's a bit harder to explain with HTTP headers, but you can do it.
I don't know. Well, let's move. We have just a few minutes, so I will really go fast here. So let's assume you are this user, beautiful user. You send a request and it goes to the CDN, like Cloudflare. And then it goes to the private network/users, a microservice. OK, everybody here works with microservice, I assume. And then it can be a load balancer, reverse proxy, doesn't matter. Will still happen. It was happening, actually. And then if you move forward, we have HTTP headers. And one of them is called Transfer-Encoding. And Transfer-Encoding is just a header that tells the server how to interpret the bytes of the request. I will not spend more time on this because it really doesn't matter. Just move forward. Well, the malicious user was requesting, was creating an HTTP request over the socket with the following content. A POST to slash, okay? And then, go one step. And then this was bypassing Node.js. The invalid header X semicolon slash N. Slash N is Node.js was expecting a slash. Crlf, that is a /r/n to separate headers. But it bypassed with just a /n. And then when it happens, the CDN was sending the whole payload to Node.js. But when it arrives on the Node.js server, it was considering two requests instead of one. The request one, POST, and the request two, GET. The GET here, it was supposed to be just the content of the POST request. But in the Node.js, it was split in two requests. So it means that when I send it to the CDN, it goes okay. And when it arrives to the Node.js server, it will parse this payload into two. So it means that I will still— I will get admin stuff. And the problem with this is that admin stuff might not even be exposed to the internet. I don't want it. And then, well. This is— this can lead to several vulnerabilities like cache poisoning by passing a lot of security, uh, layers and so on. Okay?
Yeah, I think you can go, uh, we, we have a few minutes so you can go directly with this one. Sure, sure.
Let me switch a few then.
Okay, awesome.
Okay, um, let's talk about the, the 8.N4, um, the attempt read to arbitrary path. So let's say that now you use Linux. Like me. Then, you are using a Linux-based host with multiple users. This is very common in the past. We have sysadmins and a lot of /folders, /home folders. Well, by default, when you install Node.js, it tries— when you open it, it tries to load a few configurations in a different in different locations. And one of them is the OpenSSL. OpenSSL is just a.cnf. It's the configuration of OpenSSL. You can exploit it several ways. And by default, Node.js was trying to read the openssl.cnf from a shared path like home iojs, a user that might not exist in your— service in your machine, and then the hacker can just create the user and create this file. And whenever Node.js initializes, it will load the wrong OpenSSL CNF. So, well, one thing that normally security research does to find it is to use a system tool called strace. So if you use Node.js and call strace to wrap it, you'll see all the syscalls that Node.js performs. Like, I will try to read this file. Node.js tries to read this file or read this socket and so on. So this is how it was exposed. And I created a pull request with a test to address this problem, also fixing the problem. Okay? I'll go to the last one. It's basically— you can explain the main—
[Speaker:ALEXIS MOUSSINE-POUCHKINE] Oh, yeah, yeah. No, that's really easy, actually. Certificate validation. How many of you are familiar with the concept of man-in-the-middle? That's pretty common, right? Awesome. So for those who don't know, I'll be super quick. Let's say you're— that actually happened in the States after 9/11. When you were landing at the airport, whatever airport in the States, you would be turning on your phone to make a call to your family, say, OK, I got there. But the cell that replied to your phone was located inside the airport. Why is that? Because every time I open my phone as soon as I land with an airplane, I basically get connected to a cell phone that is basically a national security cell phone. So they can listen to the conversation, check for every threat that can come from a foreign, and basically then proxy the request out to the actual receiver for your call. And that's pretty interesting because this is called man-in-the-middle attack. So there is someone listening to your phone calls or your your HTTP requests by using, for example, a proxy. So this is how basically, okay, instead of making a request directly to a server, we basically use a proxy. And when someone has access to the proxy, then they can actually sneak into your data. And why is that important? Because if you are using, for example, a debugger like Charles, for example, which I actually use, you can decrypt the data and someone can enter the process, lead read, you know, clear data and use it for whatever they want. So this is basically what they would get. So whenever you're debugging your Node.js application, that could have been a vulnerability in the past.
Yeah, that's very common. Like, I use it a lot to intercept my HTTP calls and debug. Okay, I'm sending this request through this application and I want to know the payload, the response, mock some things. And, you know, it's very common. And well, If you are in an interview and the interviewer asks you, okay, implement a proxy client. One year ago, probably I would end up with this code like HTTP GET to the proxy URL with the proxy port and the path is the destination, the final destination. And basically a curl request will look like this. Proxy and then the path. HTTP. Simple. But please don't do that. I did it and it was not good. And basically, if— when you request HTTP— when you perform HTTP requests without TLS because you're normally using a local debugger, a local interceptor, the attacker will read all the traffic without any encryption because you are using localhost. You are using the You can use a public interface for that. And the thing is, when you, um, um, when you do it, the attacker can just sniff in the network using Wireshark, whatever, and they will be able to go here. And as you can see here in the above, my password is called my secure password, and they will be able to see it. And well, that's when, uh, ProxTunnel comes in. Basically, instead of making a GET request and just redirect your request, you create the SSL tunnel with your proxy. So, you're basically sending the HTTP connect to the proxy and the proxy forwards it to the end server, to the destination. So, you have a connection, a tunnel between your proxy and the final destination. So, you'll be able to send any data you want in a safe way. Okay, so you probably don't need to do it by yourself. So be sure to use a good library. Undici is now safe. I did the mistake, but I fixed it.
Okay, so yeah, what are we learning from all of this? So basically, whatever you've been looking here has been fully disclosed and there's no vulnerability anymore. And most importantly, the target, it's always you. Not always. Most of the time it's you. Because you are running the system. You have access keys. You have whatever on your computer. So if I enter Rafael's computer, I can screw up a lot of things, I guess. So that's why I guess you get to protect pretty well.
Yeah. And that's— I have just 1 minute. And one thing that I'm including to the Node.js in the next version, hopefully, is the --experimental permission. How many of you knows Deno? So, you know the allow things, right? Allow net, allow everything. Now it will arrive in Node.js with a different approach. Maybe better, maybe worse, who knows? But yeah, that's it. I'm trying to release it in the next 19 version. And hopefully you not open many issues about it. And it will work fine. But yeah, try it. When it arrives, please try, and that's it. OK? I will skip this because it's just an explanation about the permission model. And that's it.
Yeah, all right. And one very last thing. At Orama Search, we are hiring for a staff engineer. So if you're interested in working on algorithms and data structures in JavaScript, that's your opportunity, I guess.
And same applies in your form, okay? Thank you, guys.
Thank you.
Where are you going?
We sneak out as soon as possible.
Oh.
Shall we come back?
There's question. Please, no.
Thank you, Michele Rivaello. Yeah, we have to give you the prizes. So the first is for you.
That's great.
We need to put the soundtrack. We are the champions. Thank you. Thank you very much for this. Guess what? Amazing talk. And what's going on? Well, we'll check. Do we have any questions in the room? There is Lorenzo if you want to— otherwise I have one.
Questions? Any questions?
Any?
I start. In your opinion, how much important is to deeply understand the HTTP protocol instead of doing something for just playing?
Oh, it's— I mean, when you understand the protocol you are using, you are probably doing your work in the proper way, you know? Like, if you don't understand the headers, probably your server might be receiving it and not parsing it correctly. And you don't know because you don't know how it works. So for me, it's valuable, very valuable.
Yeah, I think the talk shows 5 vulnerabilities. They're almost all linked to HTTP requests. So understanding how HTTP works can actually help you preventing these kind of vulnerabilities by adopting third-party features for other services if your code is known to be vulnerable. Until you find a fix. So you can actually proxy your requests for, let's say, nginx or something else if you know that there is a vulnerability but no fix ready yet. But you have to know it. And you know it knowing how HTTP works.
Thanks. Do you want to give a message to these amazing people that are—
Update to the latest Node.js version.
Please.
Always do that.
Thank you very much.
Thank you.
Thank you. Now you can go.
More from Michele

Beyond Coding: JavaScript Full Text Search, Entrepreneurship, and AI | Michele Riva





