8 ms·
Securing PHP
- elliottcarlson 15y agoAlso look in to Suhosin[1] from the Hardened-PHP Project [1] http://www.hardened-php.net/suhosin/ http://www.hardened-php.net/suhosin/
- jamescun 15y agoThanks, added it to the post.
- brokentone 15y agoI've looked into that, but the last update was 5 years ago. I realize it's a patch, so it doesn't necessarily correspond to a particular release, but is it up to date for modern PHP installs?
- duskwuff 15y agoI'm not sure where you're looking, but there are up-to-date patches at: http://hardened-php.org/suhosin/download.html http://hardened-php.org/suhosin/download.html
- elliottcarlson 15y agoI'm not sure where you see that - the latest patch is available for 5.3.7 at http://www.hardened-php.net/suhosin/download.html http://www.hardened-php.net/suhosin/download.html It's not up to date with 5.3.8 or 5.4 - but they are always slightly behind - but not 5 years behind. Edit: Now I see that their news page is really out of date - my bad.
- brokentone 15y agoAhh yes, thank you. I had always noticed the homepage lists the last release in 2006 and the documentation seems to be about the same and I never got to the downloads page.
- Udo 15y agoI see you marked the cURL functions as "dangerous", advising people to disable curl_exec and curl_multi_exec. This disables all apps that do HTTP requests (except those that communicate through the socket functions). Is there any particular reason why you consider cURL problematic?
- jamescun 15y agoYou are correct, that was a mistake on my behalf. The post has been amended.
- fooyc 15y agoDisabling parse_ini_file looks like a mistake too ;) (It's just a ini file parser; it has nothing to do with PHP settings.)
- jamescun 15y agoI typically disabled it because (historically, not 100% sure now) even with restrictions in place, you can still read PHP.ini and (not now mind) you could also write to the INI config with the ini functions.
- duskwuff 15y ago> You can still read PHP.ini You can always detect the contents of php.ini using functions like ini_get. Disabling those isn't recommended, as a lot of applications use them legitimately to read things like memory_limit or safe_mode. > You could also write to the INI config with the ini functions. That sounds really unlikely, unless you had php.ini owned by your Apache user or you were running PHP as root. Either one of those possibilities would have left you open to much worse problems. Perhaps you're thinking of ini_set? That only affects the current request; it doesn't have any long-term effects, nor does it write to config files.
- Joakal 15y agoparse_ini_file is highly useful if you want to avoid tumblr's php file sensitive exposure problem of includes.
- DCoder 15y agoSometimes you really need to invoke external commands through exec(). In those cases, make sure to use escapeshellcmd() and escapeshellarg().
- eekfuh 15y agoFirst off, under disabled functions, 'eval' needs to be number one. Secondly, I was kind of disappointed that this wasn't an overview on common mistakes users do when learning PHP. This feels basically feels like teaching someone how to enable safe mode, because you aren't teaching someone why they should escape sql or why they should encode user submitted content, which to me is much more important. (Though teaching someone to install Suhosin and disabling debug output is still important in my opinion, so props for that)
- jamescun 15y agoIt is a valid point, perhaps I should do a followup, showing how these settings affect PHP and examples of how someone could exploit them.
- Mandar 15y agoIf you don't know much about PHP security, the single best step to secure your installation is to start by using the recommended PHP.ini file for a production deployment (often called php.ini-production or php.ini-recommended). This will set sensible defaults you can tweak for your own app. Also, open_basedir is nice and should be used whenever you can but it doesn't match a system-wide chroot.
- brokentone 15y agoThose are some good tips, however, the memory and script execution limits you're setting there will not play well with any sort of CMS or Framework. Wordpress, Drupal, Symfony all will need an occasional (or perhaps regular) bigger load. Minimally, maybe you could leave a note that custom settings should be made for these systems. I can just see hordes of wanna be sysadmins (like myself) going out and making all the changes you've said and unnecessarily break WP.
- kijin 15y agoYou're right about the 8M memory limit, but I don't think there's anything wrong with the 15 second execution limit. No page should take over 15 seconds to generate.
- damncabbage 15y agoWhat about upgrade scripts (usually done via the web interface)? Some flush()s output out to the browser (to show some initial feedback), but continue to process and send further output as the upgrade continues.
- peterwwillis 15y agoIsn't "secure PHP" an oxymoron?
- 46Bit 15y agoWhen written properly, a PHP app is probably just as secure as one written in any other language.
- uriel 15y agoExcept that building a "properly written PHP app" is way harder than in almost every other language in widespread use. The number of pitfalls and traps you can fall into almost surpasses the 'safe' parts of the language (and its environment).
- maratd 15y agoSome of us need a language to hold our hand. Some of us don't. Some of us enjoy the freedom of coding the way we want to code, without a language shoving some perceived notion of correctness down our throat. > Except that building a "properly written PHP app" is way harder than in almost every other language in widespread use. This makes no sense. PHP doesn't force you to do things the right way, but it doesn't force you to do things the wrong way either. It just doesn't force you either way. Those of us who know what we're doing can make intelligent decisions ... and those of us who can't, shouldn't be writing in PHP.
- FuzzyDunlop 15y agoNo one can make an intelligent decision until they know what an intelligent decision is. And everyone starts off at the beginning when they're picking up a new language (or want to start learning). To be dismissive of those who 'don't know what they're doing' doesn't necessarily help make those intelligent decisions better known and easier to understand, or why they're the intelligent decisions in the first place.
- 15y ago
- snorkel 15y agoWhat's missing from just about every PHP app and PHP framework is this bit of Apache config that prevents execution of trojan PHP scripts: <Directory /var/www/website> # Only execute /index.php and no other PHP files RewriteCond %{REQUEST_FILENAME} -f RewriteCond %{REQUEST_FILENAME} .php$ RewriteCond %{REQUEST_URI} !=/index.php RewriteRule ^(.*)$ not_happening [L,F] </Directory> # Remove other file types from PHP execution RemoveHandler .phtml .php3 This way attackers can upload whatever PHP file they want but they can't execute it though an Apache request. What if the attacker names their trojan "index.php"? Doesn't matter, only top-level index.php of the site can be executed.
- duskwuff 15y agoYou've missed a few file types -- I see that you've got "phtml", but a lot of web servers will also parse files with stupid extensions including: .php3 .php4 .php5 .ph3 .ph4 .php3p .pht
- elliottcarlson 15y agoSame idea, but for nginx: server { server_name domainname.com; root /srv/sites/domainname.com/httpdocs; index index.php; access_log /srv/sites/domainname.com/logs/access.log main; error_log /srv/sites/domainname.com/logs/error.log info; try_files $uri $uri/ /index.php?$query_string; location ~ \.php$ { try_files $uri $uri/ /index.php?$query_string =403; include /usr/local/nginx/conf/fastcgi_params; fastcgi_pass phpfpm; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
- maratd 15y ago> What if the attacker names their trojan "index.php"? Doesn't matter, only top-level index.php of the site can be executed. As an alternative, you can simply gzip all uploads automatically. You will save hard drive space and prevent any funny business.
- 15y ago
- skeptical 15y agoIt usually get's to my nerve when people jump in the "PHP is inferior language because I decided so" bandwagon, but this kind of security strategy ind of gives some base for such criticism. Disable external execution functions, eval, disable disable, disable. It appears to me that this is following the approach of disabling everything and nothing, then start coding without any security concerns, because you 'secured your PHP'. I'm not a security obsessed person, but after hearing so much fuss about PHP lack of security I headed up to milw0rm a few years ago to see what it was all about. To my surprise (not so much) all the exploits were based on non sanitized user data. Why would you use user data without sanitizing it? Why would you protect yourself against a file the hacker uploaded? (they should not have uploaded it in the first place) Why would you feed exec, eval, etc with potentially dangerous content? If a programmer is stupid enough to do so, disabling such functions won't prevent him/her from screwing up big time some other way. My advice: write proper applications with proper standard security in mind. It's not that hard.
- infinity 15y agoThe problem of working with unsanitized user input is not specific to PHP, this has been a problem with other server side scripting languages as well. Here is an ancient example: NT Web Technology Vulnerabilities, written by rain.forest.puppy, Phrack Magazine Volume 8, Issue 54 Dec 25th, 1998. http://www.phrack.org/issues.html?issue=54&id=8#article http://www.phrack.org/issues.html?issue=54&id=8#article This is one of the oldest articles on SQL injection I know of.
- skeptical 15y agoThat's what I am trying to say. Common security practices will put you out of danger. I'm confused why we should have recipes to 'secure PHP'. Why don't the regular security measures simply apply? My guess is that many don't know what they are so they apply follow 'secure PHP' guides and feel safe, though they are not.
- ars 15y agoMan, I so wish I had published or even just posted it on a newsgroup (usenet). I discovered/thought of SQL injection in 1996 (with ColdFusion code), but my boss refused to let me disclose it to anyone (I was young then and actually listened to him). He was going to do some big conference or something on the subject and drum up new business, but nothing ever came of it.
- static_cast 15y agoThat's pretty sound advice. However a lot of scripts won't work if you disable exec and co. some other random ideas for php-security: If you have to enable some form of option to exec binaries be aware that open_basedir is useless now, because the attacker can just start a python instance and operate under apache user if you are using mod_php using fastcgi (mod_fcgid or nginx+php-fpm) and restrictive permissions on your directories should at least protect your other users home directories. another idea is prevent malicous scripts is to firewall apache and php from iptables. there is an iptables module for restricting uid and gid ranges to have access to the outside world. this could at least prevent a trojan dropped in /tmp to connect to their irc-server. but you can also disallow outgoing traffic to port 80, this breaks however all the auto-update features of e.g. wordpress. A lot of script-kiddie toolkits can also be stopped by not having gcc,wget,python etc.pp available to the user running php. if you have to host sensitive data on the same host as the php application it's wise to use a jail or at least chroot for php, there are some guides to put a mod_fcgid php into a chroot and: never ever use the mysql root user for database connectivity!