Secure PHP Settings in Nginx Environment

Publish: 2019-04-16 | Modify: 2019-04-16

Nginx is becoming increasingly popular nowadays, and most integrated environments such as Baota panel, Oneinstack, LNMP use Nginx as the web service. Under the Nginx + PHP configuration, FPM (FastCGI Process Manager) is used to execute PHP. This article focuses on enhancing the security of PHP programs from the perspective of web service and PHP settings, regardless of the vulnerabilities caused by improper PHP programming.

PHP Security

Disable Dangerous Functions

PHP provides functions like system() that can directly execute system commands. If the program does not have strict limitations or is not written properly, it can be extremely dangerous when exploited by hackers. It is necessary to disable such dangerous functions. You need to modify php.ini and add the following content:

disable_functions = passthru,exec,system,chroot,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket,popen

Prevent Cross-Site Scripting (XSS) Attacks

Cross-Site Scripting attacks usually occur when Site A is compromised, and hackers use scripts to access Site B or other directories, potentially leading to the compromise of all websites.

The open_basedir parameter restricts PHP's ability to open files to a specified directory tree, including the file itself. When a program needs to open a file using functions like fopen() or file_get_contents(), the location of the file will be checked. If the file is outside the specified directory tree, the program will refuse to open it. There are several common methods to set open_basedir:

Setting in php.ini

You can directly modify php.ini and add:

open_basedir="specified directory"

Setting in PHP script

Limiting in the program script:

ini_set('open_basedir', 'specified directory');

Setting via .user.ini

Let's take a look at how the official documentation explains the .user.ini file:

Since PHP 5.3.0, PHP supports per-directory INI files in the style of .htaccess. These files are only processed by the CGI/FastCGI SAPI. This feature obsoletes the PECL htscanner extension. If you are using Apache, use .htaccess files with the same effect.

In addition to the main php.ini, PHP will scan for INI files in each directory, starting with the directory of the executed PHP file, and going up to the web root directory (as indicated by $_SERVER['DOCUMENT_ROOT']). If the executed PHP file is outside the web root directory, only that directory will be scanned.

Only INI settings with the modes PHP_INI_PERDIR and PHP_INI_USER can be recognized in .user.ini files.

In short, when PHP runs in CGI/FastCGI SAPI mode, it will read a configuration file called .user.ini, where we can set the open_basedir parameter to prevent cross-site scripting. Create a .user.ini file in the root directory of the site with the following content:

open_basedir=/data/wwwroot/:/tmp/:/proc/

To prevent .user.ini from being tampered with, you can set the hidden attribute for this file:

chattr +i .user.ini

Currently, it is known that Baota panel and Junge LNMP (lnmp.org) use .user.ini by default to prevent cross-site scripting. This method is very flexible and can be set individually for a specific website.

Disable PHP Execution in Certain Directories

Most PHP frameworks, such as CodeIgniter and ThinkPHP, have a single entry point. Only index.php needs to have execution permissions for the program to run normally. There is no need to grant PHP execution permission to upload directories or static file directories, as this may be exploited. Nginx can prevent the execution of PHP in certain directories using the following rule:

# Disable PHP execution in directories such as uploads, templets, and data
location ~* ^/(uploads|templets|data)/.*.(php|php5)$ {
    return 444;
}

Other Notes

The above mainly focuses on the settings of PHP itself and restrictions on Nginx. If there are any shortcomings, please let me know. This article refers to the following sources:


Comments