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.
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.
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.
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?
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).