Hardening PHP on linux to increase security is a complex process involving a plethora of settings. A while back I developed a script in order to check for any security settings that were out of place.
The idea is that you run the script on your web server and it tells you what security settings are potentially mis-configured based on the rules that it reads from an XML file. Any settings that are not configured in line with best security practices are highlighted in red. It works in a similar way to the Centre for Internet Security’s benchmark scripts for other technologies. The one caveat is that it does need access to the ini_get function and requires a least PHP 5 to run.
The auditing script checks for (amongst other things):
- Secure session settings.
- Depreciated functions that might be relied upon.
- Functions that should be disabled.
- Dangerous settings that could lead to remote or local file inclusion.
- Error handling.
- Constants defined at compile time.
You might disagree with some of the recommended security settings or they might just not suit your current application; you can always change the XML file. A sample of the report generated by the Auditor is shown below.
You can download the script and use it to harden / secure your PHP installation. The tool is by no means a definitive hardening guide and any feedback or suggested rules / settings are welcome.

Great tool. I’ve just been using it to tweak one of my boxes.
Would you consider adding a licence and putting it up on Github so that people could contribute to it?
Glad you found it useful, spread the word. I’ll stick a GPL license on it and put it up on Github in the next few days. There is still a lot that needs to be done to it. Better explanations of each of the settings and support for extensions such as suhosin would be good. It might also be nice to include some settings from popular extensions such as APC etc.
Hi,
Looks like a great tool.
Do you have any more information or pointers to articles about the list of security checks/best practises you are checking?
Thanks,
Ian
I went through php.net and looked at each setting to determine if there could be a security risk associated with it. This site http://www.madirish.net/?article=229 also contains some good pointers on how to harden PHP.
I think I found a typo… is there such a function as fpaththru? Or did you mean fpassthru in the disabled functions section? Also, it says to use a custom directory for session.save_path but I had /tmp and the row in the HTML wasn’t red. Hope this helps, thanks a lot for the script!
Sorry for the double post. After googling, I can’t seem to find out a way to disable LIBXML_NONET and LIBXML_NOENT… would I need to recompile php? Is there a way to disable these in php.ini alone? Thanks again!
You have to disable it on compile, otherwise you need to specify the libxml_disable_entity_loader(true); before you parse any XML.
http://php.net/manual/en/function.libxml-disable-entity-loader.php. I’ll get round to fixing the 2 bugs you mentioned over the weekend :)
Hai bro,
Wow it is a nice script, i have been dreaming one building like this one, though my knowledge on php is still green and have a long way to go ><, hopefully i can learn something from your script, thx again ^^
regards
Great script… easy and very usefull… thx!
EXCELLENT stuff…. this is amazing for a fresh install.
Heartfelt thanks.
Phil, WOW, Thank you. Your comment pretty much says it all for me…
“I went through php.net and looked at each setting to determine if there could be a security risk associated with it. This site http://www.madirish.net/?article=229 also contains some good pointers on how to harden PHP.”
We all stand on the shoulders of giants! CB
Hi,
have you put this to github?
Great script! Thanks!
Great script. Thanks.
Discovered a bug you may want to fix:
self::Report(“disabled”, $function, (($de == 0) ? “enabled” : “disabled”), “disabled”, “”, (($de == 0) ? 1 : 0));
should be changed to:
self::Report(“disabled”, $function, (($de === false) ? “enabled” : “disabled”), “disabled”, “”, (($de === false) ? 1 : 0));
as ‘array_search’ returns 0 for the first element.
Thanks and keep up the great work.