• Home   /  
  • Archive by category "1"

Rails Mass Assignment Error Analysis

This release has breaking changes!

This is the 101st official release of Brakeman! It has been seven years and one month since the first release of Brakeman. To put that into historical context, Rails 3.0 was released a few days later!

How about some more numbers?

Thank you so much to everyone who has used, contributed to, or promoted Brakeman over the past seven years!

As a token of our appreciation, we have a limited edition 2017 Brakeman sticker:

Just email [email protected] with your name and address (anywhere in the world) and we’ll send you one. While supplies last!

If you have benefited from Brakeman, please consider supporting continued development via Brakeman Pro.

Changes since 3.7.2:

  • is now the default (#852)
  • is now the default (#1083)
  • “Plain” report output is now the default
  • Add simple pager for reports output to terminal
  • Remove low confidence mass assignment warnings
  • Reduce warnings about XSS in
  • Treat like (#1090)
  • Treat / like early returns (#754)
  • Rename “Cross Site Scripting” to “Cross-Site Scripting” (Paul Tetreau)
  • Remove reliance on constant in checks
  • Fix and in config files

Changes since 4.0.0:

  • Do not use pager when environment variable is set

New Default Exit Codes

and are now default behavior.

If any warnings are found or errors are raised during the scan, Brakeman’s exit code will be non-zero. This may break things! In particular, CI jobs or scripts that assume Brakeman will exit normally.

You may use and to revert back to previous behavior and always exit with error code 0.

(changes and changes)

New Default Report Format

The “plain” report format is now the default.

To revert back to the table format, use or .

(changes)

Paged Output

By default, output to the terminal will be paged with or Highline’s simple pager.

To disable, use .

In 4.0.1 Brakeman will automatically disable the pager when the environment variable is set to . This should be compatible with Travis CI, Circle CI, Codeship, and Bitbucket Pipelines.

(changes)

Fewer Mass Assignment Warnings

Low confidence mass assignment warnings have been removed in this release. Brakeman should now only warn when user input is used directly in the instantiation or update of a model.

(changes)

Fewer Warnings

Warnings about XSS in have confused quite a few people over the years. The danger is that links may have or values with XSS payloads.

Brakeman should now only warn when directly using user input or when using what looks like a URL from the database.

(changes)

More Cookies

will now be treated like cookies in general.

(changes)

More Early Returns

Calls to or will be treated like early returns when considering simple guard expressions.

(changes)

Cross-Site Scripting

Messages about “Cross Site Scripting” will now include a hyphen. This does not affect warning fingerprints.

(changes)

CONFIDENCE

Brakeman checks previously used the hash when creating warnings, e.g. . Now it’s possible to use instead.

For those with custom checks, the hash is still available and nothing should break.

(changes)

Checksums

The SHA256 sums for these releases are:

Reporting Issues

Thank you to everyone who reported bugs and contributed to this release.

Please report any issues with this release! Take a look at this guide to reporting Brakeman problems.

Follow @brakeman on Twitter and hang out on Gitter for questions and discussion.

If you find Brakeman valuable and want to support its development, check out Brakeman Pro.

How I Avoid The Rails Mass-Assignment Security Mistake

Note to readers from the future: this is a non-issue now that by default, rails complains abouts calling model#update_attributes without first setting up your attr_accessors

Wat?

By default, rails allows you to do this in your controller:

Where are your http request parameters updates a record in your database.

If it's not obvious why this is more than a little wreckless, let's give you a more concrete example.

# models/order.rb class Order # has a user_id field, # to determine the customer that this order belongs to belongs_to :user end # controllers/orders_controller.rb class OrdersController def update order = Order.find(params[:id]) if current_user == order.user order.update_attributes(params) else raise 'Stop trying to modify other users orders!' end end end

At first glance that code looks secure because you're authorizing your user (In practice you would use a gem like cancan that makes authorization a lot cleaner). It does make sure you can only modify your own orders.

But it doesn't whitelist exactly which fields you can modify. Imagine you sent these fields to that endpoint:

You've assigned your order to another user!

Look familiar? It should. A certain rather popular company with exactly one metric buttload of developers as users fell prey to this exact bug. I'm a big fanboy of theirs so I won't repeat exactly who it was, but they're huge.

Messeurs Picard and Riker sum up the feeling when you discover a bug like this in your code:

This is not a bug in rails. It's just a bit of functionality that makes it quite easy to stab yourself in the face.

Rails also gives you an easy way to white list attributes that can be mass assigned in the class method:

# models/order.rb class Order belongs_to :user attr_accessible :created_at, :address_id # and so on end

The result of this is that if you try to mass assign anything that isn't declared with , an exception is thrown, your app assplodes and that is the right thing.

The whitelist only comes into effect when you call on at least one attribute.

This means that in practice we neglect to whitelist anything and tend to leave this sort of security vulnerability lying around in our Rails codebases.

Guilty until proven innocent

On any new project then, I add this initializer:

# app/initializers/disable_mass_assignment.rb ActiveRecord::Base.attr_accessible(nil)

This automatically switches on whitelisting for all your model objects, making sure I whitelist all of my models before I mass assign them.

(Note, according to the relevant rails guide you can achieve the same effect with the following config option in ):

Use Only What You Need

Even with that in place and, it feels a little, well, wrong to just stick query parameters unchecked into . I'm with DHH on filtering your query parameters like so:

It's definitely a controller concern, though I wouldn't hesitate to move the fine details of the filtering logic somewhere else if it got to be more then four or five lines of code.

One thought on “Rails Mass Assignment Error Analysis

Leave a comment

L'indirizzo email non verrĂ  pubblicato. I campi obbligatori sono contrassegnati *