00:00:29.800
Hi! How are you guys doing today? Great! Are you here to learn about Rails security?
00:00:34.960
How many people are absolutely certain their Rails application is 100% secure? Yes, Rich? I believe you. Anyone else?
00:00:43.680
Not? Uh, this is us! We got a great introduction, so we'll just skip that. I started thinking about security seriously this past fall when I ran into an article by Patrick McKen.
00:00:49.239
He was writing about the Diaspora code base, which is an open-source Facebook replacement that respects your privacy. That code just went out on alpha release.
00:01:08.159
He checked it out, thought he would look it over, and was surprised to find several severe security errors. In summary, he said that the bottom line is: there is nothing that you cannot do to someone's Diaspora account—absolutely nothing.
00:01:16.040
In other words, the site is entirely hackable! You could take over anybody's account quite easily. I don't know if that scared me because I'm thinking, 'Well, I do Rails development', and you know what I know the basics of security.
00:01:28.280
I've gone through all the security lessons and I know all that stuff, and it was scary to me—it bothered me a lot.
00:01:35.840
Let me just give you an example. This is some code that we were playing around with back at EdgeCase. We did the Ruby Coin project, and someone had the great idea to put the coin online.
00:01:43.600
You can actually go through the coin on a web page, and you can see these tests. We're asserting equality. You can fill these things out, and when you fill them out with the right thing, the test turns green.
00:01:55.039
Well, we're actually typing in Ruby code at that point and evaluating it in the browser. Yes, you're laughing already; you know what's coming, right?
00:02:06.680
Within two minutes of the guy who did this, he published it in our Campfire room. Within two minutes of that, someone typed, 'The answers which you seek are...' and this is the Etsy password file.
00:02:22.680
What he did was type in 'system cat /etc/passwd' into the text box there. Well, he thought, 'Ha! That's clever!'
00:02:32.120
I'll fix you guys! I'll just disable the system command. So we switched to using backticks. Okay, okay smart guys! We'll just disable backticks. At this point, he decided, 'Alright, I need a real sandbox to put this stuff in.'
00:02:52.120
And actually, we're working on putting this online for real right now, and it's in a real sandbox. Theoretically, you're not going to be able to break into it once we actually release it, but we're still playing around with these ideas.
00:03:06.560
But the question is, you know, while we were playing around with this, we knew it wasn't secure—it was an internal thing and we were just having fun with it. But in real life, what are the security concerns?
00:03:16.680
Just two, maybe three days ago, I saw this post from Martin Fowler. Did anybody see this? This was on ThoughtWorks.com. If these guys don't know what they're doing, what hope is there for the rest of us? Evidently, they have some malware on their website.
00:03:34.600
It's transient; they can't track it down. It shows up sometimes in their Google reports, sometimes not. They're not quite sure where it is. It might even be a problem with their Pion; we don't know for sure. They are tracking this down now; they have suspicions, and they think they've tracked it down, and they're working at it.
00:03:57.280
If you see anything suspicious, let them know. But this is a tough problem to solve, absolutely. We've used five minutes now of our 30-minute talk. We are not going to be able to cover anywhere near all the security concerns that you have to think about when you're doing a website in the next 30 minutes—absolutely no way.
00:04:10.120
First of all, I want to say I am not a security expert. I did not study these things in depth. These are just things I got interested in when I saw that posting. I thought it would be a good idea to share with you some of the basics you should be doing. After this talk, every one of you should go and read the Rails security guide. This is really comprehensive and really good; they cover things specifically related to Rails.
00:04:51.759
Another resource you can Google for is the Ruby on Rails security guide at rubyonrails.org/security.html—that's easy to find. The other resource is the OWASP Ruby on Rails security write-up. This is a PDF—it's a whopping 48 pages of stuff that you need to know if you're doing a public website. I'll say, if you're doing an internal website, there are vulnerabilities in those as well, and this is a good guide to point that out.
00:05:19.919
So that's your reading assignment after you get done here. But now for the fun part! This is your typical setup for a Rails application: you've got your server, your browser, and your database. Out of these components, which of them do you trust?
00:05:39.760
The browser, obviously not. The browser is entirely out of your control. Anything coming in from the browser is suspect. You need to validate it, check it for bad things, and you need to treat that data with the utmost respect. That includes not only data and forms but also cookie values and URLs. Do not put critical data in URLs because they can be easily hacked.
00:06:03.080
All of this stuff can be easily hacked, and we are going to demo that today for you. What else shouldn't you trust? Well, the database! You may think you have complete control of that database, but it's quite easy for a hacker to slip in data past your application.
00:06:18.319
Just because it's in a database you control doesn't mean that it's good data and it's safe to display however you want to. Cross-site scripting attacks often come from storing stuff in the database that is later displayed to other users. So out of these components, maybe you can trust the Rails server because that's where your code is running. If you can't trust your code, you probably have bigger security issues that we want to talk about right here.
00:06:46.320
In particular, the browser and database are the things you need to be concerned with, so we're going to start with the basic vulnerability. I call this the 'little Bobby Tables' vulnerability. We have an application that Matt and Jerry at EdgeCase did—it's a very nice movie night reservation app.
00:07:03.240
You want to watch a movie, you send invites to some friends and tell them about the movies you're going to watch. We played around with this application and have now let me preface this—all the vulnerabilities we're going to display today were not in his original code.
00:07:18.120
We had to either change the code base or disable features in Rails for us to actually demonstrate this. So that is the good news in all of this—that Rails is actually doing a very good job of implementing security, but you need to be aware of what it's doing for you.
00:07:37.360
Let's start with this. This is a simple finder and we're filtering some text over all the users. We want to find all the users with a name like the filter text, and we're interpolating that text right there.
00:07:52.560
Do you see the problem? Everyone should see the problem with this. If you are doing anything like this in your application, you are at security level zero. Your PHP program might give you a pass on that, but in Rails, zing! Do not ever do this in SQL statements.
00:08:06.160
I'm going to turn this over to my hacker-in-residence, Matt, and he's going to actually show you what it looks like.
00:08:17.400
Okay, here's a quick demo. As Jim referenced, the example app here is the movie night application where you can schedule movie nights with friends.
00:08:30.320
We had to bring in an interface that let us expose the data we're showing. We created this listing of users, which you can see, and we added this filter so we can filter by name.
00:08:45.120
If I say I want to filter by Jerry and apply the filter, there we go! Now we only see Jerry, which is imminently useful. But what if we change this a bit?
00:09:03.920
Notice he's hacking the URL directly, going directly into the URL. So we'll just add a little bit of additional what looks like possibly some SQL in here. S1' or '1'='1.
00:09:19.920
Oh look at that! Our list is a little longer! Now you can see the administrator on our site—serious business!
00:09:36.000
Did you see how simple that was? That was just maybe six or seven characters he had to type in to do SQL injection, and he could have done that directly in the filter box too.
00:09:48.000
That's interesting! We could actually do something a little more complex with this and let's just give our filter a little more functionality by trying '1'='1'; DROP TABLE users; --.
00:10:06.480
Now we see the administrator's encrypted password! We've got the encrypted password from the database, ouch! At first, you might think 'Oh, it's encrypted; we're safe!'
00:10:20.560
But you can crack that if the password isn't strong enough. If it's not a good password, that is actually quite easy for hackers to crack.
00:10:36.120
What has happened is we intended for a string like this to be interpolated by clever use of input from the command line, commenting out the remaining SQL and inserting a condition that's always true.
00:10:50.200
We were able to dump the entire user database. We were able to use UNION commands within SQL to pull in fields that were not normally pulled in, and get that data out as well.
00:11:05.160
So, if you can do SQL injection, essentially your database is open for any piece of information to be pulled out of it. What is the solution? Use question marks and the built-in SQL-based interpolation.
00:11:19.920
Pass the parameter as a separate piece that is filled in. The database driver knows about question marks, and it will fill that in without danger of SQL injection.
00:11:34.320
It will quote the comments, and it'll quote appropriately, and you don't have to worry about that. So please, please, please do this! This is the most basic level of security.
00:11:49.520
This is a big problem in Rails, and I was aware of it but not really worried about it. It turns out that the way I write code could have fallen to this vulnerability, but now that I'm aware of it, I can code around it.
00:12:07.240
You do this a lot in Rails: you can update user attributes and just pass up all the parameters in the form that come in like that.
00:12:22.520
Matt, would you demonstrate? Absolutely. So, I can click here and go into edit my profile. I can change a couple of fields here. I could change my name, which I probably won't, or my email address, which actually stayed the same.
00:12:39.600
But what I could do is bring in one of our favorite tools, a DOM inspector, and do a little bit of direct manipulation to try and get around the intended security of the form.
00:12:50.200
So, I drop in and find the email address field for the user and by editing this, I'll say instead of email, I want to set that to true. The 'admin' flag in the database specifies whether you're an administrator or not.
00:13:12.960
So now Mark is now a super admin, and he can run around and do anything that comes to mind. In Rails applications, it's particularly trivial to do this with debugging tools.
00:13:36.319
If there are parameters in your class that need protection from general updates, you need to do one of two things: either use 'attr_accessible' to declare all the fields that a form is allowed to change.
00:13:50.880
Or you use 'attr_protected' to declare all the fields that the form should not change. So, which should we do: accessible or protected? Accessible is better!
00:14:10.440
Why? Because you can maintain what is particularly good. That's why whitelists are better; if you forget something, you’re still protected. A lot of people prefer protected because 'Oh, I've added a field and my form won't work.' But you'd rather deal with temporary annoyance over security issues.
00:14:28.480
The danger with 'attr_accessible' is if you forget to add it to any model, it defaults to everything accessible. So if you're going to use 'attr_accessible,' it's highly recommended to have something in config initializers to account for this.
00:14:44.000
For example, in ActiveRecord::Base you could set 'attr_accessible' to nil. You also need to think more deeply about which fields need to be accessible and which need to remain protected.
00:15:04.880
In essence, if the data isn't owned by the person editing the field, it should be protected. For example, a user should be able to own their name, their password, but the admin flag is not something that can be changed freely.
00:15:20.280
Anything dealing with permissions should be protected. This includes roles and security-related aspects.
00:15:36.680
Always prefer whitelists over blacklists. It's crucial to only list things that are permitted rather than everything that is not permitted. You can't think of everything a hacker might try.
00:15:52.480
Cross-site scripting is another common vulnerability dealing with database data. Let’s demo that.
00:16:07.960
Suppose I want to create a new movie night and invite all my friends. Let’s say I'm pretty confident that everything will work fine.
00:16:23.640
I could write in the notes field something like 'popcorn provided.' I might want to emphasize it, so I think about making it bold.
00:16:41.240
That is, just to be clear, because everybody loves popcorn! But let's see how this actually works when I try to add some HTML and make popcorn bold.
00:16:56.200
I'll just pick something here. So, we really want to ensure people know popcorn will be provided.
00:17:12.720
Let’s see if we can submit that. If we attempt and the process fails because it doesn't interpret our formatting correctly, that would be somewhat disappointing.
00:17:26.440
Okay, so it seems we may have accidentally filtered it. But, bear with me, let’s put just a benign enough form together.
00:17:40.840
I want to make sure we understand this feature we’re working on! Each time we test a cross-site scripting approach, we need to be cautious as this demonstrates the cookie data.
00:18:03.960
Let me try something here with coding. The intention is to showcase how raw output could potentially expose session information.
00:18:23.120
Clearly, there's a risk of data leakage if we do not prevent raw output. If we need raw HTML for any functionality, we must ensure we sanitize it!
00:18:39.280
This is a strong method used across Rails applications allowing you to explicitly control the tag use. Cross-site scripting vulnerabilities are real!
00:18:55.960
Alerts from hacks have occurred before; MySpace lost a significant number of records due to cross-site vulnerabilities.
00:19:11.120
We also must mention that many sites like Twitter have struggled with similar issues! Protecting against cross-site scripting is critical.
00:19:27.720
There's a vulnerability point where a hacker may gain entry and manipulate data corresponding with your permissions.
00:19:44.240
Thus, measures such as privilege escalation can help identify how to remedy access rights once a threat appears.
00:20:01.080
Let’s continue by stressing the importance of proper access control mechanisms for data-sensitive applications.
00:20:21.479
Security should be meta-cognitive; you should always analyze your approaches to managing data-based applications effectively.
00:20:42.679
Let’s shift focus to Cross-Site Request Forgery (CSRF), another significant risk. The reality of web interfaces is that attackers can submit fraudulent requests on behalf of authenticated users.
00:21:04.960
Utilizing token strategies in your Rails administration is the best form of preventative security! The session IDs should therefore always renew as users interact with the site.
00:21:22.719
Also, make sure your application enforces restful methods for modifying stateful resources! You must ensure that your data isn’t altered unnecessarily.
00:21:45.969
You should determine that session and browser interactions remain safe through unique authenticity tokens! All public hosted applications are inherently at risk from these vulnerabilities.
00:22:03.980
Relying solely on HTTPS is an impractical solution; tokens must evolve also! It’s important to maintain distinct communication standards accordingly!
00:22:24.080
Notes also about data handling: do not forget to reliably process your application to filter potential attacks! It leads to best practice security!
00:22:41.280
Cross-site scripting remains relevant consistently, and with further diligence, we must deploy the latest protocols ensuring safety! I want everyone to express this knowledge efficiently!
00:23:02.520
Rapid advances in security must be matched by an equally responsive community! If not effectively communicated, this awareness becomes less impactful.
00:23:17.280
So, always keep security in mind, trust no one, and encourage resilience among fellow developers!
00:23:32.920
Thank you for your attention! Any questions?