Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : Miscellaneous Functions : sleep

sleep

Delay execution (PHP 4, PHP 5)
int sleep ( int seconds )

Example 1362. sleep() example

<?php

// current time
echo date('h:i:s') . "\n";

// sleep for 10 seconds
sleep(10);

// wake up !
echo date('h:i:s') . "\n";

?>

This example will output (after 10 seconds)

05:31:23
05:31:33

Related Examples ( Source code ) » sleep


Code Examples / Notes » sleep

tommiboy

Using sleep() to slow down intruders is a very bad idea since it keeps your httpd running.
If someone realizes that you are using sleep(), then he can very easily run a DoS on your server.
All he needs to do is run a few hundred threads sending login requests. Worse, he could even do this in a single thread as long as he sends requests more frequently than you return from sleep(). He can drop the connection, it doesnt matter while you sleep().
This attack is very cheap regarding bandwidth, cpu, and memory consumption. Contrarily, on your server, the number of httpd instances is limited, when your server reaches the hard limit, legitimate clients will be dropped. Also, a server instance consumes at least a few megabytes of memory, and fork()ing is not free, either.
A much better solution, in my opinion, is to auto-blacklist intruders after 5 or so wrong password challenges. Admitted... auto-blacklisting is somewhat awkward, too, for three reasons:
1. It requires a script to modify .htaccess files. Most people feel a pain in their groin when even thinking about this.
2. An attacker who realizes that you auto-blacklist could exploit the fact that http does not need a tcp connection and send single datagrams with spoofed source addresses, thus having you blacklist arbitrary ip addresses (big ouch).
3. Might blacklist innocent people (dynamic ip adress?? user is too stupid to enter pass??)
Problem 1 should not be a concern. If someone can insert arbitrary content through any of your scripts, then you have a major security hole elsewhere. Having .htaccess set to read-only won't help you in that case. This opinion may be objectionable, but for me, it is fine to have .htaccess modified by a script.
Problem 2 can be avoided by either using SSL (big performance ouch!) or by starting a session prior to the login form. Since PHP is nice enough to verify sessions against ip addresses, an attacker must know a valid session as well as the corresponding ip address to be able to spoof that address, hence he must at least receive one data packet, so the address cannot be spoofed quite so easily.
Problem 3 is eleminated by running a cron job that occasionally (like every 5 mins) deletes items from the blacklist.
There are several ways to do the blacklisting, this is one: prepend "SetEnvIf Remote_Addr $_SERVER['REMOTE_ADDR'] blacklist" to a .htaccess file that contains a
<FilesMatch "^.*$">
order deny,allow
deny from env=blacklist
</FilesMatch>
rule. Only denying the login form would of course be sufficient, too, but I see no reason not to deny all :)
This is rather primitive, but good enough for my needs and very efficient (better than mod_rewrite, and better than two dozen deny rules).
Another (crazy) idea would of course be to run httpd as root and call iptables from php, but you really need big bollocks to do that... :)


jonesy

To add to Josh's observation: A hack to accomplish  the "slow-the-bastards-down" logic would be to flock a `cracker-control-file` going into the sleep operation.
Crackers ain't the only ones that can use multi-threading tactics.


linus

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) ?>


arielco

The sleep(3) *nix manpage reads:
 DESCRIPTION
 sleep() makes the current process sleep until [seconds]
 seconds have elapsed or a signal arrives which is not
 ignored.
So, ANY incoming signal that has not been set with pcntl_signal() to SIG_IGN causes sleep() to return.
If you don't want this, maybe
<?php
 time_sleep_until(microtime(true) + $secs );
?>
will work, depending on CPU load.
 RETURN VALUE
 Zero if the requested time has elapsed, or the number of
 seconds left to sleep.
The return value is an integer, and (at least in 5.1.2) it is the round()ed remaining time.


justin

Sleep sometimes does not run for the EXACT amount of time specified.
<?php $st = array_sum (explode (' ', microtime ()));
sleep (1);
echo round ((array_sum (explode (' ',microtime ())) - $st), 7); ?>
On three trials, this returned
0.9998388
0.9999161
1.001672


25-jul-2005 10:07

Regarding the use of sleep to discourage crackers, there is an alternative that could be used.  Derived from the "HTTP Digest Access Authentication" concept at http://www.faqs.org/rfcs/rfc2617.html under chapter "3 Digest Access Authentication Scheme".
For every time the login page is requested, have the server generate and remember a nonce and attach it to the login form.  When the form comes back with that nonce, check if the nonce received matches the one in memory.  If yes, continue the login process, otherwise reject the login attempt.  Throw away the nonce after one use.
Brute-force cracking won't be an option in this case, because the hacker/cracker must download the login page for every attempt to try a password.  And this will also neatly sidestep a possible weakness via the use of "sleep" to DoS attacks.


warhog

on the note below.. that difference may also result out of the code used calculating your microtime-differences.. as your machine surely is a multi-tasking machine, this may have happened because of other processes on your machine.

mphh

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.

hartmut

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!


briankstein

