19 May 2012

Injects in Various Ruby Websites Through Regexp.

On HN

You are a web developer. Let's assume you are building a website using Ruby(and probably Rails or any other Ruby framework). This is why you need to validate some input params - to make sure that they don't contain any crap you don't want to be there. Come on, you are going to google it, right?:
  1. Hmmm I need a regexp for emails. Googling: "regexp for email". Oh, nice one, I will use it.
  2. Oh, I also seek a regexp for URLs. Easy: "regexp for url". So good, I love google and ruby!
  3. This field must contain 3 capital letters - it's IATA code for an airport. I can do it by myself, I know regular expressions, I read some books! /^[A-Z]{3}$/ looks great!
Now you have ready regexps and you put them into your model, into controller, anywhere - it doesn't matter:
validates :email, presence: true, format: EMAIL regexp from google
validates :url, format: URL regexp from google
validates :departure_airport, presence: true, format: /^[A-Z]{3}$/
You can even test it tens times in console or development ENV - it will work... unless you know "the secret" with ruby Regexp.

^ for start-of-string and $ for end-of-string ARE just new lines - \n!

This is a common pattern to exploit them:
any data
proper data - valid for regexp
any other data




Thus, all your regexps that use ^$ are CRAP and worth nothing! Throw them away, they don't make sure that input is safe and secure.

XSS for your URL:

javascript:alert(1);exploit_code();/*
http://hi.com
*/

Inject for IATA code(it uses SOAP so some XML inject has very powerful impact):
<some xml><for reservation system to steal money>
SXF
</ending tags></going to miami beach>
Ruby doesn't give a sh*t about it at all. "Meh, use \A \z, we are in multiline mode by default".

The vulnerability is known and described in just a few paragraphs at rails security guide. Example  is awful - why to add <script> to file name? Rails will escape it in html_safe easily. Much better to demonstrate XSS in URL, Shell Inject or XML inject because they all are pretty dangerous.

You bought a car, you are driving on a highway, faster and faster. Then you see the wall - you are trying to stop the car asap.
Hey dude, didn't you read 300pages-manual? Page 253: "Brake is located on the roof of the car". pwned.

Regexp are just like cars - they should work as same and similar as it's possible. Breaking standard behavior by purpose and telling people "It's not a bug, it's a feature" looks so disgusting to me. It's not a feature, it's a vulnerability.

Showcases time.

Github.com(with a picture :3, fixed)







scribd.com(the same, fixed)

http://www.workingwithrails.com/person/19433-egor-homakov

http://soundcloud.com/egor-homakov (songkick link)

tumblr.com - awesome hack(tricky parser there) and easy-to-use, just put smth like this:
javascript:%0A
=(Code_to_Reblog();code_to_open_the_link();)//
http://hi.com

That's it! Of course I can find much more - but for what? I am 90% sure that your ruby project uses $^ in URL regexp too. I am so much sure because I would do the same, and this is really OK. Old versions of devise and authlogic and a lot of other gems are built with vulnerable regexps.

This is how to check: You have <input> field. Just turn it into <textarea> using WebInspector - now you can use new lines w/o all the mess with \n and %0A.