 Todd, you ready? OK. All right, well, next up, we want to welcome Morgan Roman to the stage here. He wanted me to let you know that he works in AppSec and apparently has a dog. So please welcome up on the stage for Don't Run with Scissors. Thank you, Gio. Hi, as he said, I'm Morgan Roman. I work in AppSec. This is about how to prevent your developers from doing bad things by telling them to not run with scissors, basically. And yeah, that's actually the entire talk. Thank you. I'm done. Now, it's actually quite simple. But first, just quickly about me a little bit more. I work at DocuSign. Basically, we came up with this idea because we were tired of playing whack-a-mole with bugs. And thus, I included a picture of me playing whack-a-mole at RSA because that's what you do at RSA. And I also want to point out that I'm going to use a lot of examples. This entire talk will be examples. But I may use a particular framework or a particular library. Don't take it as just this is for this framework or this library or this kind of security issue. It's a strategy that that's what I really want to get across. So I'm going to tell you what the problem is. We have A to B. Developers are supposed to write something and make it happen. They're trying to get to A to B. So what they do is this. They go in a straight line. They do it the easy way. They do it whatever way it makes the most sense. They just parse some XML. They just use some regex. Whatever makes sense at the time, however they patch it together, they have sprints, they have other priorities. Does anyone think this is always the secure way? Yeah, yeah, it could always be the secure way. All right, I like your style. Trust, don't verify. This is usually the secure way. And this is the problem. And you need all these other steps like encoding, validation, access controls, all that sort of thing. So we want to make sure that the secure way is the easy way. So now I present you the solution, this. By the way, now this is my entire talk, and now you can all leave. It's cool. Now we're going to go through some examples because this is not the first time this has happened. But I want to just explain to everybody why you would want to do this. People like it better. When you're communicating to the developers you're working with, they are much happier and they're much more likely to go along. It doesn't impede their development and it helps you ship faster. And oftentimes nowadays you can't take in a very important application offline if it's compromised. But you do want to ship a hot fix as quick as possible. So that's the kind of idea behind this. And your training will be way more effective. OK, so first the existing examples. And then I'm going to show you all how you do it yourself. So this is not a new tactic, by the way. But it's never really been explained clearly as I'm about to do. So here is React. Who here knows what React is? It's the JavaScript flavor of the week slash year or something like that. Well, I actually really like it, even though I have no clue how to use it, for the following reason. If you notice, by default it relies on the developer, usually doesn't rely on the developer to encode the input. Basic HTML, most template languages don't do that for you. But React uses JSX and by default it does, which is awesome unless they use this horrible thing called Undangerously Set Inner HTML. And this had a laser pointer, but it's not really working. So Dangerously Set Inner HTML has a very scary name and basically says, hey, if you put something in here, it's going to be bad. And instead of having XSS everywhere, you can basically be pretty sure if someone's putting something in here, I want to investigate it. It could not be XSS, but it has a pretty high chance. And by default it's already encoded. So this is safe by default, usually, unless you need an exception. All right, let's talk about SQL injection. Previous speaker was like, hey, this is still a big deal, even though it's 30 years old. Well, you can reduce a huge amount of it if you use an ORM. Who here knows what an ORM is? Sweet, I'm with my people. All right, so object relational mapping. Instead of doing raw SQL, where you have this nice user-controlled statement right here, they can just add in whatever you want and make the query whatever you want. You can just use a built-in sort of query built-in and you don't have any sort of dynamic SQL. So there's no terrible string concatenation. There's no evil plus signs, right? And here's the truth. The developers weren't trying to write insecure code. They were trying to just do whatever query they needed. They just end up shooting themselves in the foot. So how do we make this easy? And how do you do it on lots of other things? Because I did two areas that are already taken care of, but if that solved everything, I wouldn't be up here. Well, I kind of have four steps. You find the bad pattern. You find a common sync, essentially. You make the safe pattern, the default one. Then you train the developers to use the safe pattern instead of using the bad pattern. And then finally, you make some very simple and very easy static analysis tools to ensure this works a lot better. All right. So who here knows what regex denial of service is? It's cool if you don't. I'm OK with that. Just wanted to see what the audience was like. So essentially, if you send in user-supplied regex or even just badly constructed regex, it will take exponential time. So the server will just spin out doing that process forever. And that's pretty nasty. I work at a place where we take a lot of user-supplied regex, and we want to eliminate this problem once and for all. So what you can do is you just say, all right, cool. Bad regex right here. And the developers always have to remember a timeout. And then it's safe. But who can just assume the developers will oftentimes forget a timeout? It's probably going to be pretty common. So what you can do is just make your safe regex class. And you write this once, and then you handle it. If you're not super technical, don't worry about it. It's pretty simple. You say, I'm going to use the Billton regex library in our framework or Java or whatever. And then you're going to just say, it's going to, by default, always have this time span as a timeout. So you make it one or two seconds. Very simple. Now you have the safe one. Now all you have to do is train the developers to not use the dangerous one, which is here's how you can write your training. This is a template. This is AdLibs. I use this, and it's fantastic. If you use the bad way, the bad thing will happen. Instead, use the good way since it stops the bad thing. That's it. This is it. And then you include examples. And I want to highlight a few notes, right? Explain it very simply and clearly. You don't need to go and use security lingo. So you can just say, instead of saying, this causes Redos, this can say, this will cause the server to take too long to evaluate the regex, that sort of thing. I also really like to show the developer intends to do it before I show them how they should do it. So it's a weird little trick, but it's just something I've gotten from, I guess, experience doing this, that it just shows they're just more likely to say, oh, that's what I was trying to do. And then you show them how you would like them to do it. So here's the sample training. I'm not going to read this, but it basically used that nice template. And then I always like to include this example right here. So it's very clear. And it also looks about the same length, so it doesn't look more complicated. Complexity ends up getting in the way of execution. All right. So then training developers is the main thing. So training developers is usually I recommend when they get access to the repository. So that way you can give, they're usually the most excited then. They're usually ready to do their first commit or pull requests. And then they're pretty open to that training. And then once a year you retrain for their specific department or whatever cadence you want. You want to make sure that you are not a cardboard security guard. You want to constantly remind them. So then let's talk about how you do basically code analysis on this to enforce these rules. So my favorite way of doing this is to go really, really easy. And that is you use basically regex. But essentially I like this tool called DevSkim because it's grep with a JSON config file. It's open source. It's made by Microsoft. It's pretty good, right? Because all you have to do is write that little pattern. And you notice it's escaped weird, but that's it. It will detect the bad class. Now if you want to get more specific, you can use a couple other tools. There's Roslin. There's GitHub Semantic. If you have access to other more paid tools, that's also fantastic if you really want to be more specific. This little snippet right here is exactly the code I use to detect bad classes. But it's for Roslin, which is .NET only. But you can use this on across every sort of framework and language. And also I'd like to recommend one talk by Clint Gibbler called Rolling Your Own for Rolling Your Own Static Analysis. He talks very much in depth on how to do this. So the next thing is I'm going to just show you one of these big DevSkim rules because they're actually way simpler than you think. And even though it's a big, scary blob of JSON, I'm going to break down the key parts of it. So first off, I just start with a very, very simple rule over here. And then that simple rule, I just try to aim for 80%. There's probably some edge cases around it, but you find most of the problems that way. And then the second part is you can have very, very clear description. And if you have documentation, that's good. You should link to it as well. And then to finally have exclusions, so you see my SafeRageX class, then you have an exclusion to say, hey, don't flag on this. This is amazing, right? They're following the rules exactly how we want. All right, so when do you use this? Well, during the pull request is fantastic. Most of the time developers are open to that during then. In fact, later there'll be a talk by my colleague Arvy about how to do this in very good depth. So I highly recommend you come to that. There's only one track, so you should. And also on your own cadence to go on further depth. But that's more for yourself, less for showing to the developers. All right, we stopped Redos. And that wasn't so hard. Pretty simple. All we did was find the bad pattern, make the safe pattern the default one, train the developers, gave you training, and then build tools to enforce those rules. That's it. Once again, that's my talk. Thank you. No, let's go through a couple more examples, and then we'll recap. But it was very, very easy. So XXC, who here knows what XXC is? Cool, good enough. I won't describe it then. No, when you're parsing XML, there can be parts in the header file called the header area called the DTD. And essentially, it can define weird variables that let you breathe from the file system, or you can use the billion laughs attack or all sorts of nasty things. But to block it, all you have to do is just say, hey, don't allow external entities. Easy enough, but developers oftentimes forget to do that. And most XML parsing, it by default allows you to do that. So this is weird, and nobody's ever going to remember to do that all the time. And by the way, I'm just picking on this particular Java parsing library just because I found it. There's nothing particular about it. Nearly all of them have this problem. So whatever one that your company is using, or the developers like to use, I highly recommend you just wrap it and then make your own my safe XML parser. OK, then you have the training, same format, if you do the bad thing, the bad thing will happen. And the same example of unsafe and safe. Same idea. We use the exact same strategy. Again, and I can just plug and play this anywhere. And you solve it across your entire code base. And even then, using the same tool, very, very quickly writing some regex to find this stuff. And you find the problem very quickly. All right, so we made it really easy to solve XSE across your entire code base. Easy stuff. Sorry, this isn't the cool stuff where you hack into something. This is how we can defend stuff while being really lazy. All right, so let's get a little bit more fun. Imagine getting an email like this. Looks totally legit. I like this link right here. Anyone shout out what this bug is? Just shout out. Yeah, open redirect. Love it. Mr. Robot likes it, too. No. So open redirects lets you do some nasty things. It can trick users into going to phishing sites. And if you don't block the protocol, you can also get cross-site scripting. The fix is usually to recommend people use a whitelist. So I have a whitelist right here. And now let's play a game called Let's Spot the Bug. If you can't see it from that far, I apologize. But just yell out if you're able to see what one of the bugs are. Isn't anchored, what do you mean? Bingo. So that's one of the big ones. You can basically say it's part of the query string or part of the put at the end, or you could do subdomain silliness. So yeah, that's the nasty part. As he said, you can put this part of the regex anywhere you want in the string to show some examples of what could go wrong. The first one is saying, hey, I could just make this part of the subdomain. And then myevilwebsite.com, you can redirect to there. Then you could do evilwebsite.com, and then you could just put it at the end in the query string parameter. Or, hey, there's nothing blocked in the protocol, so my safewebsite.com, and voila, a little bit of XSS for you. It just needs to contain the string. So what I recommend is you create a safe redirect method or library that just works with your existing code base. And what I'd usually do is you an internal redirect that blocks bad protocols and also only redirects to your own site. And the nice thing about it is if the developers use this, you can usually assume it's safe, which is quite nice. So you take about 50% of the problem away instantly. And then the ones where they do use external redirects, you can just audit these and just ensure that they're doing it properly. And that's pretty quick to pick up with some static analysis, repping with a JSON file. All right. One more example. This one is server-side request forgery. Anyone know server-side request forgery? Just raise your hand if you know. Sweet, all right, I got my tribe. So essentially, you're able to get one server that you don't own to make a H2B call or any other web call whatever to another server. In this case, maybe you might not be able to attack this server directly because there's a firewall blocking it. But if you can talk to this server and then make a server-side request forgery, let's pretend they're all microservices. And one's hidden behind the firewall. Then you can talk to it as you want, right? There's lots of other nasty things you can do with that. Like, let's pretend you had server-side request forgery in C sharp, just as an example. Well, you can get past the firewall. Here's some other nasty things. You can call servers with long responses. So that's a good nice little denial-service tactic right there. My favorite thing, though, is by default in .NET and you have to check with whatever framework you're using, if it's Java, Ruby, et cetera, is by default, file reads and file writes and web request calls are essentially the same thing unless you cast them. So you can do a file read to some secret file. Or you can write and just take down the website or get remote code execution, which is fun stuff. So how do you defend about this? Well, you make a safe version of it, right? Sometimes you have to do this. And then sometimes you get this scary acronym if you have a webhook, right? And I'm not going to even say that, it's that offensive. But essentially, you have to allow your server to make external calls. And sometimes users are defined, right? But you can block internal IPs areas they shouldn't be talking to. You can have built-in timeouts. And you can block calls to the file system, because that's super nasty. And the safe version that inherits all the features of your web client library. So you don't have to rewrite everything, you're just setting the right settings on your safe class. All right, recap. Because I went very fast, but the strategy is the key thing about this, not the particular examples. You find the bad pattern. My rule is for this, it doesn't work for all bugs. But if you can find a common sync, for example, all regex denial service requires regex, right? All xxc requires xml. All server-side requests forgery requires a web request. So they have a common sync. Therefore, if you find a common sync, it's usually a pretty good pattern to try. The next thing is you make the safe pattern the default one. You make it very easy for the developer. And it's something like my safe regex, or safe whatever. And then you do it once right, and you maintain that. It's something that if you have an app stack department, or whoever you decide to do it, just has to maintain and make sure it's OK. But it's usually fairly simple and fairly easy to do. And then you train developers to use the safe pattern. Take a picture of the slide, because it's fantastic, because you don't have to rethink on how you're going to write it every single time. I use this all the time. Cool. I see you there. Cool. It's OK. These will be online later. And then once again, put in an example, because that really helps get the point across. And then you build tools. Now I highly recommend DevSkim, because it's really easy. And you can get something up and running really quick. But if you have a more complicated tool that you prefer, go for it. It's your choice. But having this to enforce the rules is highly valuable. And I highly recommend you do it just like 80% effective. Don't worry about getting all of the security bugs. It's OK. That's a weird thing to say at a security conference. It's like, get started. Don't worry about it. And once again, very, very simple rules. So once again, I'm going to recap one last time. So if I didn't hammer in enough, basically you find the bad pattern. You make the safe pattern, the default one. You write good documentation around to use it and good training. And then you build tools and enforce these new rules. And then you've just annihilated entire security problems in your code base. And then you got to do this. And it's easy. A to B. I like it. If you want to contact me, here's my contact information. And I'll be taking questions after this talk. Let's have lunch.