Prevent PHP script from being flooded
You can use memcache to do this ..
Simple Demo Script
$memcache = new Memcache ();
$memcache->connect ( 'localhost', 11211 );
$runtime = $memcache->get ( 'floodControl' );
if ((time () - $runtime) < 2) {
die ( "Die! Die! Die!" );
}
else {
echo "Welcome";
$memcache->set ( "floodControl", time () );
}
This is just a sample code .. there are also other thing to consider such as
A. Better IP
address detection (Proxy , Tor )
B. Current Action
C. Maximum execution per min etc ...
D. Ban User after max flood etc
EDIT 1 - Improved Version
Usage
$flood = new FloodDetection();
$flood->check();
echo "Welcome" ;
Class
class FloodDetection {
const HOST = "localhost";
const PORT = 11211;
private $memcache;
private $ipAddress;
private $timeLimitUser = array (
"DEFAULT" => 2,
"CHAT" => 3,
"LOGIN" => 4
);
private $timeLimitProcess = array (
"DEFAULT" => 0.1,
"CHAT" => 1.5,
"LOGIN" => 0.1
);
function __construct() {
$this->memcache = new Memcache ();
$this->memcache->connect ( self::HOST, self::PORT );
}
function addUserlimit($key, $time) {
$this->timeLimitUser [$key] = $time;
}
function addProcesslimit($key, $time) {
$this->timeLimitProcess [$key] = $time;
}
public function quickIP() {
return (empty ( $_SERVER ['HTTP_CLIENT_IP'] ) ? (empty ( $_SERVER ['HTTP_X_FORWARDED_FOR'] ) ? $_SERVER ['REMOTE_ADDR'] : $_SERVER ['HTTP_X_FORWARDED_FOR']) : $_SERVER ['HTTP_CLIENT_IP']);
}
public function check($action = "DEFAULT") {
$ip = $this->quickIP ();
$ipKey = "flood" . $action . sha1 ( $ip );
$runtime = $this->memcache->get ( 'floodControl' );
$iptime = $this->memcache->get ( $ipKey );
$limitUser = isset ( $this->timeLimitUser [$action] ) ? $this->timeLimitUser [$action] : $this->timeLimitUser ['DEFAULT'];
$limitProcess = isset ( $this->timeLimitProcess [$action] ) ? $this->timeLimitProcess [$action] : $this->timeLimitProcess ['DEFAULT'];
if ((microtime ( true ) - $iptime) < $limitUser) {
print ("Die! Die! Die! $ip") ;
exit ();
}
// Limit All request
if ((microtime ( true ) - $runtime) < $limitProcess) {
print ("All of you Die! Die! Die! $ip") ;
exit ();
}
$this->memcache->set ( "floodControl", microtime ( true ) );
$this->memcache->set ( $ipKey, microtime ( true ) );
}
}
How to stop people from flooding PHP API with requests?
You could serve a token generated and remembered on the server side which is rendered with your forms and validated when the form is sent back to your server. That prevents the user from just generating new post requests without actually requesting the according form from your server since they need the according token generated on your server to get it through.
Then there is the mentioned captcha which would be way too much for a login form from my point but when it comes to things like registering a new user the captcha in combination with the token sounds very good to me.
UPDATE
I Just found this article which is about floot protection of script execution in general. I think their approach is good as is the ip tracking provided you have the ability to use memcache or something similar to speed the checks up.
Quick and easy flood protection?
Use a token. You generate the token and add it to the page originating the request. In like.php
you verify that the request contains a valid token, which means it comes from your page instead of an external one POSTing directly.
PHP: why does my flood prevention script lag?
When you open a session using session_start()
, PHP locks the session file so any subsequent requests for the same session while another request has it open will be blocked until the session closes (you were exactly right with the "stacking" you suspected was happening).
You can call session_write_close()
to close the session and release the lock but this probably won't help in this situation.
What's happening is each time the key is pressed, a request gets issued and each one is backed up while the previous one finishes, once the session is released one of the other requests opens the session and sleeps, and this keeps happening until they've all finished.
Instead, I'd create a global variable in Javascript that indicates whether or not a request is in progress. If one is, then don't send another request.
Something like this:
<script>
var requesting = false;
$('#input').on('keyup', function() {
if (requesting) return ;
requesting = true;
$.ajax({
url: "/url"
}).done(function() {
requesting = false;
});
}
</script>
ZipArchive class PHP security issue
Four your other questions:
floading
That's the complex part. Let me google you some ideas:
- Prevent PHP script from being flooded
- Quick and easy flood protection? - use a nonce, time+tie it onto a session
- Use a captcha, if it doesn't impair usability too much.
uploading some kind of twisted exploit that would eventually alter my server
security
Use a commandline virus scanner (f-prot
or clamav
) to scan uploaded files. You might use a naive regex scanner in PHP itself (probe for HTMLish content in image files, e.g.), but that's not a factual security feature; don't reinvent the wheel.
buffer overflow
PHP in general is not susceptible to buffer overflows.
Okay, joking. But you can't do anything in userland about it. But pushing strings around isn't much of a problem. That's pretty reliable and unexploitable in scripting languages, as long as you know how to escape what in which context.
filenames that have arbitrary code injections
At the very leat you should most always use basename()
to avoid path traversal exploits. If you want to keep user-specified filenames, a regex whitelist is in order. =preg_replace('/[^\w\s.]/', '', $fn)
as crude example.
Related Topics
How to Access a Variable Across Two Files
Inserting Utf-8 Encoded String into Utf-8 Encoded MySQL Table Fails with "Incorrect String Value"
Execute Python Script from PHP
A PHP/Pthreads Thread Class Can't Use Array
How to Trust PHP _Destruct() Method to Be Called
Preg_Match() VS Strpos() for Match Finding
Adding Multiple Tabs to Woocommerce Single Product Pages
Turn Plain Text Urls into Active Links Using PHP
PHP Pdo Insert Batch Multiple Rows with Placeholders
Running Imagemagick on Xampp 1.8.3 with Windows 7
Python Format Datetime with "St", "Nd", "Rd", "Th" (English Ordinal Suffix) Like PHP's "S"
Error 500: Premature End of Script Headers
Measure String Size in Bytes in PHP
PHP Adding Custom Namespace Using Autoloader from Composer