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 when you write this code and render it to the DOM, the user input here, like first name, for example, what happens to it? In the general case where this is insecure user input, it could lead to potential, well vulnerabilities, like XSS on the webpage, but with React, you're kind of safe. Now why is that? And so let's see what happens when we actually put something in like a script alert thing or image source or whatever into this JSX code snippet. Well, actually, if you look at a page, you get something like this, which looks like a script or whatever element they would have put there, but it's not. That is because if you look very carefully with your dev tools inspector thing into this specific component, specific element on the page, would actually see that all of those angle brackets, they're not real angle brackets. They're actually HTML entities that encodes and tell the page that it needs to render, it needs to render like the angle brackets the left and to the right, but they're not full angle brackets. So that is why when you put that into the page and as user input, nothing would happen, no script would actually get evaluated, no runtime JavaScript evaluation, because this isn't actual real HTML element or something around it. And the browser know this, and this is what I mean when I say React is mostly secure by default. React is mostly secure by default actually means that it knows to encode. So now we have this new jargon telling us what this actually is. This is secure by default if you actually do output encoding by default on any user input.
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.
Let's bring this back to Kate Levy and let's change something else. This, let's try a link. Okay, let's try a link, which is not just a bit of text. Let's try and change this to well, this is over here. So this is if I, there we go. I just hover it. You could see the browser bottom left. This is going to her Twitter account. So I'm gonna change this to, let's try to be kind of malicious here. Right, let's say someone has this free form field and they just build up JavaScript alert, which is like again, the classic way of maybe introducing some XSS. So if I do this, let the page reload, I'm assuming it does, this is what you need to like go here and maybe click on it and we see now an XSS, but why, what is going on? This is actually pretty weird. Like why do I have an XSS and alert if I'm actually using React? This is pretty newish version of React as well. Okay this, you know, 17 and above. So what is, what is going on here? Now to understand what is going on there, let's go back here. The Twitter link, the database, the Twitter link actually gets inserted here. And so what we now understand is, well, React does not apply output encoding and protect you from href values, like HTML attributes that go here. And that is something that you should be aware of. So let's try to fix it. If, first of all, now you are aware of it and you know that if something is malicious or we need to fix it, but let's see, there are some pitfalls in how we try to fix those things. So let's look at that as well. I'm gonna go here and I mean, we can leave it at that.
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.
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. Okay, set Twitter link and use state. I'm gonna kick it off with the database, yes. Okay, cool, yes, little dot, use effect, use effect. And I'll call on, yes, autocomplete it. There we go. And then we wanna find if, no, not that one. GitHub co-pilot, that's insane, right? Twitter link dot index of JavaScript.
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.
Like, what do you think about this? Is this a good fix? Let's try it. I like this autocomplete, go with that one. So basically, this says, if Twitter link over there on the database that we get as user input has, has JavaScript in it, it will actually set it to, I don't know, set it to something like this, right? Just a hash and that's it. Hopefully I didn't forget to close anything. Looks good, I think it looks good, let's try it. Did it reload, no idea, let's see. Did not reload, did reload, I'll reload it. There we go. So, no we still have it. So this is not yet working. Oh, did I not save this one? Something here, I didn't save, let's try again. Oh, I'll tell you what we didn't do. So now we need to set the Twitter link instead of the database Twitter link, right? This is real life coding real life debugging, there we go. We got to use the new variable. Okay, now is it loading it fast enough? There we go, now it did load it fast enough and you can see that on the bottom left, actually I can click on it and just nothing happens because it adds just a hashtag there and that's 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? Wait it to reload, there you go. So, I reloaded it and now we have the XSS again, so the fix wasn't really that good for us. Let's try something else. Let's say that we wanna catch it. So, what do you think we should do like that? Should we do a two lower case and try it like this? Two lower case would that work? So, like this. And as you can see, this is basically the thought process of a developer and what would be great is if they had a tool that would help them on the IDE to basically follow the right APIs. I will get it loaded. Let me see. Where do I go? So it did get loaded pretty fast I think. And looks like we fixed it. Did we? We know it, what coming, right? 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.
Let's say that name is not now Gibson Explorer. Let's go back here, right? Not Gibson Explorer anymore. That's gonna be, again, that thing that we saw. Well, let's do, I don't know, well, let's do. I mean, JavaScript alert will not work there. That's not a link, so I can try this vector instead, like alert and see what happens. And changed it, but I mean, no alert. I don't even see an image tag, so that's okay. Let's try something else.
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.
Comments