emphatic solutions : ephemeral musings in the ether...
Brian Doll, Software/Systems Architect, San Francisco Bay Area, California

The dangers of url_for in Rails applications

February 2010

In a great post about named routes in Rails, path vs. url, Viget Labs ponders which variant is best used.

Most often we use foo_path, which when used in Rails URL helpers will generate a relative path, where foo_url generates a full URL. In most cases the path makes most sense, but not always.

Prerequisites to coax the url_for dragons out of hiding

  1. A web server that is listening to any incoming request by IP (rather than by hostname)
  2. A Rails app that is generating some links with full URL named routes
  3. Cached pages that store content that includes those full URLs

Can you see where this is going yet?

# to take Viget's example
map.resources :doohickeys
link_to 'index of doohickeys', doohickeys_url
  # => <a href="http://www.example.com/doohickeys">index of doohickeys</a>

Where did www.example.com come from? Let’s take a look. In both Rails 2.3.5 and Rails 3 beta, if we have not explicitly passed in a :host option, we get @request.host_with_port. So, no matter what hostname you used to resolve the app, that hostname will be used to generate full URLs.

Exploiting url_for

One man’s casual bug is another man’s security exploit, right? Let’s modify our local hosts file:

 # /etc/hosts
 # map the target website's IP to your favorite web destination
 10.0.0.0  emphaticsolutions.com

Now, when we visit the target website with our own domain, those URLs look like this:

map.resources :doohickeys
link_to 'index of doohickeys', doohickeys_url  
  # => <a href="http://emphaticsolutions.com/doohickeys">index of doohickeys</a>

If the target application is caching content that includes these links, and you’re lucky enough to hit an uncached section of the site, you’ve just injected your own hostname into the target’s website content for other users to see and click on. Your directing clicks on their site, back to yours.

Many stars must align

Sure, there are a lot of variables that have to pan out for this issue to be exploitable. That doesn’t make the issue any less real. One solution to this would be to include a configuration option that is defined per environment, to identify the desired hostname for a given app. Think of it as the canonical hostname that should be used unless you explicitly set one when generating a URL. I think this solution works for most applications, and if you don’t use the configuration, you’ll get the existing behavior.

Another solution is to configure your web server to use a specific hostname for both http and https URLs. Here is that configuration for Apache:

So what do you think? Should Rails provide a configuration option to specify an app’s hostname, or is that outside the scope of what the app should be concerned with?


Thoughts from Twitter


About the author:

Brian Doll is a business-focused technologist who has been building things on the web for over 13 years. He has extensive experience in retail, media and financial service industries in both start-up and large enterprise environments.

He enjoys speaking on lean engineering, web application performance and systems architecture. Having been inspired by Ruby and reinvigorated by Rails, Brian has been an avid contributor in the Ruby/Rails community since early 2007.

Additionally, he is a husband, father, thought worker, tree-hugging, music-loving, punk, atheist, non-conformist, optimist, Quality seeker. Phew! Here you'll find a mix of thoughts on fitness (Crossfit, Paleo foods), philosophy and programming (Ruby, Rails and other goodies).



Generated by Jekyll
Copyright © 2007-2010 Brian Doll