|
Chapter 11. Hiding PHPIn general, security by obscurity is one of the weakest forms of security. But in some cases, every little bit of extra security is desirable.
A few simple techniques can help to hide PHP, possibly slowing
down an attacker who is attempting to discover weaknesses in your
system. By setting expose_php = off in your
Another tactic is to configure web servers such as apache to
parse different filetypes through PHP, either with an Example 11.1. Hiding PHP as another language# Make PHP code look like other code types
Example 11.2. Using unknown types for PHP extensions# Make PHP code look like unknown types
Example 11.3. Using HTML types for PHP extensions# make all php code look like html
Code Examples / Notes » security.hiding25-may-2005 09:06
You could also do this in .htaccess when you use Apache and your configuration allows you to override : <Files test> ForceType application/x-httpd-php </Files> That way, you can use the URL test?pop=true without having to fake it by using test/index.php. See the Apache manual for more info: http://httpd.apache.org/docs/mod/mod_mime#forcetype mmj
You can see if somebody's using PHP just by adding the following to the end of the URL: ?=PHPB8B5F2A0-3C92-11d3-A3A9-4C7B08C10000 If the page is using PHP, this will show the PHP credits. Setting expose_php to Off in php.ini prevents this. php
What about this in a .htaccess file : RewriteEngine on RewriteRule ^$ /index.php [L] RewriteRule ^([a-zA-Z0-9\-\_/]*)/$ /$1/index.php [L] RewriteRule ^([a-zA-Z0-9\-\_/]*)\.(html|htm)$ /$1.php [L] RewriteRule ^([a-zA-Z0-9\-\_/]*)$ /$1.php [L] Typing "sub.domain.foo/anything" loads "/anything/index.php" if 'anything' is a directory, else it loads "/anything.php". I'm sure you can find mutch better, but it works great on my site :) bryce nesbitt
Using the .php extension for all your scripts is not necessary, and in fact can be harmful (by exposing too much information about your server, and by limiting what you can do in the future without breaking links). There are several ways to hide your .php script extension: (1) Don't hard code file types at all. Don't specify any dots, and most web servers will automatically find your .php, .html, .pdf, .gif or other matching file. This is called canonical URL format: www.xxxxxx.com/page www.xxxxxx.com/directory/ This gives you great flexibility to change your mind in the future, and prevents Windows browsers from making improper assumptions about the file type. (2) In an Apache .htaccess file use: RewriteEngine on RewriteRule page.html page.php (3) Force the webserver to interpret ALL .html files as .php: AddType application/x-httpd-php .php3 .php .html yasuo_ohgaki
To hide PHP, you need following php.ini settings expose_php=Off display_errors=Off and in httpd.conf ServerSignature Off (min works, but I prefer off) sth
The flipside to this is, if you're running a version of PHP/Apache which is not known to have exploitable bugs (usually the latest stable version at the time), and an attacker sees this, they may give up before even trying. If they don't, they may continue to attempt their exploit(s). It really depends on the type of attacker. The educated, security advisory reading attacker vs. script kiddie on the street. If you're keeping up on patches, version exposition should not be a problem for you. prrogers
The default session identifier-name PHPSESSID is publicly visible in an HTTP cookie and or URL if sessions are used. It can be changed in the php.ini to something more generic to further obscure PHP.
eric
Something that has not been mentioned here is also the PHPSESSION id that will be displayed in the URL when passing it from page to page using GET. If users have cookies set to off, this will be visible. This can be reset before any session_start() call with ini_set(). Be aware however that this can't be changed in this way if you use autho session start.
rustamabd
So far I haven't seen a working rewriter of /foo/bar into /foo/bar.php, so I created my own. It does work in top-level directory AND subdirectories and it doesn't need hardcoding the RewriteBase. .htaccess: RewriteEngine on # Rewrite /foo/bar to /foo/bar.php RewriteRule ^([^.?]+)$ %{REQUEST_URI}.php [L] # Return 404 if original request is /foo/bar.php RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$" RewriteRule .* - [L,R=404] # NOTE! FOR APACHE ON WINDOWS: Add [NC] to RewriteCond like this: # RewriteCond %{THE_REQUEST} "^[^ ]* .*?\.php[? ].*$" [NC] 29-jan-2003 06:53
PS. If you want to use pretty URLs (i.e. hide your .php extensions) AND you have safe-mode=on, the previous example (ForceType) won't work for you. The problem is that safe-mode forces Apache to honor trailing characters in a requested URL. This means that: http://www.foo.com/home would still be processed by the home script in our doc root, but for: http://www.foo.com/home/contact_us.html apache would actually look for the /home/contact_us.html file in our doc root. The best solution I've found is to set up a virtual host (which I do for everything, even the default doc root) and override the trailing characters handling within the virtual host. So, for a virtual host listening on port 8080, the apache directives would look like this: <VirtualHost *:8080> DocumentRoot /web/doc_root Alias /home "/web/doc_root/home.php" AcceptPathInfo On </VirtualHost> Some people might question why we are overriding the trailing characters handling (with the AcceptPathInfo directive) instead of just turning safe-mode=off. The reason is that safe mode sets global limitations on the entire server, which can then be turned on or left off for each specific virtual host. This is the equivilent of blocking all connections on a firewall, and then opening up only the ones you want, which is a lot safer than leaving everything open globally, and assuming your programmers will never overlook a possible security hole. l0rdphi1
More fun includes files without file extensions. Simply add that ForceType application/x-httpd-php bit to an Apache .htaccess and you're set. Oh yea, it gets even better when you play with stuff like the following: substr($_SERVER['PATH_INFO'],1); e.g. www.yoursite.com/somepage/55 And: foreach ( explode('/',$_SERVER['PATH_INFO']) as $pair ) { list($key,$value) = split('=',$pair,2); $param[$key] = stripslashes($value); } e.g. www.yoursite.com/somepage/param1=value1/param2=value2/etc=etc Enjoy =) raz
May some servers not allow you to put this line (i.e this not work) AddType application/x-httpd-php .asp .py .pl or DefaultType application/x-httpd-php so, the alternative method that really a good one is: 1- In your .htaccess file write: RewriteEngine on RewriteBase /dire/ or just / RewriteRule securename yourfile\.php [T=application/x-httpd-php] example: all url like www.example.com/securename parsed as www.example.com/yourfile.php 2- but here the $_GET not work, but $_POST work, so for dynamic pages like www.example.com/yourfile.php?page=1 you use www.example.com/securename?page=1 now: instead of using $_GET use <?php $uri = $_SERVER['REQUEST_URI']; $page = strstr($uri, '='); $page = substr($page, 1); $valid_pages = array('1', '2','...'); $page = in_array($page, $valid_pages) ? $page : '1'; //.... ?> and for bad URL you can add this code to .htaccess file of coarse below the first code in .htaccess #-- RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^.*$ http://www.example.com/securename [L] 12-may-2004 04:20
Keep in mind, if your really freaked out over hiding PHP, GD will expose you. Go ahead - make an image with GD and open with a text editor.. Somewhere in there you'll see a comment with gd & php all over it. kevin vincent
Just a thought but if you have changed the extensions that php interprets I would assume you've also changed header.php and footer.php files to the new extension. EG: index.php, somefile.php, header.php, footer.php... Change the Apache directive so PHP interprets .kev files and rename your files: index.kev, somefile.kev, header.kev, footer.kev If you leave header and footer as PHP files then it won't understand how to interpret them. user
It is unnecessary, to let every Pampelhuber inspect your 'php.ini' files. Put the following into the .htaccess of your htdocuments' root: #Obscure 'php.ini' files (where they exist) RedirectMatch 404 .*php\.ini$ benjamin
In response to the previous messages, for apache, there is a easier way to set files without "." to be executed by PHP, just put this in a ".htaccess" file : DefaultType application/x-httpd-php jtw90210
In order to get the PATH_INFO to work in order to pass parameters using a hidden program/trailing slash/"pretty url" in more recent versions of PHP you MUST add "AcceptPathInfo On" to your httpd.conf. AddType application/x-httpd-php .php .html AcceptPathInfo On Try it out with your phpinfo page and you'll be able to search for PATH_INFO. http://yourserver.com/myphpinfo.php/showmetheway If you want to drop the .php use one or both of these: DefaultType application/x-httpd-php ForceType application/x-httpd-php dimitar
In case there are an Internal Server error(error 500) using the old code below in an .htaccess file, you can replace it with the code modification that must solve the problem. Old code ----------- <Files ~ "^[^\.]+$"> ForceType application/x-httpd-php </Files> Replacement of the code above(code modification) ------------------------------------------------------------ AddHandler server-parsed .php <Files ~ "^[^\.]+$"> SetHandler application/x-httpd-php </Files> Regards, Dimitar Tanev raven-3
I've found that your script ahmad does not work to me. So I've modified it, maybe someone will find it useful: //default page $config['main']="main"; //checking query $QS=explode("&",$_SERVER['QUERY_STRING']); $QS=explode('/',$QS[0]); //we have to find out if main page is in Query string //if not, then use default if (!$QS[0]) $MODULE=$config['main']; else $MODULE=strtolower($QS[0]); //here everything take place //below query is converted into table. //use it like following: $_QUERY['theme'] for ($i=1;$i<count($QS);$i+=2) $_QUERY[$QS[$i]]=$QS[$i+1]; so eg link: http://xyz.com/?projects/topic/20/theme/purple means: $module="projects"; $_QUERY['topic']=20; $_QUERY['theme']="gray"; PS. I'm using PHP 4.4.2 php
I´ve found an easy way to hide php code and the uri is searchable by google and others...(only for unix or linux) At first I have some rules in my hide.conf (i made an extra .conf for it (apache 2.0)) For example when I want to mask the index.php <Files index> ForceType application/x-httpd-php </Files> My problem is, that my code should be readable... so I made an extra folder for example srv/www/htdocs/static_output My phpcode is in the includefolder....(for ex. mnt/source/index.php) Then I made a link in the shell > ln mnt/source/index.php srv/www/htdocs/static_output/index So the code is readable (with .php extension) in my includefolder and there is only the link in the srv folder without extension(which is called by the browser...). m1tk4
I usually do: <code> RewriteEngine on RewriteOptions inherit RewriteRule (.*)\.htm[l]?(.*) $1.php$2 [nocase] </code> in .htaccess. You'll need mod_rewrite installed for this . simon
I use the following in the .htaccess document <IfModule mod_rewrite.c> RewriteEngine On RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> then the following simple code <?php $permalinks = explode("/",$_SERVER['REQUEST_URI']); $varone = $permalinks[1]; $vartwo = $permalinks[2]; ... ?> marpetr
I think the best way to hide PHP on Apache and Apache itself is this: httpd.conf ------------- # ... # Minimize 'Server' header information ServerTokens Prod # Disable server signature on server generated pages ServerSignature Off # ... # Set default file type to PHP DefaultType application/x-httpd-php # ... php.ini ------------ ; ... expose_php = Off ; ... Now the URLs will look like this: http://my.server.com/forums/post?forumid=15 Now hacker knows only that you are using Apache. ahmad
I am use this script to hidding PHP: index.php -------------- <?php // PARSING QUERY STRING $QS=explode("&",$_SERVER['QUERY_STRING']); $QS=explode('/',$QS[0]); // IF Modul is Undefined set it to index if (!$QS[0]) $MODUL='index'; else $MODUL=strtolower($QS[0]); // WE can make a Variable $_QUERY // for alternative _GET for ($i=1;$i<count($QS);$i+=2) { $_QUERY[$NVAR]=$NVAR=$QS[$i]; $$NVAR=$QS[$i+1]; } // Check the Modul is exists? if (!file_exists("modul_directory/{$MODUL}.php")) $MODUL="index"; #### THIS IS EXAMPLE TO IMPLEMENTATION THE SCRIPT // Load The Template include("template.php"); // Load The Module include("modul_directory/{$MODUL}.php"); // Load The Footer include("footer.php"); ?> we can access the modul in URL like this: ================================= www.example.com/?forum/topic/20 - it mean load the modul forum.php, and set the _QUERY['topic']=20 www.foo.com/?voting/id/54/type/piechart&choice=2 - it mean load the modul voting.php, and set the _QUERY['id']=54 and _QUERY['type']='piechart' and set _GET['choice']=2 28-dec-2005 03:29
Even you hide your PHP, requests for bugy scripts still come. No matter whether you have the script on your server or not. You can make an additional step for those requests. Since the host now trying that buggy script then, in the future when a new bug arises it will be tried by that host again with a high possibility. So banning that host completey at its first attempt may be a good idea. For this, 1- Add Permanent links for those requests in your httpd.conf: RedirectMatch permanent (.*)awstats(.*)$ http://your_server/your_script.html RedirectMatch permanent (.*)xmlrpc(.*)$ http://your_server/your_script.html and add whatever you want to ban. 2- Write following code in your_script.html <? $host= $_SERVER['REMOTE_ADDR']; $dropit = "iptables -A INPUT -i eth0 -p tcp -s $host -m multiport --destination-ports 80,25,22 -j DROP"; shell_exec($dropit); exit ?> Yavuz Darendelioglu nikolai-zujev-
Assign files w/o extension to php interpreter without using ReWrite module [clip httpd.conf] <Files ~ "^[^\.]+$"> ForceType application/x-httpd-php </Files> [/clip] azureash
Another way to hide your .php extensions is to use the Apache ForceType directive (which is often referred to as pretty URLs.) Basically you force Apache to parse a file as PHP that matches the trailing directory name in your URL. For example, place this directive in your Apache httpd.conf file: <Location /home> ForceType application/x-httpd-php </Location> and create a php file name "home" in your doc root. This file should not have a .php extension, and can be a php template file. Combined with a function to strip out URL parameters, this can create a new templating system, which can effectively hide your file extensions. In this example, http://www.foo.com/home/bar.html would actually use the home script we created, and then the "bar.html" could be used to specify content to include. bminton
Another technique is to have every file be named index.php and be in it's own directory. Then instead of using for instance http://my.site/foo.php you could use http://my.site/foo/ where foo is a directory with a file called index.php in it.
istvan dot takacsnospam
And use the ServerTokens min directive in your httpd.conf to hide installed PHP modules in apache. dyer85
Although it's probably obvious to most people, Yavuz Darendelioglu's post below utilizes a method that will only work on a *nix OS, not Windows, and probably not Mac. Also, his regex uses some superfluous matching, instead, write the redirect like so: (you don't really need to use absolute path when redirecting to a resource on the same server, either): RedirectMatch (?:awstats|xmlrpc) /deny.php ldemailly
adding MultiViews to your apache Options config lets you hide/omit .php in the url without any rewriting, etc... elora
<bminton at efn dot org>'s suggestion won't work. All someone has to do is look at "foo.com/dir/" and try "foo.com/dir/index.html", "foo.com/dir/index.php", "foo.com/dir/index.cgi", until no 403/404 is returned.
|