sleep

(PHP 3, PHP 4, PHP 5)

sleep -- Delay execution

Description

int sleep ( int seconds )

The sleep() function delays program execution for the given number of seconds.

例子 1. 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

See also usleep() and set_time_limit()


add a note add a note User Contributed Notes
anonymouse
15-May-2006 05:27
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
arielCo
01-Mar-2006 12:38
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.
Josh
09-Feb-2006 07:27
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
warhog at warhog dot net
19-Dec-2005 05:24
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.
justin at jennnixon dot com
24-Nov-2005 03:52
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 05: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.
linus at flowingcreativity dot net
08-Jul-2005 11:07
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) ?>
vmadman at gmail.com
03-Jul-2005 05:43
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
Breeze at Hotmail dot com
05-Jun-2005 03:51
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 Gren, (german for "Yours sincerely" :)
Breeze

PS: I'm german, so don't be bothered by my english. :)
tommiboy
11-May-2005 07:43
Two additions to my previous note:

1. You can of course *always* run a DoS on any server at any time. If you have a few hundred hijacked machines, then you can incapacitate even huge sites like amazon or worldpay who have really large resources, as has been done before. Unluckily, there is not much you can do against braindead crimials. Even if you block them on the IP layer, they can still fill the wire with datagrams  :(
However, sleep() makes an attack a lot cheaper. If the target uses for example sleep(5); then the attacker can safely assume that one request will keep one process running for 5 seconds.
So, only a few dozen requests (w/ dropped connections), will safely run you into "MaxClients" and you will not be able to accept legitimate requests any more. So what, increase "MaxClients" then, I hear you say? The attacker can do this for hours, but you can't...
10MB of memory for a server process is not a unreasonable assumption. If your web server has 2GB of RAM then it will start thrashing after starting 200 processes. A 32 bit machine is out of virtual memory after 400. That can be achieved using a 14.4k modem...

2. The <FilesMatch> rule in my example is flawed as it opens access to config files. By mere coincidence (due to another rule), it has been working fine for a year and a day on my machine, so I never noticed until now.
It is still a bad mistake. Use your login form's filename rather than "^.*$".
tommiboy
05-May-2005 10:33
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... :)
BrianKStein at gmail dot com
08-Mar-2005 07:11
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.

?>
MPHH
06-Jul-2003 03:33
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.
cet [at] carlthompson [dot] net
25-Jun-2003 09:10
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.
Jonesy (at) jonz dot net
16-Apr-2003 03:52
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.<br>
Crackers ain't the only ones that can use multi-threading tactics.
josh at NO chatgris SPAM dot com
28-Jan-2003 08:33
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.
hartmut at six dot de
25-Aug-2000 09:38
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!