In response to the posts below about security, you could set a MySQL or Text record using the IP address that was logging in and then the login script would ban anyone who didn't wait the full sleep time because their IP would be in a temporary ban list and their name would only be deleted from that by a command after the sleep command.
<?php
//This script gets called with login params
echo "One moment while we check your username and password. DO NOT press the back button on your browser.";
//Put the user's IP address in a text file or MySQL database
sleep(5); //5 seconds should be enough
//Delete the user's IP address used above
//Perform authentication method.
//Print some text using an if statement to notify the user whether they were right or wrong.
?>


josh

In regards to sleep being inconsistent, your benchmarks aren't accurate. You add overhead by bundling microtime() into your other function calls. I believe a more accurate benchmark could be obtained using this instead:
<?php
$t0 = microtime();
sleep(1);
$t1 = microtime();
// Make your comparisons here
?>
Granted I doubt that sleep() is accurate down to the nanosecond - the function call alone to retrieve the time will take time, and that amount of time may vary depending on the computer it is being run on, number of current processes and their priorities, etc. However, the above code will give you a more accurate representation.
-- Josh


breeze

I would consider adding
a random sleep (2 to 5 sec),
before checking the login-information,
and an IP-based ban-list,
making multithreaded attacks useless,
to be a good protection.
"[...] Fill[ing] the wire with datagrams [...]" may slow down, but won't block your server.
If a "very bad hacker" (tm) has the possibility to use hundreds of machines to attack your server he will surely bring down your system insignificantly if you're using a sleep() or not.
mit freundlichen Grüßen, (german for "Yours sincerely" :)
Breeze
PS: I'm german, so don't be bothered by my english. :)


vmadman

I think you guys are over thinking this.  It's always nice to code expecting the worse, but odds are, you will never have someone targetting you for exploits in your custom code.
They would rather find exploits in a nuke site so that they can do the most damage.
With that aside, an effective way to prevent brute force attacks would be to only allow a certain number of authentication attempts at once, regardless of the IP.
15 would be a safe number, and sleep(10).  Brute force attacks can only be successful under two conditions, 1) be able to process insanely fast, or 2) get really lucky and find an easy password.
When an authentication request starts, write a row to a mySQL table and delete it when you're done.  Also mysql_num_rows when you start the request.
Deny immediately if num_rows returns greater than 15, sleep 10 seconds if num_rows exceeds 10, and sleep 5 seconds no matter what.
This progressive security approach would not only be effective, but would baffle the cracker. (he cannot see your code and would not know what is going on)
But do not let anyone tell you any different.  If he decides to DoS you (ane he has the resources to pull it off).. there is nothing you can do to stop it outside of notifying your ISP.
-Luke


josh

Contrary to previous posts, sleep provides not security whatsoever against crackers.  They can quite easily create a multithreaded program that will try 1000 passwords at a time effectively disabling your sleep pause, and sessions don't help as each a request can make itself look like a new session.  The only way to make this effective at all is to store the last time a user attempted to login in a database and onyl allow x tries per time period.

anonymouse

As I read everithing I think that it is easyest to limit new authentication requests to some number for some time. And delay new authentication attemts that are over the limit.
If you don't want user disruption, make it auth req per second per IP


cet

About using sleep() after an authentication failure:
While it is true that crackers can launch multiple concurrent attempts, the number of concurrent attempts is limited to your server's maximum number of concurrent requests.  As this number is usually miniscule in comparison to the numbers of attempts a cracker would probably need to brute force a password, sleep() _does_ in fact provide effective anti-cracking benefit.
Of course, a smart cracker could write his code to end the connection long before the sleep() is done, but that makes it a guessing game; how quickly can the connection be ended without accidently losing the successful connections the cracker wants?  This is not an easy question to answer for the cracker because all of those concurrent connection attempts can significantly slow down all of the responses, even successful ones.  Against this "smart" cracker there is going to be a limit; sleep(30) is probably going to be no more effective than sleep(5).  In the end, using sleep() makes the code neccessary to brute force a password much more complicated and that in itself will eliminate some would-be crackers.  For the others, it does slow them down somewhat.
So the short answer is that using sleep() after an authentication failure is _always_ better than not using sleep().
Best of all is to use sleep() after successful authentication too-- this would mean that the cracker _must_ wait the full sleep() period in every case and makes brute forcing a password require a very, very long time (years?).  This probably wouldn't even bother users that much as it would only happen once per login.


matt

/**
* Like PHP's sleep(), but this accepts decimal values
*
* @param float $seconds
*/
function sleep2($seconds) {
  usleep(floor($seconds*1000000));
}


Change Language


Follow Navioo On Twitter
connection_aborted
connection_status
connection_timeout
constant
define
defined
die
eval
exit
get_browser
__halt_compiler
highlight_file
highlight_string
ignore_user_abort
pack
php_check_syntax
php_strip_whitespace
show_source
sleep
sys_getloadavg
time_nanosleep
time_sleep_until
uniqid
unpack
usleep
eXTReMe Tracker