I am quite surprised about it but not many people know Suhosin extension, particularly shared webhosts and even administrators of dedicated web servers. Suhosin is a well-known PHP extension made by Stefan Esser, PHP security researcher.
With any PHP software, you cannot protect yourself from unexperienced programmers, creating errors in applications that lead to most obvious security issues (unsecure include() on user input, unprotected mail forms, etc.).
We have been running Suhosin on all our servers with a great success and so far we didn't find any problems with Drupal and any other PHP software.
How does Suhosin work and what does it protects against? You can either install it as a PHP module or as a PHP patch and recompile yourself. The huge advantage of a standard module is that you don't have to recompile PHP itself and you might not loose any possible vendor support. With the patch, you get a bit more protection but you need to recompile PHP everytime there is a new PHP version (And without proper server administration, I bet you will forget and make things even worse).
Therefore I usually recommend installing Suhosin module as it's also in standard Debian/Ubuntu:
sudo apt-get install php5-suhosin
What does Suhosin protect against?
- The only stable and real PHP remote file include protection available - including php://input, etc. (very important)
- Protects against HTTP Response Splitting Vulnerabilities
- Protects against scripts manipulating the memory_limit
- Adds protection against newline attacks to mail() (very important)
- Filters ASCIIZ characters from user input
- Ignores GET, POST, COOKIE variables with the following names: GLOBALS, _COOKIE, _ENV, _FILES, _GET, _POST, _REQUEST, _SERVER, _SESSION, HTTP_COOKIE_VARS, HTTP_ENV_VARS, HTTP_GET_VARS, HTTP_POST_VARS, HTTP_POST_FILES, HTTP_RAW_POST_DATA, HTTP_SERVER_VARS, HTTP_SESSION_VARS
- Supports verification of uploaded files through an external script (want automatic antivirus checking of EVERY uploaded file? Done!)
- Allows disabling the preg_replace() /e modifier
- Allows disabling eval() and blacklist/whitelist of eval functions!
- And more and lot more and a lot much more.
Did I tell you that I consider shared webhosts running PHP without Suhosin as irresponsible?
What about configuring Suhosin? The configuration file is either in /etc/php5/conf.d/suhosin.ini or integrated in php.ini, based on your Linux distribution. This is a config we use, together with explanation:
# Enable Suhosin. extension=suhosin.so # How many directory traversals are permitted? "../dir" is OK, # "../../../../../dir" is not (5 times > 4). suhosin.executor.include.max_traversal=4 # Disable /e in preg_replace which is usually used insecurely. Feel free to # turn on at dedicated servers and slap everybody who uses /e. suhosin.executor.disable_emodifier=Off # Protect mail forms against spammer attacks (Effectively disables any headers # injected from user input. Very important. suhosin.mail.protect=2 # Upper limit for memory. When safe_mode is disabled, users can use ini_set to # change their memory limit, with Suhosin up to this amount. suhosin.memory_limit=256M # What to do when Suhosin filters out something. 402 = 402 HTTP response. # See Suhosin conf. suhosin.filter.action=402 # Maximum limits for variables coming from COOKIE, POST and GET. # These are reasonable values (based on experience). suhosin.request.max_array_depth=4096 suhosin.request.max_array_index_length=2048 suhosin.request.max_name_length=2048 suhosin.request.max_value_length=650000 suhosin.request.max_vars=4096 suhosin.post.max_array_depth=8048 suhosin.post.max_array_index_length=1024 suhosin.post.max_name_length=2048 suhosin.post.max_totalname_length=8048 suhosin.post.max_vars=4096 # Maximum file uploads in a script. suhosin.upload.max_uploads=100 # Newest thing we learned. Disable any include,curl,fpassthru,base64_encode,mail # and others in eval(). This is Security by obscurity, however it works # very well for shared hosts when an attacker is able to upload a bad # script. Most of the current scripts use obfuscated code decoded from # base64 and then eval()'ed. This stops them, until they learn something new. suhosin.executor.eval.blacklist=include,include_once,require,require_once, curl_init,fpassthru,file,base64_encode,base64_decode,mail,exec,system,proc_open, leak,syslog,pfsockopen,shell_exec,ini_restore,symlink,stream_socket_server, proc_nice,popen,proc_get_status,dl, pcntl_exec, pcntl_fork, pcntl_signal, pcntl_waitpid, pcntl_wexitstatus, pcntl_wifexited, pcntl_wifsignaled, pcntl_wifstopped, pcntl_wstopsig, pcntl_wtermsig, socket_accept, socket_bind, socket_connect, socket_create, socket_create_listen, socket_create_pair,link,register_shutdown_function,register_tick_function # Feel free to turn on, disables eval() at all. suhosin.executor.disable_eval=Off # We don't use but feel free. Function whitelist! # Anything that's not in this list will not be permitted! suhosin.executor.func.whitelist= # This is equivalent to disable_functions in php.ini. suhosin.executor.func.blacklist= # Log all actions into Syslog. suhosin.log.syslog = S_ALL & ~S_SQL # Check all file uploads using some script. # The script must write "1" as a first line of standard output # to allow the upload, anything else to disallow. suhosin.upload.verification_script=/opt/check.sh
Based on my experience, Suhosin works very well, even together with PHP Xcache and Memcache.
See Hardened PHP for more configuration directives.
I have a small quiz for you! Take a look at suhosin.executor.func.blacklist. Do you know what is a huge difference between this directive and php.ini disable_functions? Post in comments and I'll buy a beer for the first one who answers correctly and also arrives at DrupalCon San Francisco.
Jakub is owner and founder of Dynamite Heads. Jakub is a member of Drupal Security Team and supports Czech Drupal community at Drupal.cz