Modern frontend frameworks like React are well thought-of in their application security design and that’s great. However, there is still plenty of room for developers to make mistakes and use insecure APIs, vulnerable components, or generally do the wrong thing that turns user input into a Cross-site Scripting vulnerability (XSS). Let me show you how React applications get hacked in the real-world.
Let Me Show You How React Applications Get Hacked in the Real-World
AI Generated Video Summary
React's default security against XSS vulnerabilities, exploring and fixing XSS vulnerabilities in React, exploring control characters and security issues, exploring an alternative solution for JSON parsing, and exploring JSON input and third-party dependencies.
1. Introduction to React Security
Hello and welcome to my talk. Today, I want to show you a few gaps in React coding that you should know about. I'll provide examples of XSS vulnerabilities found on Twitter and explain the importance of using secure APIs.
♪ Hello and welcome to my talk. You thought your React application is secure? Think again. My name is Irantu, and I want to show you today a few gaps that you should know about when you do React coding.
So, why are we here today? I know what you're thinking right now. Like, this is the year 2021. Or is this going to be another talk about XSS? Like, what do you want from my life right now with XSS in React? Because I thought we got over it by now. Well, that's why I'm going to say, Hello XSS, my old friend. And I'm going to show you a couple of examples that I was just running over Twitter, just to find some coding examples of people showcasing some of their code stuff on React. And what are they actually doing there?
So, here's one example, right? This is XSS, this is this year. What's going on, let's see. Looks like someone is trying to build a counter. But something's messy over there. Are you seeing what I'm seeing? Because when I zoom in a bit inside, I see the whole fancy use effect kind of stuff. Is it fancy still? I don't know, it's already a few versions into React. But anyway, you can see that there's a count variable that's coming maybe from the outside. We are putting it in. We have no idea what's in it. Is it sanitized? Is it not? Should we output and code it? What does it even mean to output and code things? We'll learn about it in a second. But as you're seeing, there's a mix here of React APIs and the Domain APIs like in a rich GML, which is not a really secure way of doing things. And this mix actually causes cross-site scripting attacks or vulnerabilities, like in this application.
Let's look at another example. I've also seen this case on Twitter, which is also this year, not so long ago. So this person was trying to avoid the Runtime Evaluation Eval function by basically accepting user input as well and well running it. Because when you're doing return A plus B and A is an IIFE or a function or whatever, well, it's gonna get run. It's gonna get evaluated. So that doesn't really solve the problem either. So we're having a lot of those different things. That if we're not using the right APIs, we're not aware of what are the secure APIs or what are the insecure APIs? I'm not just talking about, you know, dangerously inner HTML things. I'm talking about other things as well. And you'll see it in a second.
2. Introduction to Iran Tal
Hello, I'm Iran Tal, a Developer Advocate at Snyk. We help developers build secure applications using open source. If you need assistance with vulnerabilities or insecure code, we're here to help. Reach out to me on Twitter @Iran_Tal.
So introducing myself, my name is Iran Tal. I'm a Developer Advocate at Snyk where we help developers build applications securely using open source. So if you're in your IDE writing some JS code, writing some Node.js code, Java, whatever that is, we'll help you find it, we'll augment your experience of doing that by telling you real-time, if you are actually having some vulnerabilities and insecure codes right there. Well, this is really cool, but I'm doing some other things as well. You know, GitHub star, activists on web security topics. So, you know, Node.js probably sending me active there as well, doing all of those kinds of things. But really, if you just wanna reach out and talk about any of this or something else on Twitter, Iran underscore Tal, and reach out and say, hi.
3. Exploring React Security and XSS Vulnerabilities
React is mostly secure by default, but there are still some gaps to protect against XSS vulnerabilities. React encodes user input by default, preventing script execution and ensuring security. However, there are still potential pitfalls and vulnerabilities to be aware of. Let's explore these issues through live coding and simulations on a website with user input. By understanding the risks and gaps, we can enhance the security of React applications.
So let's get on with this. React is mostly secure by default, right? Like other frameworks like Vue and Angular, most of these get things right on the client side, right? As far as it goes to XSS and maybe some other things when some frameworks take, you know, a bit more bulky and take a step further as well. But why am I saying mostly secure, right? Like what is going on? Why is Iran on this stage right now saying mostly secure? What is left for me to protect? Because I thought using React actually protects me from all of these weird XSS stuff happening to my applications.
So to realize that we kinda need to, you know, explore something else. I'm saying React is mostly secure by default, but what does secure by default mean? We need to explore this a little bit and you need to understand a little bit more of the jargon and that's where I'm gonna just level up and just say what XSS is so everyone here can be on the same level playing field.
So with that said with this knowledge, let's move a little bit forward and figure out now if React is secure by default, and it does secure output of user input, why are you saying this is mostly secure by default? What is still left for me to protect and where really all the gaps? So let's dive now in into some live coding together and see what we can learn about some pitfalls. And so for that, I have this build application website where it's this Kate Libby was building their package profile for Opus for some maintainers and things like that. So it's kind of like the webpage with packages on it. So let's dive into something like this and see how it looks like. Well, I need my ID, there we go. Let's make sure everything works. And if it does, I should have, nope, this one here. Okay, cool. This is the website that I've just built and looks like it's working pretty cool. Has some elements in it, like user input here, sorry, like the name, the description or something, link to their Twitter, some more stuff that I can use like testimonials. So there's a lot of user input here that we can use as a baseline of just simulating what could actually go wrong. So let's take a look at this a little bit more. For example, this database has all of the things that I was talking about over here. And this is what we're actually going to use to simulate what could actually go wrong. So I'm gonna go and change some of them, for example, just for the sake of things.
4. React's Default Security Against XSS
React helps secure against XSS vulnerabilities by default, applying output encoding to user input and converting it into HTML entities.
So I can change this to my name here. And once I do it, you see total loads to the run all over here. That's fine, but what happens if I change it to something like image source X on error alert one, and hopefully that triggers an XSS? It doesn't, this is where react actually helps you and secures things by default. Actually output and codes, this is what we said with the example of the first name. This is why if you try those things and they didn't actually execute, that's fine. That's because that's fine database utter name over here is simply something that react knows to now apply output encoding and change all of this into HTML entities. So so far so good.
5. Exploring XSS Vulnerabilities in React
Let's try a link and change it to something malicious. We see an XSS vulnerability even when using React. React does not protect against href values, so be aware of this. Let's explore how to fix it and the pitfalls to avoid.
6. Exploring React Security - Twitter Link
And just before around here, a bit, we have enough room. And so let's go ahead and try these whole, I use a factor just like change and sanitize it together. So let's try something like this is Twitter link. We put it over there.
7. Exploring XSS Vulnerabilities - Fixing and Testing
Like, what do you think about this? Is this a good fix? Let's try it. So, it looks like we fixed it. Did we fix it? What happens if someone gets a bit, well tricky and maybe they do something like that? They just do it as a upper case kind of string. So, now if I do it, did it reload? So, we fixed the uppercase, we fixed the lower case, but what else could go in, right? Like anything else. We get stripped, trim, space characters and all those things. We can try all of those, but would it actually work, would they not? We can try a different way of escaping it maybe, but that's maybe a bit tricky.
8. Exploring Control Characters and Security Issues
Let's explore what happens when we add a control character, such as slash r slash, to escape the lower case and index sub. This can cause the whole thing to fall apart, highlighting the importance of learning how to do things right.
What we haven't tried is, what happens if we add things like a control character. And that is something that I could actually add a control character over here and escape something like, slash r slash something like that. And that would actually escape the whole two lower case and index sub and everything will be just fine. Let me show you what I mean by that. If I just do slash, no not here, over here, I just started off with slash X nine 10, which is a control character. If I tried that one, the whole thing falls apart. Reload it again. There we go. So, as we're learning doing one thing and the other and the other, these are all trying to mitigate a problem, but there are still some issues, still some issues that we should figure out how to do it. So, learning how to do things right is important.
9. Exploring an Alternative Solution for JSON Parsing
Now let's explore an alternative solution for handling JSON files. Instead of building a custom parser, we can use existing packages like React-JSON-Pretty. Although it's inactive and unmaintained, it has a significant number of downloads. By checking the popularity and latest version, we can ensure security. Let's dive into the package profile and play around with the package parser. We'll demonstrate how XSS can occur from other sources.
Now let me go into something else. Let's say that I actually want to, oh, let's avoid this whole thing for a second, so I can try another example. I said it actually want, well, Libby actually wants to go ahead and do this whole packet JSON view. And well, she's not gonna go and, I mean, I'm not gonna go and write a parser that I indent stuff and highlights. You could actually have themes and pretty cool colors, right? So I'm not gonna build all of this. I'm gonna go outside and find something where I can give it a JSON file, like the PackageManifest for your npm package. We'll go ahead and do this whole really cool highlight syntax thing because I'm also not really a CSS person. So this whole thing is not for me. I'm gonna go over to something like the Snyk Advisor and I'll look for some packages, already found something called React-JSON-Pretty. It's, unfortunately, it looks like inactive. It's unmaintained or something, but it has something like 40K downloads, which is a lot. So, you know, maybe I'll try and use it. You could try and check if this is popular by version or not. So hopefully, I mean, hopefully everyone are on the latest version, which they are. So that's a good thing from security wise if there's like, this was vulnerable, this was vulnerable, you knew what to upgrade to. It also looks like this is mostly used as a direct package, which makes sense, as opposed to like an indirect package. So I'll go ahead and use it. The most popular version indeed has no security fixes. Let's see what's going on. I'm gonna go and use this. So I'm gonna go into package profile. There it is. It does package parser, I'm pretty sure. There we go. So I've imported this as package parser and I've provided it the package manifest, which is basically all of this JSON from the database file that I have here. Let's play around with this one here. So it's a simple component. Just take some configuration and then things apply it by default, that's it. And I can go ahead. And what I want to show you is like, let's try and do XSS from other places.
10. Exploring JSON Input and Third-Party Dependencies
Let's explore potential vulnerabilities in JSON input from external sources, such as NPM packages. By manipulating the package JSON, we can introduce malicious code and test how the application handles it. This highlights the importance of scanning and securing third-party dependencies. Additionally, be cautious when using href HTML attributes, as they are not output encoded by default.
What I would say is, I don't remember what was here, so I'll just do ABC, but let's say this, you know, if I were thinking how to exploit this, I would say, if this package was written by someone, maybe they didn't take a good care enough of sanitizing the data or output-encoding it by going into all of the recursive elements that actually are within the JSON, so all of the elements that's like living inside other fields in other fields. So what if I tried to put it here? Like maybe this level on the JSON is sanitized, but this one is not, or output-encoded would be the best way of doing this. But looks like it is. So that looks okay. So there we go, getting back to normal. Now, it looks like this is working, and if this is a JSON input from an NPM package that you get, as well, that is not controlled by you, that is controlled by someone else, right? So what if that person gives you a bad package JSON, right? Like I'm gonna go and do something like this and say, hey, like you're getting this package JSON. There you go. So package manifest. There you go. Now, it's not a JSON anymore. Now it's a string. It's a string, which I control, because I can define whatever I want in my package JSON and mine is just a TAR file and I'll send it to you, right? So if this is the input now, let's see what happens. Changed the whole meaning of what the package JSON is, but the question is, is the application ready to handle something like that? Doesn't look like it, because it looks like it tries to render it. You should probably have put an alert box somewhere there. And I'll alert, on our alert, probably should have worked. Oh, there we go. So now we see that what's happening, right? So now you're using a component, an open source library that may have vulnerabilities in it, even though you were thinking it might be okay, you know, probably, you know, well, probably it's not, but no, you have to like test all of those things. So it's kind of like brings us into the world of, you know, managing components, learning about all of those things. So here are my takeaways.
Let's go back to slides. Yeah, there we go. So takeaways for us, right? This is, you know, avoid all of this, you know, dangerously inner HTML, obviously you do not wanna do this, but the fact that you're avoiding it doesn't mean that others are avoiding it as well, like we've seen here. So you should really scan your third-party dependencies if you're doing something like npm audit, you know, that's fine. It's a great way to, you know, get awareness for security vulnerabilities. But in my case, I found out when I was using React.JSON in my demo here is that he did not find it when I was doing npm install and npm audit, nothing was showing up for it. You know, luckily I was using a sneak test and I was able to find it. So be aware of what you're putting into this, if I have to summarize, right? Be aware of what you're putting into your, I would say dependencies in general, libraries collection or your applications, components, be aware of what you're putting there, be able to scan it all the time and fix it. And the other thing is, of course, be careful of what you put into those href html attributes because they are not getting output encoded by default. So thank you, React, as I would say, React responsibly and securely.