 All right, welcome everyone. I'm going to be talking about rail security and the history of rail security. My name is Justin Collins. I'm president beef on the internet. I have not like a ton of slides but more than I'm normally comfortable with and there's a lot of information. So I probably explain some things too much and some things not enough. So I say if I say something that you don't understand or a term that you've never heard of take that as an opportunity to like go Google it and learn about it. The slides also have like a ton of links in them. So I always post all my slides online on my website so you can go back and like click through those links and learn more, get into the details of things. There's going to be like two parts. The first part is essentially a bunch of security issues that rails has had in the past. And then the other part is some of the features that have been added over the years. So you're supposed to do one of these slides. I also calculated, this is my sixth RailsConf fifth time speaking and also second time sponsoring but not enough to get on the big screen that you saw at the beginning of the conference. I've been doing application security for eight years about eight years at some different companies. Same eight years working on a security tool for Rails called Breakman. Does anyone here use Breakman? Okay, so everyone who didn't raise your hand if you're working on a Rails app you should probably go and try Breakman. I'll give you a very short tutorial in the middle of the talk. And I've also been working on Breakman Pro which is like Breakman except it's more pro as implied in the name. So this conference already like I think has addressed a lot of history about Rails. So some of this might be your repeat, sorry. But July 2004 Rails was released. This was the email from DHH to the mailing list. Rails 0.5, it is no longer vaporware. So it was out 2004. End of 2005 Rails 1.0 was released. Here's the blog post. It's out, great. August 2006, so less than a year later the first CVEs for Rails were announced. And if you're like what are those things? What are CVEs? I will tell you that I always forget what CVE stands for because in the security world we just call them CVEs but they're actually CVE identifiers and CVEs are common vulnerabilities and exposures which is a registered trademark of a company called MITRE which essentially manages these things. And the reason that they do that is because otherwise I would be up here saying okay, so like in 2006 there was like a security issue and it was like this thing and you'll be like oh this one and I'm like no, no, no, not that one the other one and it gets really confusing. So essentially you can assign these identifiers to publicly announced vulnerabilities so that we can all talk about them in a coherent way. And you may have noticed the middle number is the year and usually that's the year it comes out. Sometimes it's the year they requested the number and things come out a little bit later. So 2006 there were two CVEs that came out for Rails and I really like the post around it because I think, well at least for those of us in the security world this is like a bit of looking back at the way things used to happen and they don't go like this anymore. So there was a post by DHH August 9th, 2006 evening says look hey we're working on Rails 1.2. However there's a mandatory upgrade that you need to do because there's a security issue. However it's so bad we won't tell you what the security issue is. And that's something in 2018 like doesn't happen anymore. When they're released they're released and typically a lot of details along with them so everyone can understand what's going on, the impact and so on. But in this post it's just like look just like we can't go into specifics just upgrade. Please, please, please upgrade. The next day August 10th and I don't know if 3.38 AM was the local time for DHH when you posted this but it was kind of like a midway update. Like okay there's only a few versions that are affected but it's extremely serious. We're all working on it. Thanks for being understanding. Sorry this is so terrifying. About 13 hours later there's another post that says look okay so people kind of figured out what's going on. We didn't fully fix it the first time with 115, here's 116 and I kind of left out the stuff if you were in Michael Hartle's talk a lot of stuff below this is like this is how you upgrade rails and this is how you can fetch a gym and kind of a lot of the deployment stuff that we don't really worry about so much and also stuff about how to change I think mod ruby or something so that you avoid this problem. Again there's the link you can go look at sort of the historical stuff but even though it says here's the full disclosure edition it doesn't really say what the problem is. It's something like okay well you could load the profiler which doesn't really make a lot of sense. So all I really got from this was like it was like full on panic just there's something wrong and this happens to a lot of software teams you have a security issue and you actually have never gone through it before and you have no idea how to handle it and that's exactly what I saw in these blog posts. I looked around and Evan Weaver had a blog post from that time he and also I recently tried to look at the diffs between 114, 115, 116 to figure out what the security issue was and it's like who knows what's going on it's really difficult to tell so he did he instrumented his app and tried to figure out it was something about how files were being automatically loaded and if you look the URL here is slash db slash schema and if you look down at the bottom you see it says hey I found a file that matches slash db slash schema I'm gonna load it and essentially the vulnerability was the routing layer would look pretty much anywhere in your Rails app for a matching file and then it would load that file and then it might go oh well that wasn't a controller I guess 404 or something but it would still load and execute the file and that included by the way the at the time if you had like public slash uploads or imagine any Ruby file that might be on the server you could execute it so that was pretty bad this is what we call RCE or remote code execution basically the top of the pyramid for security issues I can run arbitrary code on your server all right 2007 CVE 2007 5380 this one was kind of interesting because they basically just dropped a feature so I don't know if you remember 2007 but it was really common to see like J session ID or PHP session ID or in this case like underscore session ID in the URL and that was your session it's a very bad idea to pass around sensitive values in the URL in 2007 you may recall having HTTPS was kind of like a luxury so these URLs very easy to find intercept replay steal et cetera so when the CVE came out they actually just drop this feature they're like you can no longer pass sessions in the URL as a query parameter only cookies something else caught my eye not security related it used to be slash person slash one semi colon edit was what the URL would look like and I wasn't around Rails in 2007 so I was like what like this looks insane to me and they blamed it on libraries interpreting semi colon edit as like part of the query parameters but I think they're like totally justified in saying like okay you shouldn't have semi colon as part of your URL just that was just a side thing all right jumping ahead to 2011 there was a CVE this one so this one's interesting for a reason that I'll get to you in a second first up cross site request forgery works like this I log into my bank account that's my current balance I just come here for fun I log into the bank account and then I go and visit some other website while I'm logged in in the sound browser I go visit another website that website makes a request to my website not my website my bank website so quick someone shouted out how does an evil website make a request to my website? Yes image tag thank you right on easiest way image tag URL of course that makes a get requests most people kind of realize like it's way too easy to make get requests and we know rest we should not have state changing actions behind get requests so you put it behind a post but it's almost as easy to make a post request across so if I had a URL like this and I know it looks ridiculous but trust me there were issues that look just like this so I'm like okay I'll just like transfer some amount from the sign in account whoever that is to my account as the attacker now I'm the attacker sorry I changed rules it's a one-man play up here so can anyone tell me why this works maybe the guy who shout out image tag okay yeah exactly cookies so when you make a request to a site regardless of where the request is coming from the browser will send the appropriate cookies for that site I will say this is changing relatively soon there's a new thing called same site cookies where this it essentially gets rid of cross-site request forgery that's not part of Rails yet though as far as I'm aware okay so that's cross-site request forgery, great this is how Rails takes care of it and used to take care of it as well as fancy name is synchronizer token pattern I put a token in the session I put a token in my forms for my post requests and then when I get a post or delete or patch or put or whatever I check those two against each other and if they match great if they don't reject the request so that's awesome we didn't cover get but again you shouldn't put state-changing things behind get this is kind of what it looked like you're probably familiar this is what it used to look like now the token is much longer what about like javascript requests well the feeling in 2007 2011 also 2007 was it's fine because an attacker can't make a cross-domain XHR request and you can't forge it because in the context of CSRF you can't write the headers in the request so it's fine however this came out in flash there was a vulnerability where you could do this you could essentially set the headers on a post request forwards an XHR request and Rails would accept it because it trusted all XHR requests I won't go into the details of how this worked except to say in flash you have to have a cross-domain.xml file to allow things to happen cross-domain and the check for that happened after flash made the request it checked but too late so you can go read up on that as a result Rails changed how it did the protection now you have these meta tags and you have to send the token on every not get request but every kind of request including XHR and you may be familiar it looks like this and this allows javascript to pull out those tokens and send it along with the proper request great I just want to point out that the timer didn't start and I didn't start my timer so I have no idea where I am on this all right so 2012 mass assignment Michael Hardell mentioned it he didn't mention the GitHub side or Igor Homikov and Igor Homikov would probably be I don't know how we'd feel about the fact that we're still talking about him in 2018 in relation to this event but if you're around in 2012 you may have been aware of the drama that happened around this something like this first we have to understand what mass assignment is it looks like this your updating attributes you pass in prams and if someone comes along and they're like okay great I'm just gonna set user admin to true as part of this update and then Rails will happily accept that and I want to point out this wasn't like a all only Rails thank you this was not just Rails like PHP had this feature called different things it wasn't just like a Rails thing but it was something that Rails did okay so Homikov came along he was 18 at the time and he said hey Rails has protection against mass assignment but how do we make sure that people use it and he didn't feel like he got the appropriate response to his question let's put it that way so he started playing around and he's like well GitHub is on Rails maybe they have mass assignment his first attempt he was able to open an issue 1001 years in the future at the time simply by changing if you imagine like issue and then like date or something as one of the options he set the date to the future so he's like oh that's cool and then he was like well and you can read his blog post but it sounded like he kind of went to bed and was like wait a second I feel like I could do even more with this so you can look this was I took the screenshot recently 261 comments like people keep commenting on this for some reason so he made a commit to master in the Rails repo and he wasn't like super tactful about how he did this so how did he do it I pulled this from a post from Peter Nixie I guess and this is kind of like okay maybe the code on the GitHub side look like this this is the code to update your public key now I looked and I looked and I can't find any record of being able to edit your SSH keys on GitHub but everyone around the time was talking about doing that so I guess I trust them so imagine there was a controller like this and basically it was just like the example I showed you before mass assignment when setting the public key so what he did was like okay you know maybe there was a form that looked like this where you could change the name on the key he's like okay I'll just change the user ID on the key so he controlled the key it was his key but he assigned it to the Rails account and then he was able to push to Rails very quickly mass assignment over time I pulled this from previous talk Rails 2 like you could white or black list in the model actually accessible actually protected Rails 3.1 you could force all models to have to white list in Rails 3.2.3 if you generated a new app you would get that by default and then Rails 4 we got strong parameters which we'll talk about great so now 2013 if you were around and doing Rails in 2013 you probably went through this pain I was at Twitter at the time we experienced a lot of pain and a lot of sleepless nights over this so what happened first of all you can serialize arbitrary Ruby objects to YAML so here I'm dumping an object and then I load it back up great well if you can deserialize something probably you can figure out a way to execute code during the deserialization process and you can go to this post and it's like it walks through all this it's like very long and complicated and pulls out a lot of like weird classes that Rails had in order to achieve this but you could do it however how do you get the YAML to the server I know you saw the next slide but I'm gonna say something different so you could say content type YAML and send a request to the server and Rails would accept that if you turn that feature on which I don't think very many people did so that was out but you could put your YAML in XML and send that to the server and Ruby would deserialize the Ruby object and now you're back to RCE so basically we all went through and turned that off where we could or disabled this YAML thing inside of XML however there was like a part two to this I hope you're already please pay attention to this right here if you're not paying attention okay part two when Rails parsed JSON it converted it to YAML and then parsed the YAML yes it converted the JSON to YAML and then parsed the YAML so you could basically send up YAML tell it it's JSON it would try to convert it to YAML but it was already YAML and then you're back to where you started wow okay whew okay more RCE this is two different CVEs honestly it should have been one but that's a whole nother drama that you can maybe read about online start here if I have something like this and I'm passing I'm essentially allowing users to control what I render on the server side classic directory traversal looks like this dot dot dot dot dot go back up somewhere and then go back down some other directory so in this case hey render your gem file so I can see your dependencies not super exciting however until quite recently render with default to ERB so if it looked at a file and it's like I don't really see an extension I recognize I'll just treat it as ERB and if you have ERB then you're executing code okay that's step one actually I guess that's step two first was directory traversal second is I can render things as ERB now let me provide a payload to the server that will get written to a file that I know about how about the log file so I'll send up a request it'll be like nothing will happen with this parameter but it'll get logged as you can see down there down there parameters get logged there's ERB in the parameter now I render the log file now I'm executing this code on the server I'm back to RCE now the way to get this to happen the reason there are two different CVs one had to do with if you use these glob routing this glob routing feature and then the other one was render essentially being able to render any file on the server but I thought the cool part was putting code in the log file and then rendering the log file to execute it I don't know what happened in 2017 everything was cool I don't know quick tangent when you're talking about preventing cross-site scripting which I'm not gonna talk about you can go read about cross-site scripting if you don't know what it is there are kind of two things you can sanitize or you can escape and these two things get mixed up all the time even libraries will call sanitizing escaping or escaping sanitizing I wanna clarify this for you sanitizing means you take the input and you try to strip out the bad stuff escaping means you take the input you change special characters to safe versions of those characters and it's encoded and when it renders let's say an HTML they'll be treated just kind of like text and displayed properly why does that matter well because sanitizing is extremely hard we get it wrong all the time it's so difficult to figure out what's dangerous pull it out and make sure that when you pull it out that was a safe thing to do and the string you end up with is still safe very difficult escaping is extremely easy it's so easy you just walk the string replace this character with those characters and you're done that's it as long as you escape the right things it's so easy it's like 10 lines of code you're done why do I mention that here are all the CVEs I happen to find that are related to sanitizing methods in short avoid using sanitizing methods these ones or any other ones escape if possible otherwise you're probably gonna end up having to do fix something because of these alright is that really the time I have left? okay let's go Rails 1.2 2007 I ran across this 1.2 added parameter log filtering when you log stuff it can get filtered awesome Rails 4 this got upgraded from application level to sorry from controller level to application level this is the default configuration initializer that gets generated for you filter out passwords put your sensitive parameters in there and Rails will filter the logs for you awesome August 2010 I have to mention breakman 0.0.1 was released I mentioned I'd give you a quick tutorial here it is install it running good a few days later Rails 3.0 was released so it gives you a sense of like the vintage here I didn't realize that until I went back and looked what happened in Rails 3? Michael Harrell mentioned it we went from manually escaping things to automatically escaping things it was a little bit painful for some people to do that upgrade but overall that was like an amazing security upgrade for Rails really amazing now we kind of take it for granted and that's awesome that we do jumping ahead again 2011 well not jumping ahead one year later sorry Rails 3.1 what happened? we got has secure password awesome adds a password attribute to your user model automatically hashes it with bcrypt we get an authenticate method we'll do the comparison for us all our authentication problems are solved awesome nobody laughed okay well anyways it was a good thing to add in Rails 3.1 config.force.ssl was added in Rails 3.1 this just meant all your requests were redirected to HTTPS as of 5.2 and probably earlier I'm sorry I didn't get the exact version number on this redirects requests to HTTPS it says the secure flag on your cookies and it sends the strict transport security header very quickly the secure flag tells the browser do not send this cookie on any request that is not HTTPS that's it that's all the security you get for the security flag but it prevents people from eavesdropping and grabbing cookies the strict transport security header also called HSTS is a response header which tells the browser hey within some time window usually people say it's like a year or two every time your browser makes a request to this domain you're going to use HTTPS doesn't matter if I'm clicking a link or typing it in doesn't matter the browser will automatically change it to HTTPS and if you try to do HTTPS the browser will just stop you nope, won't work there's more details around that please take a look in particular be aware that if you set this you cannot have mixed content on your site which is a good thing that you don't have it anyway but just be aware it actually has some side effects June 2013 Rails 4.0 hooray strong parameters probably everyone here has a pretty good grasp of this because you're forced to deal with strong parameters but before this parameters were hashed within different access and what's cool about having it be its own thing now is you can start layering some security things on for example redirect2 now checks to make sure that you're not passing in params directly to it same with URL4 and also you can do things I didn't put in these slides but I've seen people do things with actually putting params into SQL you can kind of do it safely not into SQL queries but passing into like active record methods because it will be converted to a hash automatically and that prevents some SQL injection issues that's like an advanced usage I guess but this is awesome and we could probably build more on top of that Rails 4.0 we also got encrypted session cookies so before Rails 3 session cookie was marshaled and it was signed it was also like URI encoded and base64 encoded which was great in the sense that you couldn't forge cookies very easily but you could read them just fine so if people put sensitive values into the session cookie you could read them and sometimes that led to bad things in Rails 4 session cookie was no longer marshaled it was JSON which is good because serializing and deserializing things is dangerous still signed and it's encrypted so you can't easily read it also base64, URI, etc but this was good a lot of people were kind of looking for this however you should not put your session values into cookies anyway even though it's encrypted if your application becomes successful you will start feeling a lot of pain around that just a side note Rails 4.0 also added some default headers and they're all security headers which is great X-Frame options prevents a site from putting your site inside of an iframe and performing clickjacking attacks awesome XSS protection header is useless however we said it anyway this basically tells the browser turn on your XSS protection which all browsers do by default anyway let's just be safe X content options it tells Internet Explorer stop guessing that JSON is actually HTML even when I'm telling you that it's JSON Rails 5.0 added per form CSRF tokens so if you don't turn this on essentially a user has one token that they use for all their posts requests for their whole session you turn this on each form gets its own so if I steal one CSRF token from a page I can only use it for that one form so it kind of restricts the use of stolen CSRF tokens which are pretty hard to steal anyway honestly one added encrypted secrets there was a talk yesterday from Christopher Rieger Rieger he also wrote these blog posts so you can go read about it I won't talk about it that much but now you can encrypt your secrets 5.1 was like no never mind encrypt your credentials instead and Christopher mentioned in his talk that this is still like an ongoing discussion so in 5.3 maybe you'll see it's great that people are thinking about it and working on ways of safely storing credentials along with the source code yeah 5.2 also added more default headers and they're all security related so X download options tell us internet explorer when someone tries to download something don't show the open button just show the save button that's good I guess X permitted cross domain policies tells the browser hey if you're using flash and you're looking for a cross domain.xml we mentioned that earlier don't accept it even if I send it to you don't accept it don't accept any cross domain.xml don't allow any flash to be making cross domain requests for my domain so that's good refer policy is a privacy header essentially controls what the browser sends in the refer header and there are a whole bunch of options the default for Rails is this strict origin when cross origin which basically says if I'm on my origin my site, my domain and I'm going HTTPS to HTTPS send the whole refer no problem if I'm going to a different domain that's also HTTPS you can send basically any name and domain but not the path or parameters or anything if I'm going from HTTPS to HTTPS send nothing so that just protects privacy a little bit Rails 5.2 also added a DSL for content security policy content security policy is a response header which could probably take up a full day workshop easily insanely complicated not on the face of it when you first look at it, you're like this thing is awesome I'm going to use it and then you realize it has all kinds of crazy side effects different browser implementations I'm sorry it sounds like I'm trying to talk you out of using content security policy I'm not, it's an awesome header you should try to use it if you're trying to retrofit it onto a legacy application you are going to feel so much pain if you're writing a new application put it in place, get a reasonable policy and work from there the promise of content security policy is preventing XSS the overall sort of base level of content security policy is controlling what happens on your site what images are loaded what fonts are loaded what objects are loaded what plugins are loaded what scripts are loaded what those scripts can do and then there's like a whole bunch of other things as well so please look into content security policy but please be aware that it's like a deep subject with some weird edge cases you can Mozilla has the best documentation for content security policy there's like I don't know 20 directives, that's probably wrong but there are a whole bunch of directives that you can use much more than just these ones and essentially you just say where you can load things from and so on so please take a look at that and like I said it's built into Rails now not that it will create one for you but the DSL is there to set up the policy and you can also do like per controller I think policies as well as site-wide okay so typically on this slide I have like a whole bunch of links however the Rails security guide which has always been really good it seems like it's been updated recently so this is actually the best place to go to learn about Rails security and Rails security features it's like the most up-to-date at the moment resource and it's really good so definitely go check that out that is the end of my talk you can find me on the internet and at these places please check out Breakman and also I have Breakman stickers up here if this is your first RailsConf you should be aware that it's a requirement the speakers give out stickers unofficial requirement I guess thank you very much for attending