l2t

PHP Security Configurations

PHP Security Best Practices For Sys Admins

If you are running php based web application it is very important to look at the following areas to secure the webserver:

  • XSS: Cross-site scripting is a vulnerability in php web applications
  • SQL Injection: It is a vulnerability in the database layer of an php application.
  • File uploads: If attacker upload malicious file then he can basically gain the control of the server.
  • Remote File Execution: An attacker can open files from remote server and execute any PHP code.
  • eval(): A function that allows string to run as php code.
  • CSRF: This attack forces an end user to execute unwanted actions on a web application in which he/she is currently authenticated.

Once you know kind of problems you are dealing with then you can tune your php configuration to secure your web app. First check what modules are installed by default when php was installed.

Command to list php installed module

Following command list all the installed modules in php:

php -m

Make sure you use necessary modules that you need for your web app. Remove unwanted modules or disable them.

Let's check the example about how you can remove the unwanted module:

# find the location where modules are stored
# use this location in following commands
php -i | grep ".ini files"

# remove sqlite3 module
mv /etc/php.d/sqlite3.ini /etc/php.d/sqlite3.disable

# or remove it completly
rm /etc/php.d/sqlite3.ini

# other methods to turn on/off
mv sqlite3.{ini,disable}
mv sqlite3.{disable,ini}

Restrict PHP Information Leakage

To disable information related to installed php you need to disable the following configuration in your php.ini file:

# Find the location of your php.ini
php -i | grep "php.ini"

# search following variable
# and turn this setting off
expose_php=Off

Error logging

Make sure you do not log all the errors on the browser rather log them in a specific file to view via command line:

# Find the location of your php.ini
php -i | grep "php.ini"

# Open php.ini file from above location
# Turn of Display error settings
display_errors=Off

# Add following settings
log_errors=On
error_log=/var/log/php/error.log

Disallow Uploading Files

If your application does not need to allow your visitor to upload files then disable the file upload. If your application needs to allow file upload then

  • enable file upload
  • restrict the upload file size
  • make sure your application logic filters the file extension that your application needs
# Find the location of your php.ini
php -i | grep "php.ini"

# Open php.ini file from above location
# Turn off/on your file upload settings
file_uploads=On
upload_max_filesize=1M

# To disable file upload
file_uploads=Off

Turn Off Remote Code Execution

To prevent attacker to execute php files remotely open your php.ini settings and turn off the following settings:

# Find the location of your php.ini
php -i | grep "php.ini"

# Open php.ini file from above location
# Save following configurations
allow_url_fopen=Off
allow_url_include=Off

Enable SQL Safe Mode

If turned On, mysql_connect() and mysql_pconnect() ignore any arguments passed to them. Let's have a look at the example:

# Find the location of your php.ini
php -i | grep "php.ini"

# Add following settings
# To your php.ini file
sql.safe_mode = On

# Define following variables
# Make sure you change the variables
# Add these lines to your php.ini
mysqli.default_host = "127.0.0.1"
mysqli.default_port = "3306"
mysqli.default_user = "root"
mysqli.default_pw = "Password123"

Now, when you have these configs in your php.ini file you do not need to define these variables during runtime. See below example:

# this line should be replaced
$db = new mysqli( "127.0.0.1", "root", "Pass123", "database_name", "3306" );

# with this line
# you don't need to pass above variables
$db = new mysqli();

Note: This feature has been REMOVED as of PHP 7.2.0.

Control Form POST Size

When a form is submitted via post request in php make sure you limit the size of the form data. Open your php.ini file and add following setting:

; Set a realistic value here
post_max_size=1K

The 1K sets max size of post data allowed by php apps. This setting also affects file upload.

To upload large files, this value must be larger than upload_max_filesize.

Resource Control (DoS Control)

Resource Control (DoS Control)

You can set maximum execution for your php script to proper value. This prevents long file execution if someone is running a script for long time:

Open your php.ini file and update these settings:

# set in seconds
max_execution_time = 30
max_input_time = 30
memory_limit = 40M

Disabling Dangerous PHP Functions

To disallow dangerous function to prevent server attack disable some of the dangerous functions in your php.ini file:

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

PHP Fastcgi / CGI – cgi.force_redirect Directive

The configuration directive cgi.force_redirect prevents anyone from calling PHP directly with a URL like http://xyz.c/cgi-bin/php/hackerdir/backdoor.php.

; Enable cgi.force_redirect for security reasons in a typical *Apache+PHP-CGI/FastCGI* setup
cgi.force_redirect=On

Limit PHP Access To File System

Following php.ini setting will allow php to access file within a specified directory, If a file is outside of the paths defined, PHP will refuse to open it.

; Limits the PHP process from accessing files outside
; of specifically designated directories such as /var/www/html/
open_basedir="/var/www/html/"

How Do I Search PHP Backdoors?

Followings are some of the commands to find any backdoors in your app:

grep -iR 'c99' /var/www/html/
grep -iR 'r57' /var/www/html/
find /var/www/html/ -name \*.php -type f -print0 | xargs -0 grep c99
grep -RPn "(passthru|shell_exec|system|base64_decode|fopen|fclose|eval)" /var/www/html/

Restrict File and Directory Access

Make sure your webserver root location has only permissions that you need:

# Allow read only permission
chmod -R 0444 /var/www/html/

# Mac OS
HTTPDUSER=$(ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\  -f1)
sudo chmod +a "$HTTPDUSER allow delete,write,append,file_inherit,directory_inherit" /var/www/html
sudo chmod +a "$(whoami) allow delete,write,append,file_inherit,directory_inherit" /var/www/html

# Linux OS
HTTPDUSER=$(ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\  -f1)
sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX /var/www/html
sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:$(whoami):rwX /var/www/html

Session Path

Make sure to update upload temp location and session save path as per your need:

# Path for session data
session.save_path="/var/lib/php/session"

# Temp upload file location
upload_tmp_dir="/var/lib/php/session"

I hope you like this tutorial do share and like if you are blown with this article.