6 ms·
What'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/
by snorkel 15y ago
What'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.
- elliottcarlson 15y agoIdeally though, you should make sure that anything not part of your system, doesn't get passed through PHP. This will take away this common security risk, as well as limit the overhead required to serve those files.
- maratd 15y ago> Ideally though, you should make sure that anything not part of your system, doesn't get passed through PHP. For you to upload a file to your system it has to pass through PHP. That's where the problem is. Once it's on your system, it can be executed by other means ... those means not necessarily being Apache or NGINX. By encoding the upload, you not only reduce the size, but also render it harmless.
- infinity 15y agoJust a thought: can we find some input, which will turn into a malicious script, when compressed or encoded by an algorithm and saved as a file on the server? The encoded file could contain something like <?php ... ?>. If the server could be tricked into parsing the encoded file for PHP, we are in trouble. I think about uploading an additional .htaccess, which will contain a directive to send .zip files to the PHP parser - of course this should never be possible. There are some encoder/decoder tools on the web, where it is possible to enter, for example, base64 encoded strings and get these decoded. It is often possible to enter base64 encoded JavaScript plus some closing tags or brackets to break out of the input field. When decoded, the JavaScript will be executed by the browser and we have found a cross-site scripting flaw.
- maratd 15y ago> Just a thought: can we find some input, which will turn into a malicious script, when compressed or encoded by an algorithm and saved as a file on the server? This is not possible with gzip: http://www.gzip.org/zlib/rfc-gzip.html#file-format http://www.gzip.org/zlib/rfc-gzip.html#file-format I should mention that on top of this technique, I also rename all files uploaded to a random hash that is stored in a database. That hash is never revealed to the client. When the file is downloaded, the real name is provided from the database as the file name, while the source of the file is read from its true location. So even if an intruder were to upload a malicious file and somehow managed to bypass the encoding algorithm ... he wouldn't know where to find it. He would have to hack the database on top of everything just to find out where it is.
- gcb 15y agowhat i do is to serve user facing php files as .html and keep backend includes as .php then just block apache to serve anything .php this usually get me covered of most backdoors bugs in pear and such. ...not that i do that because of this reason. it was first only for organizing the code tree.
- infinity 15y agoBut this usage of hidden php can sometimes be detected. If expose_php is not Off, you can see the X-Powered-by HTTP header and the PHP version, if the requested page was a PHP ressource. You can also try to get the PHP eastereggs displayed with something like this, on a PHP generated page: http://example.com/?=PHPE9568F36-D428-11d2-A769-00AA001ACF42 http://example.com/?=PHPE9568F36-D428-11d2-A769-00AA001ACF42 Trying to provoke errors or weird PHP specific behaviour, maybe with PHP error messages displayed, is another way to gather some informations about the script language used by a site. But this is already more aggressive than simply looking for an X-Powered-By: header. Just rewriting the file extension does not make a site any safer. Omitting file extensions is generally an interesting alternative, because in case you change from .php to .aspx or whatever, all URLs stay the same. Cool URIs don't change.
- shabble 15y agoI think there probably is some security in changing or omitting file extensions in your URIs. It seems that an awful lot of exploited sites are attacked opportunistically - you find an exploit, find a suitable search term, and google up some victims. If you can move yourself out of matching those general results, you gain the (small) benefit of not being hit by all those automated scan/'sploit scripts. Yes, it's security through obscurity, and is absolutely not something you should rely on, but it can reduce the number of people giving your wobbly-looking front door a kick. Of course, if everyone starts doing this, the scanners will switch to more robust methods of testing for your language and server types and versions.
- gcb 15y agoI couldn't care the slightest about exposing php. Only safe bet is to assume your public facing services will be compromised at one point. it was a decision mostly done by usability and code clarity (separate presentation scripts from data/model ones) But one benefit of not having the regular setup, is that even if i'm a victim of an automated attack, it will probably fail because it did not expected to not be serving .php or .phtml files as php. For a skilled targeted attack i'd still be as hopeless as the person hiding php. had that happen when one box was compromised because of a ssh key bug. but it turned out, the attack was automated and had vectors that worked with linux x86 and several common unixes. i was running irix on an very old box. so i had just some weird log entries instead of a root kit. not that it prevented the paranoid i am to wipe the system as if i had a root kit.
- ars 15y ago"every PHP app"?? What about apps that don't limit themself to just index.php? I never understood this obsession with having everything flow through index.php. Apache already has a method to dispatch requests to the proper controller AKA file. Why rewrite it again? This is fictional security. If someone can upload a file, they can also upload index.php (and from my experience cleaning up a few hacks, that is exactly what they do). And if you (correctly) set it so they can't write to the top level directory, what you really should do is remove the php handler from the directories they can write to.
- kijin 15y agoHaving everything go through index.php (the "front controller") makes it a lot easier to manage common libraries and use PHP's autoloading capability. You don't have to add a bunch of includes to every script. You don't have to change every script if you decide to replace one of the common libraries. You can force every request to go through the same set of checks (such as authentication). You can have pretty URLs like "/blog/post/123". The front controller pattern doesn't have much to do with security, though. It also doesn't work with apps like WordPress.
- jontas 15y agoI personally run my applications entirely through index.php but your argument does not make sense. You can easily include one file at the top of all your scripts and have that handle things like autoloading, authentication, etc. Then if you need to make a change you are still only changing it one spot.
- kijin 15y agoIf you have a front controller, you don't even need to repeat that single include in any file. Why repeat the same include in 100 different files if you can avoid it? Also, what if you realize after a while that you need to change the location of the single include file because you carelessly placed it in a publicly accessible directory (bad for security) ? Now you have to edit 100 files. Another reason: What would your templates look like if your app had 100 different entry points? It would seem silly to have 100 template files in addition to 100 PHP scripts. So the developer is most likely to mix business logic with templates in the same file(s). Not good. Of course, if you're a good enough developer to know that you should avoid problems like this, it doesn't really matter how you organize your site. But I think that the front controller pattern helps to push developers (especially novices) toward the right direction.
- mark242 15y agoI'm reading this, and I'm just dumbstruck that, in over 15 years of development, that this is actually a recommended solution to PHP security. This isn't a knock against your configuration; I'm sure it's (probably) fine for your usage, but whatever happened to properly sanitizing and sandboxing uploaded content? I mean, I'm trying to imagine another web application language where "attackers can upload whatever (X) file they want" is even a valid case, ever. I mean, imagine a war file being wholesale replaced-- it isn't possible without going out of your way to misconfigure your app server. This, I think, is the base problem with PHP; the default configuration is predicated upon content and code not being segregated at all, and hot redeploy is the norm, without any notification to the admin that it's actually happening.
- kijin 15y agoIf you're writing the app, you're absolutely right. Apps should be written in such a way that everything is properly sanitized and sandboxed. Unfortunately, a lot of people who use PHP are stuck with third-party apps with questionable security records, such as WordPress. If you want to have anything resembling security in such an environment, you need to resort to band-aid solutions such as disabling functions. It's far from optimal, I admit, but at least it helps reduce damages if (or rather, when) the third-party app gets hacked.
- mark242 15y agoOkay, yes, a considerable amount of blame lies with apps and frameworks that have security holes. But here's the thing: make the runtime secure /by default/, so that -- if you really want to run Wordpress, you have to uncomment the PHP configuration labeled "this is extremely hazardous and will likely result in your machine getting compromised" and I think you'll find those third-party apps and frameworks cleaning up their act in a hurry.
- kijin 15y agoMany of those features are completely harmless if used correctly. By itself, exec() doesn't cause your machine to be compromised. It is a valuable function that every scripting language should have. (Would you like Python to disable os.exec* by default just to make websites more secure?) Besides, incompetent developers will always find a way to make vulnerable apps using even the most benign features. The only way to make a runtime secure against fools is to allow nothing. There is also the logistical problem that if the default runtime can't run popular apps such as WordPress, people will simply switch to a broken runtime instead of cleaning up WordPress. This is a particularly big problem in shared hosts who need to make their service compatible with everything or risk losing business. It's been difficult enough to get them to adopt PHP 5.3. On the other hand, safe_mode, register_globals, magic quotes, etc. can and should be disabled by default. Good news: The PHP team is finally getting around to deprecating them. Also, I use dotdeb's FPM packages on my servers, and dotdeb's default configuration tends to be pretty good.
- infinity 15y agoI would prevent uploads of arbitrary PHP files. If they are not parsed by the PHP interpreter, they might be delivered as PHP source code, like an ordinary text file. This could be used to be included into another vulnerable website. So your website is part of an attack, the malicious code is on your server, but remotely included and executed on another machine. Also, if nearly arbitrary PHP files can be uploaded, the chances might be good that it's possible to upload other files as well, like some additional .htaccess files for subdirectories.