Github Mass Assignment Vulnerability Management

This site may earn affiliate commissions from the links on this page. Terms of use.

GitHub, one of the largest repositories of commercial and open source software on the web, has been hacked. Over the weekend, developer Egor Homakov exploited a gaping vulnerability in GitHub that allowed him (or anyone else with basic hacker know-how) to gain administrator access to projects such as Ruby on Rails, Linux, and millions of others. Homakov could’ve deleted the entire history of projects such as jQuery, Node.js, Reddit, and Redis.

Since launching in 2008, GitHub has quickly outpaced competitors like Codeplex and, depending on which metric you use, it has even outgrown the long-time incumbent Sourceforge. In essence, GitHub is a web-based wrapper around Linus Torvalds’ Git revision control system (which he initially wrote to aid Linux development), but it is the addition of social network features like feeds, friends, and trends that have fueled GitHub’s impressive growth. Ultimately, GitHub makes it very easy and fast for developers to collaborate — plus it’s free for open source projects — and as a result, some 1.4 million developers have been attracted to the service in just three years, creating more than 2.3 million repositories. A list of the most-forked projects on GitHub almost reads like a contemporary who’s who of successful open source projects.

Despite its size and importance, though, GitHub has never been hacked — until now. GitHub uses the Ruby on Rails application framework, and Rails has been weak to what’s known as a mass-assignment vulnerability for years. Basically, Homakov exploited this vulnerability to add his public key to the Rails project on GitHub, which then meant that GitHub identified him as an administrator of the project. From here, he could effectively do anything, including deleting the entire project from the web; instead, he posted a fairly comical commit. GitHub summarily suspended Homakov, fixed the hole, and, after “reviewing his activity,” he has been reinstated.

Putting aside the way GitHub handled the situation (quickly and with aplomb), the main issue is that GitHub was vulnerable to an incredibly simple and well-known Rails hack that has probably existed since the site’s inception. Ruby experts like Michael Hartl and Eric Chapweske have been writing (and warning) about the mass-assignment vulnerability since 2008, when GitHub was first launched. In short, it’s highly likely that Egor Homakov was not the first person to exploit GitHub in this way. We would’ve heard about it if a large project had been deleted out of the blue — but maybe hackers have been quietly modifying code bases for their own, nefarious ends.

Moving forward, GitHub has apologized for obfuscating the how white hat hackers should disclose security vulnerabilities and set up a new help page that clearly lists how to report issues. GitHub, alongside 37signal’s array of popular web apps (Basecamp and Campfire), is probably the biggest deployment of Ruby on Rails on the web. After last year’s long series of high-profile hacks on technology companies like Sony, RSA, LastPass, and Google, we probably shouldn’t be surprised that GitHub was vulnerable — but still, when it is a service that so many important projects rely on, it’s shocking that an age-old vulnerability wasn’t picked up in a security audit; if GitHub performs security audits, that is.

For discussion on the vulnerability used by Homakov, see his personal blog and Chris Acky’s blog

Last revision (mm/dd/yy): 12/21/2016

Introduction

Definition

Software frameworks sometime allow developers to automatically bind HTTP request parameters into program code variables or objects to make using that framework easier on developers. This can sometimes cause harm. Attackers can sometimes use this methodology to create new parameters that the developer never intended which in turn creates or overwrites new variable or objects in program code that was not intended. This is called a mass assignment vulnerability.

Alternative Names

Depending on the language/framework in question, this vulnerability can have several alternative names

  • Mass Assignment: Ruby on Rails, NodeJS
  • Autobinding: Spring MVC, ASP.NET MVC
  • Object injection: PHP

Example

Suppose there is a form for editing a user's account information:

<form> <input name=userid type=text> <input name=password type=text> <input name=email text=text> <input type=submit> </form>

Here is the object that the form is binding to:

public class User { private String userid; private String password; private String email; private boolean isAdmin; //Getters & Setters }

Here is the controller handling the request:

@RequestMapping(value = "/addUser", method = RequestMethod.POST) public String submit(User user) { userService.add(user); return "successPage"; }

Here is the typical request:

POST /addUser userid=bobbytables&password=hashedpass&email=bobby@tables.com

And here is the exploit:

POST /addUser userid=bobbytables&password=hashedpass&email=bobby@tables.com&isAdmin=true

Exploitability

This functionality becomes exploitable when:

  • Attacker can guess common sensitive fields
  • Attacker has access to source code and can review the models for sensitive fields
  • AND the object with sensitive fields has an empty constructor

Case Studies

GitHub

In 2012, GitHub was hacked using mass assignment. A user was able to upload his public key to any organization and thus make any subsequent changes in their repositories. GitHub's Blog Post

Solutions

  • Whitelist the bindable, non-sensitive fields
  • Blacklist the non-bindable, sensitive fields
  • Use Data Transfer Objects (DTOs)

General Solutions

Data Transfer Objects (DTOs)

An architectural approach is to create Data Transfer Objects and avoid binding input directly to domain objects. Only the fields that are meant to be editable by the user are included in the DTO.

public class UserRegistrationFormDTO { private String userid; private String password; private String email; //NOTE: isAdmin field is not present //Getters & Setters }

Language & Framework Specific Solutions

Spring MVC

Whitelisting

@Controller public class UserController { @InitBinder public void initBinder(WebDataBinder binder, WebRequest request) { binder.setAllowedFields(["userid","password","email"]); } ... }

Reference

Blacklisting

@Controller public class UserController { @InitBinder public void initBinder(WebDataBinder binder, WebRequest request) { binder.setDisallowedFields(["isAdmin"]); } ... }

Reference

NodeJS + Mongoose

Whitelisting

var UserSchema = new mongoose.Schema({ userid  : String, password  : String, email  : String, isAdmin  : Boolean, }); UserSchema.statics = { User.userCreateSafeFields: ['userid', 'password', 'email'] }; var User = mongoose.model('User', UserSchema); _ = require('underscore'); var user = new User(_.pick(req.body, User.userCreateSafeFields));

ReferenceReference

Blacklisting

var massAssign = require('mongoose-mass-assign'); var UserSchema = new mongoose.Schema({ userid  : String, password  : String, email  : String, isAdmin  : { type: Boolean, protect: true, default: false } }); UserSchema.plugin(massAssign); var User = mongoose.model('User', UserSchema); /** Static method, useful for creation **/ var user = User.massAssign(req.body); /** Instance method, useful for updating **/ var user = new User; user.massAssign(req.body); /** Static massUpdate method **/ var input = { userid: 'bhelx', isAdmin: 'true' }; User.update({ '_id': someId }, { $set: User.massUpdate(input) }, console.log);

Reference

Ruby On Rails

Reference

Django

Reference

ASP.NET

Reference

PHP Laravel + Eloquent

Whitelisting

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { private $userid; private $password; private $email; private $isAdmin; protected $fillable = array('userid','password','email'); }

Reference

Blacklisting

<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { private $userid; private $password; private $email; private $isAdmin; protected $guarded = array('isAdmin'); }

Reference

Grails

Reference

Play

Reference

Jackson (JSON Object Mapper)

ReferenceReference

GSON (JSON Object Mapper)

ReferenceReference

JSON-Lib (JSON Object Mapper)

Reference

Flexjson (JSON Object Mapper)

Reference

Authors and Primary Editors

References and future reading

Other Cheatsheets

One thought on “Github Mass Assignment Vulnerability Management

Leave a Reply

Your email address will not be published. Required fields are marked *