Code snippets for symfony 1.x


Refine Tags

Snippets tagged "brute"

sfGuard Logging with Brute Force Login Prevention

For those of us who just need a bit more security out of this already awesome authentication plugin. This has been tested to work on symfony 1.2 using sfGuardPlugin version 3.1.3 stable.

The default behavior of this snippet is a log that tracks each login attempt, the IP, the username entered, and whether it was successful or not. The brute force protection's default settings will check to see if more than 5 attempts for the same username in the past 2 minutes were failed attempts. It also includes a cooldown period of 15 minutes from the last failed login attempt. All of these variables can be changed in the arguments for checkBruteForce().

The first thing we need to do is create a log for sfGuard. Your schema should now contain the following:


    _attributes:    { phpName: sfGuardLog }
    ip:             varchar(30)
    username:       varchar(20)
    valid_login:    boolean

Once the changes to your schema have been made, rebuild your models, forms, and filters. Next, we need to extend the peer class for this new sfGuardLog model to handle brute force protection.


    Auther: Christopher Lewis (
    Check for brute force login attempts
    Case I
     1. Get all logins for this username in the past N minutes
     2. If P or more of them are fails, this is likely a brute force attempt, return true
    Case II
     1. Get last P logins
     2. Are they all fails? AND Are they all within the same window of N minutes? AND Was the last attempt within the past Q minutes?
        If all are true, return true
     N = $attempt_window
     P = $allowed_fail_count
     Q = $cooldown_window
  public static function checkBruteForce($username, $attempt_window = 2, $cooldown_window = 15, $allowed_fail_count = 5)
    //Case I...
    $N_minutes_ago_timestamp = strtotime("$attempt_window minutes ago");
    $N_minutes_ago_sqltime = date('Y-m-d H:i:s', $N_minutes_ago_timestamp);
    $c = new Criteria();
    $c->add(sfGuardLogPeer::USERNAME, $username);
    $c->add(sfGuardLogPeer::CREATED_AT, $N_minutes_ago_sqltime, Criteria::GREATER_THAN);
    $entries = sfGuardLogPeer::doSelect($c);
    $failed_count = 0;
    foreach($entries as $log) { if($log->getValidLogin() == false) { $failed_count++; } }
    if($failed_count >= $allowed_fail_count) { return true; }
    //Case II...
    $all_fails = false; $all_in_window = false; $last_attempt_recent = false;
    //Are they all fails?
    $c = new Criteria();
    $c->add(sfGuardLogPeer::USERNAME, $username);
    $failed_count = 0; $timestamps = array();
    $entries = sfGuardLogPeer::doSelect($c);
    foreach($entries as $pos => $log)
      if($log->getValidLogin() == false) { $failed_count++; }
      array_push($timestamps, strtotime($log->getCreatedAt()));
    if($failed_count >= $allowed_fail_count) { $all_fails = true; }
    else { return false; }
    //Are they all within the same window of N minutes?
    $time_a = $timestamps[0];
    $time_b = $timestamps[(count($timestamps) - 1)];
    $window_in_secs = $time_b - $time_a;
    $window_in_mins = $window_in_secs / 60;
    if($window_in_mins <= $attempt_window) { $all_in_window = true; }
    else { return false; }
    //Was the last attempt less than Q minutes ago?
    $Q_minutes_ago_timestamp = strtotime("$allowed_fail_count minutes ago");
    $last_attempt_timestamp = strtotime($entries[0]->getCreatedAt());
    if($Q_minutes_ago_timestamp <= $last_attempt_timestamp) { $last_attempt_recent = true; }
    else { return false; }
    //If all are true, return true
    if($all_fails == true && $all_in_window == true && $last_attempt_recent == true) { return true; }
    return false;  

Last, we'll need to overload the executeSignin action in the sfGuardAuth module to include our new logging and security features:


public function executeSignin($request)
    $user = $this->getUser();
      return $this->redirect('@homepage');
    $class = sfConfig::get('app_sf_guard_plugin_signin_form', 'sfGuardFormSignin');
    $this->form = new $class();
      $values = $this->form->getValues();
      //Log attempts
      $log = new sfGuardLog();
      //Check for brute force attempt
      $is_brute_force = sfGuardLogPeer::checkBruteForce($request->getParameter('signin[username]'));
      if($this->form->isValid() && !($is_brute_force))
        $this->getUser()->signin($values['user'], array_key_exists('remember', $values) ? $values['remember'] : false);
        // always redirect to a URL set in app.yml
        // or to the referer
        // or to the homepage
        $signinUrl = sfConfig::get('app_sf_guard_plugin_success_signin_url', $user->getReferer('@homepage'));
        return $this->redirect($signinUrl);
by Christopher Lewis on 2009-06-03, tagged authentication  brute  login  plugins  security  sfguard