I knew that PHP limits the amount of memory that one script can allocate, so life is good, right? Right? Wrong!
Reading the documentation it states: Changeable – PHP_INI_ALL, meaning that you can change it using ini_set from the script itself. Even worse, it goes on to say: “Note that to have no memory limit, set this directive to -1”. So I whipped together a small testcode:
<?php ini_set('memory_limit', -1); $a = array(); for($i = 0; $i < 10000000; ++$i) $a[] = 'foobard!'; print memory_get_usage();
And managed to allocate a whopping 979MB with the php.ini setting being 16MB! As far as I can tell, there is no way to enforce the memory limit set in php.ini! Suhosin doesn't seem to do it and neither does safe-mode.
What does this mean? Well, if the user is allowed to run PHP scripts in any shape or form (this includes scripts run trough RFI) they can DoS your server back to the stone age! This also means that on a shared host any client can take down the server!
How can you defend against it? As far as I can tell, there is no easy solution... Depending on your OS and HTTP server, there might be configurations provided by those to limit the damage. A workaround would be do disable ini_set (using the "disable_functions" directive), but this might break some applications.
PS. Of course the documentation says: "This helps prevent poorly written scripts for eating up all available memory on a server." - ie "this isn't a security feature" - but still, shouldn't there be some way to limit this?
Update: correction - suhosin can limit the maximum amount of allocated memory but it this feature is switched off by default. Sorry for doubting suhosin - this is something every PHP install should include (in fact: it is something the PHP core should include, but apparently their ego doesn't allow for this).