Thursday, January 31, 2013

Rails is [Fr]agile. Vulnerabilities Will Keep Coming.

This post is just a thought, with some minor vulnerabilities(all of them are reported). Everyone knows these "January events":
1) find_by_* can be tricked to use user input's :select as injection
2) XML can be tricked to use YAML
3) YAML can be tricked to initialize arbitrary objects
4) AGAIN! JSON can be tricked to use YAML(see point 3..)

Is it over? No, I guess.
This is just a short demo, how FAR this [Fr]agileness can lead to:
There is "redirect_to" method and it accepts:

    # * <tt>Hash</tt> - The URL will be generated by calling url_for with the +options+.

    # * <tt>Record</tt> - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record.
    # * <tt>String</tt> starting with <tt>protocol://</tt> (like <tt>http://</tt>) or a protocol relative reference (like <tt>//</tt>) - Is passed straight through as the target for redirection.
    # * <tt>String</tt> not containing a protocol - The current protocol and host is prepended to the string.
    # * <tt>Proc</tt> - A block that will be executed in the controller's context. Should return any option accepted by +redirect_to+.
    # * <tt>:back</tt> - Back to the page that issued the request. Useful for forms that are triggered from multiple places.

Agile, huh?
Let's assume there is open redirect(it's bad but it happens): 'redirect_to params[:next]'
Here is generated response for /path?next[status]=200&next[protocol]=javascript:alert(document.domain)

<html><body>You are being <a href="javascript:alert(document.domain)//HOST/">redirected</a>.</body></html>

Status 200 - no redirect happened. URL has XSS. Now you just need to make user to click it. You can use clickjacking, but he can also decide to click by himself. And you can also set custom :alert, :notice - flash messages.

Another one - famous arrays with nils, which was patched in JSON/XML parsers too and it broke some apps. If you pass [nil] to find_by_ methods you can also find records where this field IS NULL(It wasn't set, intentionally). This is a good vulnerability for all kinds of APIs, spree example:
(I'm sorry about this PR and I behaved irresponsibly. Following bugs were disclosed privately.)

Conclusion: keep an eye on your 'params'. Don't put it in 'agile' methods. It hurts.
Another conclusion: should we (Rails) start using less magic and more predictable behavior? I'm not sure.

P.S. Most likely this is the last technical post in the blog. I am starting a yet another security agency(core service is the Ruby/Rails audit), doing pen-test and code review for some cool startups and it's awesome when you can hack/help people and get paid for it. 
Want to make your Ruby application super secure? Drop a line: 
Following security posts will be published on another website, some of old posts will be probably rewritten, with nifty design etc. I got a lot of delicious stuff in my drafts ;)


  1. who in their right mind would do this: redirect_to params[:next]???

    1. like this