How to Harden Your PHP for Better Security
PHP is widely used among many sites & applications, but should be hardened for security. Here’s some advanced tips to secure your PHP configuration file.
PHP is by far the most popular web back-end programming language in use today. To date, over 80% of sites with a backend implement PHP. WordPress, Joomla, and Drupal are all backed by it. Unfortunately PHP has become a popular target for hacking attempts, which is why securing its configuration is critical. Follow these simple steps to harden your PHP configuration and to help protect it from hacking vulnerabilities.
Locate the PHP Configuration File
The name of the configuration file for PHP is php.ini, which you will need to edit. The location of the file varies based on your hosting company and server type.
Edit with Shared Hosting
If you are not sure where your php.ini file is located, contact your hosting provider. Some providers require that you place PHP settings within the “.htaccess” file in the web root. If this is the case, PHP settings should be added one per line in the format “php_value Name value”. Keep in mind that your hosting provider may prevent certain settings from being modified.
Edit with a VPS or Dedicated Server
Web Host Manager (WHM) simplifies the process of editing the PHP configuration file by providing a simple user interface. Simply find the “Service Configuration” section in WHM and click “PHP Configuration Editor”. On the page that appears, select “Advanced Mode”.
If you are not using a control panel such as WHM, you will need to directly open and edit php.ini. The location of php.ini will vary based on your server’s operating system. Many Linux systems place the file at the path “/etc/php.ini”. You can confirm its location via the command line. Start by logging in to the server via SSH (contact your hosting provider for instructions). Once connected, enter the command “php –ini” and press Enter. Search for the line returned entitled “Loaded Configuration File” and take note of the php.ini file path.
You can open and edit php.ini using a text editor that runs within the command-line, such as “nano” for Linux. Simply type “nano /path/to/php.ini” and press Enter.
Within php.ini, each setting is placed on its own line in the format “settingname = settingvalue”. Any line starting with a semicolon is a comment, so don’t update any of those lines.
Edit Configuration Settings
Below is a list of settings that should be reviewed and updated to improve security. The settings are grouped into several sections below based on their purpose.
Section 1: Remote Connections
allow_url_fopen = 0
allow_url_include = 0
Do not allow fopen wrappers to open remote URLs. Remote content cannot always be trusted; disabling these options ensures that fopen wrappers can load only local content.
Section 2: Runtime Settings
max_input_time = 30
max_execution_time = 30
Limit the maximum amount of time allowed to process inputs, as well as the maximum amount of time that a PHP script can run. Here, both settings are set to a 30 second limit. This ensures that, in case a script became compromised, it would not read inputs or run for an extended period of time. A well-coded script should not require more than 30 seconds to run.
memory_limit = 8M
Ensure that a PHP script never utilizes more than 8MB of memory. In case a script was compromised, this setting effectively limits the amount of memory that the script can utilize.
register_globals = off
Disabling this setting effectively prohibits request data from automatically being stored as a variable. Registering global variables raises several concerns; one example is that environment variables can easily be modified. To avoid these issues, ensure that this setting is off.
expose_php = 0
By default, the presence of PHP as well as its version number are exposed as a part of HTTP responses. Since this provides unnecessary insight into the server, it is advisable to turn this off.
cgi.force_redirect = 1
Ensure that PHP can be run only through a web server redirect rule. This prevents PHP from being called directly, which improves security.
Section 3: Input Data Restrictions
post_max_size = 256K
max_input_vars = 100
Hackers can try to flood web application resources by sending mass data to it, which can reduce transfer speeds and available server resources. The effect of this type of attack can be minimized by reducing the maximum size of POST data, and also by limiting the amount of request data. Note that “post_max_size” also impacts the maximum size of file uploads; if your application has file upload capabilities, ensure that the value of this setting is at least as large as “upload_max_filesize”.
Section 4: Error Handling
display_errors = 0
display_startup_errors = 0
Error messages should never be displayed to the end user, since the messages often contain detailed information about the application’s code and the server. This information could potentially be used to assist hackers. Instead, log error messages to a secure file on the server.
log_errors = 1
error_log = /home/johndoe/error_log
PHP errors should be logged in order to debug the application code as well as to investigate for potential vulnerabilities. If you are using a file manager such as the one included with cPanel, a convenient and secure location for the error log is directly outside of the web root.
Section 5: Restrict File Access
open_basedir = "/home/johndoe/public_html"
Open_basedir ensures that PHP can include files from within only the listed directories. This improves security by preventing PHP scripts from unintentionally accessing secure files outside of the whitelisted paths. Note that you must add every directory that PHP needs to access to the whitelist, including the temporary file upload and session directories (see below). You can add multiple directories to the list by placing a colon between each directory. For example:
open_basedir = "/home/johndoe/public_html:/var/lib/php/tmp_upload:/var/lib/php/session"
Section 6: File Uploads
file_uploads = 0
If your application does not contain functionality for uploading files from users’ computers, it is advisable to disable this PHP feature altogether. This helps to prevent hackers from uploading scripts which might then be injected into the application.
file_uploads = 1
upload_max_filesize = 1M
If your application requires file upload capabilities, keep “upload_max_filesize” to as small of a value as possible.
upload_tmp_dir = /var/lib/php/tmp_upload
By default, temporary file uploads are placed in a directory that is writeable by all system users. The location should be switched to a more secure directory. Ensure that the new directory location is not located within the web root. If you are using a file manager such as the one included with cPanel, then an easy and secure location to create the upload directory is directly outside of the web root (i.e. the same directory that public_html is located within). Another secure location is to create the directory within the PHP directory in “/var/lib”. The path depends on the operating system, i.e. “/var/lib/php” or “/var/lib/php5”. If have open_basedir restrictions in effect, ensure that the temporary upload directory is included in the open_basedir whitelist.
Section 7: Session Security
Sessions are used to preserve information across multiple requests for individual users. The actual information is stored on the server, and a cookie (or, less securely, HTTP request data) containing a session ID is used to validate users. Sessions are used for purposes including authentication into a web application, which is one reason why its security is so important. The following settings can be updated to help reduce the risk of session interception.
session.use_strict_mode = 1
Create a new session ID if the browser sends a previously-uninitialized ID. This helps prevent an attack called session fixation.
session.cookie_httponly = 1
session.use_cookies = 1
session.use_only_cookies = 1
session.use_trans_sid = 0
Save session ID in a cookie, rather than sending it as a URL parameter. This helps keep a user’s session secure by preventing session fixation attacks.
session.name = custom_session_id
Cookies store their information in key-value format. It is advisable to update the default key name of the cookie that stores the session ID. Update “custom_session_id” with a custom value.
session.cookie_secure = 1
If your web application runs over the HTTPS protocol for security, enable this setting to force cookies containing session IDs to be accessed only over a secure connection.
session.referer_check = example.com
Check where the request came from in order to determine whether to allow access to session data. Update this setting value to your application’s domain name to help prevent session information from being accessed if a script is loaded from an external source.
session.save_path = "/var/lib/php/session"
The default session file save path is writeable by all system users. The location should be switched to a more secure directory. Ensure that the new directory location is not located within the web root. If you are using a file manager such as the one included with cPanel, then an easy location to create the session directory is directly outside of the web root (i.e. the same directory that public_html is located within). Another secure location is to create the directory within the PHP directory in “/var/lib”. The path depends on the operating system, i.e. “/var/lib/php” or “/var/lib/php5”. If have open_basedir restrictions in effect, ensure that the session save path is included in the open_basedir whitelist.
session.hash_function = sha512
SHA-512 is a more secure hashing algorithm for creating session IDs compared to the default MD5 hash function. This algorithm is available in PHP version 5.3+. If you are running a lesser version of PHP, use the SHA1 hash algorithm instead. To do so, set “session.hash_function = 1”.
session.bug_compat_42 = 0
session.bug_compat_warn = 0
Disabling these settings will ensure that session variables cannot be globally initialized, which improves security.
Disable Vulnerable Functions
disable_functions = ini_set,php_uname,getmyuid,getmypid,passthru,leak,listen,diskfreespace,tmpfile,link,ignore_user_abord,shell_exec,dl,set_time_limit,exec,system,highlight_file,source,show_source,fpaththru,virtual,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,proc_open,proc_close,proc_get_status,proc_nice,proc_terminate,phpinfo,popen,curl_exec,curl_multi_exec,parse_ini_file,allow_url_fopen,allow_url_include,pcntl_exec,chgrp,chmod,chown,lchgrp,lchown,putenv
Several PHP functions can provide open doors for web application hacks if not used carefully. For example, sending improperly validated inputs to many of these functions results in security issues. Disabling these functions altogether is a simple and effective solution to the problem. However, if your application requires any of the functions listed, remove it from the list.
soap.wsdl_cache_dir = /var/lib/php/soap_cache
As with file uploads and session data, SOAP cache data should not be stored within the default temporary directory. Set this to a more secure directory.
After you make changes to the php.ini file, you will need to restart the web server. WHM provides a button to restart the server after editing the file. If you are not using a control panel such as WHM, you will need to restart your server via the command-line. For Apache, enter the command “sudo apachectl graceful” and press Enter.
By updating these settings, your PHP environment is further along in staying protected from hack attempts. Securing your PHP environment from hackers is an important step to protect your business reputation. Keep in mind, however, that a poorly coded application is always an open door to hacks, even with a hardened PHP configuration. Start by keeping your configuration hardened, and from there always write secure application code.