4

I have this form:

<form method="post" action="secret.php">
    <label for="pw">Password: </label><input type="password" name="pw" id="pw" />
</form>

This is secret.php:

<?php 
if(isset($_POST["pw"])) {
    if($_POST["pw"] == "hello") {
        echo("<strong>Good pw.</strong><br />");
    } else {
        echo("<strong>Bad pw.</strong><br />");
        echo("<a href=\"form.php\">Back</a>");
        sleep(5);
    }
} else {
    header("Location: /tut/first/form.php");
}
?>

What happens is that if the password is wrong, it sleeps before displaying Bad pw. When I submit the form, it sleeps 5 seconds on the form page, and then changes page and displays Bad pw. Why?

  • `sleep()` just delays the execution of the current thread for the time you tell it. Output isn't sent to the browser until the current request is completed. You could use output buffering, I guess... – crush May 31 '13 at 18:56
  • Have a look at [`flush()`](http://php.net/manual/en/function.flush.php), though [it has issues in some browsers](http://stackoverflow.com/questions/6001628/php-flush-not-working-in-chrome). – Orbling May 31 '13 at 18:59
  • Why do you want a sleep? the code above could be a valid soulotion for a problem, maybe just not to solve your problem, so what was you supose to solve with the sleep? – Puggan Se May 31 '13 at 19:03

3 Answers3

4

What is happening is that you are causing the PHP script to sleep. The script must complete before it sends the result back to the client (the browser).* So you are causing the script to take 5 seconds longer before it responds to the client that it wasn't a good password.

Since you are not trying to avoid a brute force situation here I would suggest something like this:

<?php 
if(isset($_POST["pw"])) {
    if($_POST["pw"] == "hello") {
        echo("<strong>Good pw.</strong><br />");
    } else {
        echo("<strong>Bad pw.</strong><br />");
        echo("<script type=\"text/javascript\">");
            echo ("setTimeout(function() {");
                echo ("window.location = form.php;"); //might need a more complete URL here
            echo ("}, 5)"); //sleep for 5 seconds before redirecting
        echo("</script>");
        sleep(5);
    }
} else {
    header("Location: /tut/first/form.php");
}
?>

*The output is actually sent back as it's written in the PHP script but with buffering you don't see this making much of a difference except in headers and very large pages.

BlargleMonster
  • 1,602
  • 2
  • 18
  • 33
  • Oh I see. So what should I be doing instead? Do it with javascript? –  May 31 '13 at 18:59
  • 2
    Javascript is rather insecure because the client can change it, or they could make their own program to hit your php file without any limitations at all. I made a suggestion in my edit that should help. – BlargleMonster May 31 '13 at 19:02
  • @BlargleMonster so? the only thing he wants to do is redirect from the "bad password" page to the original form. javascript will work just fine for this (unless the user has it disabled, up to you if you care about that or not). if the user wants to screw with the js, that's their fault - they will just continue to see the "bad password" page. there's no security problem here. – user428517 May 31 '13 at 19:06
  • What I want to do is echo bad password, then sleep for 5 seconds, then redirect to the form page. JS would work, but I would like to do in PHP if possible and I am trying to understand your answer Blargle. –  May 31 '13 at 19:10
  • @Maxwell in that case javascript will be fine. You will probably want to echo the `Bad pw.
    ` and then echo out a little javascript `
    – BlargleMonster May 31 '13 at 19:35
  • @maxwell, i get that you want to use php to do this, but it doesn't make much sense to do this with php. php runs on the server. you should use javascript for client-side operations like redirecting to another page. – user428517 May 31 '13 at 19:54
  • @Maxwell Sorry for the large stream of edits. I posted some sample code that will probably help you out. Basically it gives them the same bad password response and starts a 5 second timeout to redirect the page through javascript. – BlargleMonster May 31 '13 at 20:05
0

You need to look into output buffering, although from what I see, the logic is flawed.

This may help

PHPSrike
  • 33
  • 1
  • 9
Rob W
  • 9,134
  • 1
  • 30
  • 50
0

If you want to echo something to the browser right away, try doing flush() when you want to flush the output buffer to the browser. Also, you may need to disable compression (like gzip) which can interfere with output buffering.

However with that said, you're going about this completely wrong. All that the user would have to do is open up another tab / refresh and the server will validate the login information again, so doing sleep() isn't going to have the effect you think it is.

I have actually designed something similar to this and this is what I did:

Create a database table called failed_logins and another called login_bans and both are based on IP address. Every time a user provides incorrect information, add an entry in the failed_logins table. What you want to do is tier it so that after the first login, the user is banned for 5 seconds, after the second, it goes up to 15 seconds and 3 or more within a certain period (like say 2 hours) the user is banned for 45 seconds. This is all done server-side so that there is nothing the user can do to circumvent the ban. So you will have to check their IP every time they access the page to see if their IP has been banned.

Then on the client-side display a countdown timer containing the number of seconds remaining in the ban and disable the submit button.

Mike
  • 23,542
  • 14
  • 76
  • 87
  • But I want the user to be automatically redirected to the form after 5 seconds if he has entered the wrong password. I also want to echo Bad pw while he is redirected. –  May 31 '13 at 19:20
  • It would be better to do that with JS only on the client-side, not PHP, but make sure you are also doing it in the back-end using something like what I have here. Using `sleep()` can actually be a DDoS vulnerability, especially for 5 seconds. Imagine thousands of people all connecting at the same time, and for every one it spawns a new process that can't even end for 5 seconds. – Mike May 31 '13 at 19:58