User Tools

Site Tools


linux:securingphp

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
linux:securingphp [2014/12/24 10:42] – external edit 127.0.0.1linux:securingphp [2024/02/05 13:57] (current) rlunaro
Line 1: Line 1:
 ====== Securing PHP ====== ====== Securing PHP ======
  
-Some years ago had the personal pleasure of know c99.php: a website of a friend of mine got caught by this unpleasant visitor+Here is my configuration / notes about securing a php installation.  
 + 
 + 
 +===== Avoid common exploits ===== 
 + 
 +These configuration rules are taken from the .htaccess file configuration of Joomla, and  
 +I've adapted it for apache. They address some common exploits.  
 + 
 +<code> 
 + 
 +<IfModule mod_rewrite.c> 
 +    RewriteEngine On 
 +     
 +    ## Begin - Rewrite rules to block out some common exploits. 
 +    # If you experience problems on your site block out the operations listed be 
 +    # This attempts to block the most common type of exploit `attempts` to Jooml 
 +    # 
 +    # Block out any script trying to base64_encode data within the URL. 
 +    RewriteCond %{QUERY_STRING} base64_encode[^(]*\([^)]*\) [OR] 
 +    # Block out any script that includes a <script> tag in URL. 
 +    RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR] 
 +    # Block out any script trying to set a PHP GLOBALS variable via URL. 
 +    RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR] 
 +    # Block out any script trying to modify a _REQUEST variable via URL. 
 +    RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) 
 +    # Return 403 Forbidden header and show the content of the root homepage 
 +    RewriteRule .* index.php [F] 
 +    # 
 +    ## End - Rewrite rules to block out some common exploits. 
 + 
 + 
 +    ## Begin - Joomla! core SEF Section. 
 +    # 
 +    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 
 +    # 
 +    # If the requested path and file is not /index.php and the request 
 +    # has not already been internally rewritten to the index.php script 
 +    RewriteCond %{REQUEST_URI} !^/index\.php 
 +    # and the request is for something within the component folder, 
 +    # or for the site root, or for an extensionless URL, or the 
 +    # requested URL ends with one of the listed extensions 
 +    RewriteCond %{REQUEST_URI} /component/|(/[^.]*|\.(php|html?|feed|pdf|vcf|raw 
 +    # and the requested path and file doesn't directly match physical file 
 +    RewriteCond %{REQUEST_FILENAME} !-f 
 +    # and the requested path and file doesn't directly match a physical folder 
 +    RewriteCond %{REQUEST_FILENAME} !-d 
 +    # internally rewrite the request to the index.php script 
 +    # RewriteRule .* index.php [L] 
 +    # 
 +    ## End - Joomla! core SEF Section. 
 + 
 + 
 + 
 + 
 +</IfModule> 
 + 
 +</code> 
 + 
 +===== per directory configuration ===== 
 + 
 +Not all the directories of your website are the same; some of them must allow the  
 +execution of php, some others not. **In the case you have to allow php execution**,  
 +you have use "php_admin_flag engine On" to allow php execution in that directory:  
 + 
 +<code> 
 +<Directory "/var/www/YOUR-DIRECTORY/"> 
 + 
 +    Options -Indexes +FollowSymLinks 
 + 
 +    AllowOverride None 
 + 
 +    php_admin_flag engine On 
 + 
 +    php_admin_value open_basedir "LIST-OF-DIRECTORIES-HERE" 
 +    php_admin_value include_path "ALLOWED-INCLUDE-DIRECTORIES-HERE"     
 +    php_admin_value upload_tmp_dir "ALLOWED-TMP-FILES-HERE" 
 +    # you can configure any php param here:  
 +    php_admin_value post_max_size "25M" 
 +    php_admin_value upload_max_filesize "20M" 
 +</Directory> 
 +</code> 
 + 
 +==== Any other directory where won't be php files must have the php execution restricted ==== 
 + 
 +PHP execution must be restricted in those directories where  
 +it's clear won't be any php file in them: 
 + 
 +<code> 
 +<Directory "/var/www/MY-WEBSITE/UPLOADED-FILES"> 
 +    # To avoid c99.php injection 
 +    php_admin_flag engine Off 
 +</Directory> 
 +</code> 
 + 
 +==== Even it'good idea to restrict any request to some directories at all ==== 
 + 
 +For instance, you can restrict the access to your logs directory of your website at all  
 +to avoid someone could guess the url and try to gain access to the logs content:  
 + 
 +<Directory "/var/www/MY-WEBSITE/logs"> 
 +    <RequireAll> 
 +        Require all denied 
 +    </RequireAll> 
 +    php_admin_flag engine Off 
 +</Directory> 
 + 
 +==== Ohter directories must only be executed from inside your website ==== 
 + 
 +Imagine you have a directory of php files you only want through a cron  
 +file: in that case, specify that those directory cannot be reached from  
 +any place, but from inside of the machine only:  
 + 
 +<code> 
 +<Directory "/var/www/MY-WEBSITE/RUNNING-FROM-INSIDE"> 
 +            <RequireAll> 
 +                    Require local 
 +            </RequireAll> 
 +</Directory> 
 +</code> 
 + 
 + 
 + 
 + 
 +===== php_openbasedir must be configured per site ===== 
 + 
 +In the apache configuration of the virtual host, **open_basedir** must be configured and must point  
 +to the directory of the web application or deeper, to ban php to open other files that aren't in the  
 +installation.  
 + 
 +Example: 
 + 
 +<code> 
 +    <Directory "/mywebsite"> 
 +        php_admin_value open_basedir "/mywebsite:/dev/urandom" 
 +    </Directory> 
 +</code> 
 + 
 +===== include_path must be specified also and limited to the web directory or deeper ===== 
 + 
 +''include_path'' is another funny thing. It specifies what php files can be read by the  
 +''include'' command: it's better to specify the more constrained directory possible: if the  
 +application has an "include" directory, specify this directory only, to avoid an attacker  
 +to read configuration files or other information.  
 + 
 +This configuration must be set per virtual host, and it's better to set a non-existent file  
 +in the main php.ini file.  
 + 
 +Example: 
 + 
 +<code> 
 +  php_admin_value include_path "/mywebsite/include/" 
 +</code> 
 + 
 + 
 +===== upload_tmp_dir must be set OUTSIDE YOUR WEBSITE ===== 
 + 
 +**__This is a frequent source of problems__**. And I misunderstood that many times, until somebody 
 +kindly let me know about this, by injecting c99.php in my website. This directive configures  
 +the directory where upload files must be placed when loaded: it's a very bad idea to have them  
 +inside your website, because it allows an attacker to upload any php file and execute it afterwards.  
 + 
 +Example:  
 + 
 +<code> 
 +php_admin_value upload_tmp_dir "/tmp" 
 +</code> 
 + 
 + 
 +===== engine must be unset if the site doesn't need php  ===== 
 + 
 +Configure ''engine on'' only if you need php in the virtual host:  
 + 
 +Example:  
 + 
 +<code> 
 +php_admin_value engine On 
 +</code> 
 + 
 +In any other website, turn it off
  
-For those who don't know this script, it is a little piece of art: once uploaded to a website, it allows the attacker to change everything that is changeable and to hack everything that is hackable, if such verb exits. Well, to the point: I am the type of person that thinks that the solution is not to create an automatic to tool to scan the server every X minutes and detect it and delete this type of files. The solution is to put in place the security measures to avoid and minimize the posibility of these scripts to prosper.  
  
-After examining the website, soon we realized that there are ways to avoid an attack of this nature without restricting too much the security of your instalation. Here is a little resume of what we have learned of that days.  
  
  
linux/securingphp.1419414128.txt.gz · Last modified: 2022/12/02 22:02 (external edit)