0

I have this simple php code fired by Ajax that checks if an entered password is correct. Now for this function I would also want to have an ability to block login for 10 seconds after 5 failed attempts in entering.

Here is the code itself:

//Beforehand I started the session, and connected the $link to the mysql database
if(!isset($_SESSION['lim'])){
        $_SESSION['lim'] = 5;
    }

    $p = $_POST['text']; //I WILL TAKE CARE OF VALIDATION LATER
     //All of the passwords will be crypted, and the variable will be   
     //validated. Just after I'm done with this system. 

        if($_SESSION['lim']>0){
            $result = mysqli_query($link, "SELECT id FROM passwd where pass = '".$p."' ;");
            if( mysqli_num_rows($result) > 0){
                echo 1;
                $_SESSION["passed"] = "true";
            }else{
                echo 0;
                --$_SESSION['lim'];
            }
        }else{
            echo 2;
            if(!isset($_SESSION['blockTime'])){$_SESSION['blockTime'] = time();}
        }

         if(($_SESSION['lim'] == 0) && (time() - $_SESSION['blockTime'] > 10)){
             $_SESSION['lim'] = 5;
         }

The problem is the code doesn't do the blocking part after 5 tries. Now the issue itself is most probably located in this bit:

 if(($_SESSION['lim'] == 0) && (time() - $_SESSION['blockTime'] > 10)){
     $_SESSION['lim'] = 5;
 }

Because without this portion, the blocking works fine (apart from not enabling the login after 10 seconds). It seems the if statement is executed everytime instead of only when the lim is empty and 10 seconds have passed.

What could possibly be the issue here and how could I make the if work properly

aln447
  • 981
  • 2
  • 15
  • 44
  • 2
    [Your script is at risk for SQL Injection Attacks.](http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) Learn about [prepared](http://en.wikipedia.org/wiki/Prepared_statement) statements for [MySQLi](http://php.net/manual/en/mysqli.quickstart.prepared-statements.php). – Jay Blanchard Mar 24 '16 at 19:45
  • 1
    Please use PHP's [built-in functions](http://jayblanchard.net/proper_password_hashing_with_PHP.html) to handle password security. If you're using a PHP version less than 5.5 you can use the `password_hash()` [compatibility pack](https://github.com/ircmaxell/password_compat). – Jay Blanchard Mar 24 '16 at 19:45
  • 2
    Also you have the right idea in preventing brute force type attacks, but using the session is unreliable for this as a user can easily delete or not use cookies to begin with (which negates anything you're doing in session), and still brute force you. I can say in personal experience I use memcache, but a database is also good in this case. – skrilled Mar 24 '16 at 19:46
  • Check the edit in the code – aln447 Mar 24 '16 at 19:54
  • It makes no sense to use sessions for this, because a brute forcer would simply *not* send a session cookie. It completely fails to protect against the attack it's supposed to prevent. This code is actually better if it doesn't exist at all. – Evert Mar 24 '16 at 21:12
  • So what do you say is the better option? I'm only starting with php security – aln447 Mar 25 '16 at 11:37

2 Answers2

1

when you re-init, ensure to reset your blockTime var as well :

 if(($_SESSION['lim'] == 0) && (time() - $_SESSION['blockTime'] > 10)){
     $_SESSION['lim'] = 5;
     unset($_SESSION['blockTime']);
 }
Cédric Françoys
  • 870
  • 1
  • 11
  • 22
1

you have a problem in your code. The last --$_SESSION['lim']; makes it to zero but it doen's set $_SESSION['blockTime'] to time() so... when it's compared in:

if(($_SESSION['lim'] == 0) && (time() - $_SESSION['blockTime'] > 10)){ $_SESSION['lim'] = 5; }

it's ever true so the counter it's restored.

To avoid it just add ´$_SESSION['blockTime'] = time();´ every time you subtract a try.

if(!isset($_SESSION['lim'])){
    $_SESSION['lim'] = 5;
}

$p = $_POST['text'];

    if($_SESSION['lim']>0){
        $result = mysqli_query($link, "SELECT id FROM passwd where pass = '".$p."' ;");
        if( mysqli_num_rows($result) > 0){
            echo 1;
            $_SESSION["passed"] = "true";
        }else{
            echo 0;
            --$_SESSION['lim'];
            $_SESSION['blockTime'] = time();
        }
    }else{
        $_SESSION['blockTime'] = time();
    }

     if(($_SESSION['lim'] == 0) && (time() - $_SESSION['blockTime'] > 10)){
         $_SESSION['lim'] = 5;
     }

Tested and working.

All in all please review comments made about injections and brute force are important.

Hope it helps!

ZeroWorks
  • 1,618
  • 1
  • 18
  • 22