You should put sleep into both the pass and fail branches, since an attacker can check whether the response is slow and use that as an indicator - cutting down the delay time. But a delay in both branches eliminates this possibility.
sleep
(PHP 4, PHP 5)
sleep — Retrasar la ejecución
Descripción
$seconds
)
Retrasa la ejecución del programa durante el número de segundos dados por
seconds.
Parámetros
-
seconds -
El tiempo de parada en segundos.
Valores devueltos
Devuelve cero en caso de éxito, o FALSE en caso de error.
Si la llamada se interrumpió por una señal, sleep() devuelve
un valor distinto de cero. En Windows, este valor será siempre
192 (el valor de la constante
WAIT_IO_COMPLETION dentro de la API de Windows).
En otras plataformas, el valor devuelto será el número de segundos que quedan para
dormir.
Errores/Excepciones
Si el número de segundos especificado por seconds es negativo,
esta función generará un error de nivel E_WARNING.
Historial de cambios
| Versión | Descripción |
|---|---|
| 5.3.4 |
Antes de PHP 5.3.4, en Windows, sleep() siempre
devuelve NULL cuando el sueño ha sucedido, si tener en cuenta si el
sueño fue interrumpido o no.
|
Ejemplos
Ejemplo #1 Ejemplo de sleep()
<?php
// hora actual
echo date('h:i:s') . "\n";
// dormir durante 10 segundos
sleep(10);
// ¡despierta!
echo date('h:i:s') . "\n";
?>
Este ejemplo imprimirá (después de 10 segundos)
05:31:23 05:31:33
Ver también
- usleep() - Retrasar la ejecución en microsegundos
- time_nanosleep() - Retrasar por un número de segundos y nanosegundos
- time_sleep_until() - Hacer que el script duerma hasta el momento especificado
- set_time_limit() - Limita el tiempo máximo de ejecución
A really simple, but effective way of majorly slowing down bruit force attacks on wrong password attempts.
In my example below, if the end-user gets the password correct, they get to log in at full speed, as expected. For every incorrect password attempt, the users response is delayed by 2 seconds each time; mitigating the chances of a full bruit force attack by a limit of 30 lookups a minute.
I hope this very simple approach will help make your web applications that little bit more secure.
Ashley
<?php
public function handle_login() {
if($uid = user::check_password($_REQUEST['email'], $_REQUEST['password'])) {
return self::authenticate_user($uid);
}
else {
// delay failed output by 2 seconds
// to prevent bruit force attacks
sleep(2);
return self::login_failed();
}
}
?>
This will allow you to use negative values or valuer below 1 second.
<?php slaap(0.5); ?>
<?php
function slaap($seconds)
{
$seconds = abs($seconds);
if ($seconds < 1):
usleep($seconds*1000000);
else:
sleep($seconds);
endif;
}
?>
This is a critical thing to use time delay function as sleep() Because a beginner can find that this is not working and he/she will see that all output appearing at a time.
A good way to implement this is by using the function - ob_implicit_flush() then you don't need to use flush() function explicitly.
A sample code :
<?php
ob_implicit_flush(true);
for($i=0;$i<5;$i++)
{
$dis=<<<DIS
<div style="width:200px; background-color:lime;border:1px; text-align:center;text-decoration:blink;">
$i
</div>
DIS;
echo $dis;
sleep(5);
//flush();
}
This may seem obvious, but I thought I would save someone from something that just confused me: you cannot use sleep() to sleep for fractions of a second. This:
<?php sleep(0.25) ?>
will not work as expected. The 0.25 is cast to an integer, so this is equivalent to sleep(0). To sleep for a quarter of a second, use:
<?php usleep(250000) ?>
Simple function to report the microtime since last called or the microtime since first called.
<?php
function stopWatch($total = false,$reset = true){
global $first_called;
global $last_called;
$now_time = microtime(true);
if ($last_called === null) {
$last_called = $now_time;
$first_called = $now_time;
}
if ($total) {
$time_diff = $now_time - $first_called;
} else {
$time_diff = $now_time - $last_called;
}
if ($reset)
$last_called = $now_time;
return $time_diff;
}
?>
$reset - if true, resets the last_called value to now
$total - if true, returns the time since first called otherwise returns the time since last called
Note: The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), the sleep() function, database queries, etc. is not included when determining the maximum time that the script has been running.
it is a bad idea to use sleep() for delayed output effects as
1) you have to flush() output before you sleep
2) depending on your setup flush() will not work all the way to the browser as the web server might apply buffering of its own or the browser might not render output it thinks not to be complete
netscape for example will only display complete lines and will not show table parts until the </table> tag arrived
so use sleep if you have to wait for events and don't want to burn to much cycles, but don't use it for silly delayed output effects!
Remember that sleep() means "Let PHP time to do some other stuff".
That means that sleep() can be interrupted by signals. That is important if you work with pcntl_signal() and friends.
Notice that sleep() delays execution for the current session, not just the script. Consider the following sample, where two computers invoke the same script from a browser, which doesn't do anything but sleep.
PC 1 [started 14:00:00]: script.php?sleep=10 // Will stop after 10 secs
PC 1 [started 14:00:03]: script.php?sleep=0 // Will stop after 7 secs
PC 2 [started 14:00:05]: script.php?sleep=0 // Will stop immediately
http://php.net/session_write_close may be used to address this problem.
I hope this code will help somebody to solve the problem of not being able to flush or output the buffer to the browser (I use IE7).
It may work for you with just [ echo str_repeat(".", 4096); ] and without even using ob_... and flush.
<?php
ob_start();
ob_implicit_flush(true);
//[ OR ] echo "..."; ob_flush(); flush();
set_time_limit(0);
function sleep_echo($secs) {
$secs = (int) $secs;
$buffer = str_repeat(".", 4096);
//echo $buffer."\r\n<br />\r\n";
for ($i=0; $i<$secs; $i++) {
echo date("H:i:s", time())." (".($i+1).")"."\r\n<br />\r\n".$buffer."\r\n<br />\r\n";
ob_flush();
flush();
sleep(1);
//usleep(1000000);
}
}
sleep_echo(30);
ob_end_flush();
?>
Since sleep() can be interrupted by signals i've made a function which can also be interrupted, but will continue sleeping after the signal arrived (and possibly was handled by callback). It's very useful when you write daemons and need sleep() function to work as long as you 'ordered', but have an ability to accept signals during sleeping.
<?php
function my_sleep($seconds)
{
$start = microtime(true);
for ($i = 1; $i <= $seconds; $i ++) {
@time_sleep_until($start + $i);
}
}
?>
Very useful to prevent password brute forcing! Simply add few seconds timeout to login script and the probability to guess the password decreases a lot!
Here is a simplified way to flush output to browser before completing sleep cycle. Note the buffer must be "filled" with 4096 characters (bytes?) for ob_flush() to work before sleep() occurs.
<?php
ob_implicit_flush(true);
$buffer = str_repeat(" ", 4096);
echo "see this immediately.<br>";
echo $buffer;
ob_flush();
sleep(5);
echo "some time has passed";
?>
