For those who don’t speak Russian or Ruby-on-Rails, I thought I’d translate the recent GitHub hack controversy.
The underlying issue is an “Insecure Direct Object Reference”, #4 on the OWASP Top 10 list of most important web-application vulnerabilities. It means that that a hacker can change what's in the website database without having permission.
The cause of the GitHub hack was the toolkit/programming-language they used to build their site: Ruby-on-Rails. Ruby-on-Rails supports a feature known as “mass assignment”. It means that hackers can add parameters to webrequests that don’t belong there, and they’ll be assigned to the object along with the normal parameters. In other words, your account might have a flag otherwise invisible to you like “admin=false”. By including “user[admin]=true” in an otherwise innocent web request, you can give yourself administrator privileges and take over the site.
This “mass assignment” feature is pretty toxic, at least as far as cybersecurity goes. It’s one of those big features that make Ruby-on-Rails so easy to use in order to build websites. Fixing the security problem therefore makes it harder to program websites in Ruby-on-Rails, and would instantly break most existing websites built using the toolkit.
That’s why when Russian programmer Egor Homakov reported the “bug”, it was rejected. The argument was that this is behaving by design, and that while it was dangerous, it was prominently described in the “Ruby On Rails Security Guide”. There is a solution for programmers: “blacklist" values that should not be mass assignable, such as marking “admin” as something that causes a mass assignment to fail. In other words, it’s the owner’s responsibility to not shoot themselves in the foot, not the gun manufacturer’s.
Any cybersecurity professional knows this is wrong, but being Russian, Homakov’s English skills aren’t so good at arguing his point. So he used his hacking skills instead, and used the bug to hack into GitHub.
GitHub and Ruby-on-Rails are independent projects that are otherwise unrelated to each other. GitHub is a popular project hosting site, and it just so happens that one of the zillions of projects it hosts is “Ruby-on-Rails”. On the other side, Ruby-on-Rails is a toolkit for creating websites, and it just so happens that one of the zillions of websites written with Ruby-on-Rails is “GitHub”.
This gave Homakov a neat opportunity. He wanted the owners of the Ruby-on-Rails project to take him seriously, so what better way to do that than hack the very site hosting Ruby-on-Rails using the very bug he was talking about? He used the bug to hack into GitHub, and gave himself administrative control over the Ruby-on-Rails project. He used this hacked authority to then write a comment into the Ruby-on-Rails source code discussing the problem.
It took no time at all for GitHub to fix that one bug, by blacklisting the hacked value so nobody can repeat the hack. But GitHub can’t be sure that there aren’t more mass assignment problems in their source code waiting to be discovered. Given any complex website written in Ruby-on-Rails, there is a good chance you can eventually find a mass assignment bug if you try hard enough.
There are a few cybersecurity lessons here.
The first lesson is that when you own a gun that accidentally fires 1% of the time you pick it up, then you’ll eventually shoot yourself in the foot. The same is true of Ruby-on-Rail’s mass assignment: you’ll eventually shoot yourself in the foot. It’s inherently dangerous, you can’t consider it for your next big project until this bug is fixed -- and since fixing this bug will break all existing Ruby-on-Rails websites, I doubt that will ever happen.
The second lesson is that “blacklisting” doesn’t work. We’ve tried blacklisting known bad characters (like ') from SQL, and found it doesn’t stop SQL injection. We’ve tried blacklisting known bad characters (like <) from HTML, and found it doesn’t stop cross site scripting. You can’t expect programmers to correctly blacklist all variables that shouldn’t be set with mass assignment, because they’ll eventually forget one, a hacker will find it, and break in. Instead, you have to “whitelist” known safe variables, where the consequence of a programmer error is simply a bug in the website, not a hack.
The third lesson is that there is no good solution to the problem. Ruby-on-Rails already has plenty of what appear to be good solutions -- that fail. If you put “ActiveRecord::Base.send(:attr_accessible, nil)” in the file “config/initializers/disable_mass_assignment.rb”, you will fix the problem the way it should be fixed. But while good for you, most programmers still won’t use it,and there will still be a pervasive problem with mass assignment. We’ve had an obvious solution to SQL injection for a decade (“parameterized queries”), but most programmers still don’t use them, so SQL injection is still the web application’s #1 problem. “Insecure direct object reference” will stay at #4, or even rise to #3, until the Ruby-on-Rails project makes a change.
The fourth lesson is understanding "ease of use". Mass assignment makes creating websites a lot easier. But it makes securing websites much harder. You lose more in security than you gain in ease-of-use of the toolkit. As the GitHub hack showed, if you are putting your site on the Internet, security isn't an option. You don't need to fix every security problem, you don't even need to fix everything in the OWASP Top 10. But if you ignore the the top 4, you are a fool.
Finally, this shows the benefit of irresponsible disclosure. Homakov possibly broke the law, or at least, behaved “unethically” according to many people’s definition. Yet, it was not malicious, and caused no harm (other than deserved harm to reputation). It was the level of “disclosure” needed to bring what I feel is necessary attention to the problem.
Update: ASP.NET has a mass-assignment problem too, just not as big as Ruby-on-Rails.