Monday, February 11, 2013

Rails Vulnerabilities: Learning The Lesson

previous: Rails is [Fr]agile. Vulnerabilities Will Keep Coming
JSON exploit: http://www.zweitag.de/en/blog/ruby-on-rails-vulnerable-to-mass-assignment-and-sql-injection

Today we got 3 new vulns, IMO only JSON-related is dangerous, but I want to look at the lesson we all should learn.

attr_protected must be removed at all because it leads to DoS easily.
I guess this method is extremely unpopular anyway - nobody cares.

Regexps
use /m flag to match with newlines with .
"aa(cc\nbb".to_s.gsub(/\(.+/, '')
 => "aa\nbb" 

YAML
Wasn't it absolutely obvious to keep YAML.load away from "input"? It was, then why rubygems (Gemfile.lock) and 'serialize' were waiting for "personal" exploitsI knew about potential vuln through SQL injection, but I was on rails 4 codebase.  Even direct assignment leads to RCE in older rails. This is bad and silly :(

Don't Put Magic Params Into Magic Methods
just a few examples(you probably read them if you're following @homakov)

Any parameter in rails app can be: Integer, Date, Time, StringIO, Boolean, BigDecimal, Float, Array or Hash. thanks to alternative inputs and rack query parser!

1) validates :field, length: 2..10
 it is not safe because param can be an array: field[]=123123123123123123123&field[]
2) redirect_to user_input
can lead to XSS if user_input[status]=200&user_input[protocol]=javascript:...
3) create(!) accepts arrays and can create thousands of records with one call! It can be used with JSON params and your service will be full of spam.
4) your mailer can be used for bad because :to accepts an array and it can be a long array with other people's addresses. 
5) mysql compares "string" with integers by casting strings to 0. Yes, "randomtoken"==0 for it. Thanks @joernchen for the find but it's WONTFIX. 0 can be easily passed via JSON and XML.

JSON
If you ask me what I trust in I reply God JSON. It looks like such a simple format, so reliable and obvious. Until today. Today I learned that "json_class" attribute makes json parser to "const_get" the value. This is non sense. JSON::GenericObject is double non sense. Sad panda.

backports
there are some vulns fixed in 4 but they were not ported on old versions. For example escape_html_entities_in_json - if you do JSON.dump(user_input) it can lead to XSS in < 4.
And CSRF for routes.rb match method.
default_headers to prevent clickjacking
And bunch of other stuff.

hardening
rails codebase contains too many features not used in everyday development. Multiparameters, alternative inputs, aliases(alias in named route collection leading to RCE) and so on. It needs hardening, to reduce such enormous surface for attacks.

P.S. don't blame Rails again. You can blame rails for mass assignment (i'm kidding, blame yourself for this), but for RCEs - blame JSON/YAML gems.

So far, Rails itself is pretty safe.

3 comments:

  1. > P.S. don't blame Rails again. You can blame rails for mass assignment (i'm kidding, blame yourself for this), but for RCEs - blame JSON/YAML gems. So far, Rails itself is pretty safe.

    Seriously? I always thought that "Don't let YAML.load close to any user input" was common Ruby knowledge. Just like "(Nearly) always use \A\z instead of ^$". I mean, even I, who never wrote a single line of Ruby code in my life, know this stuff.

    I know, the multiline option for regular expressions is Ruby's fault (a really, really, really bad choice) and YAML might have done a better job at educating people that it's a fully-fledged serialization format and not just some key-value store.

    But in the end it's Rails fault for using them the way it did.

    Really, this is not intended as bashing against Rails (every software has vulnerabilities), but I think blaming all these vulns on "the others" is disingenuous.

    ReplyDelete
    Replies
    1. cannot share your point.. yes, Yaml could do better job educating developers but "Don't let YAML.load close to any user input" wasn't too obvious for me. At least I could not imagine RCE through it (DoS - yes)


      After all rails ecosystem is a network of different gems. We cannot blame rails because it is the central and most known gem. Rails is a glue.
      i can blame rails though for its magic methods, and attack surface.

      Delete