Home > Article > Backend Development > Possible attacks and solutions when installing PHP in CGI mode
If you don’t want to embed PHP into server-side software (such as Apache) and install it as a module, you can choose to install it in CGI mode. Or use PHP with different CGI wrappers to create secure chroot and setuid environments for your code. This installation method usually installs the PHP executable file into the cgi-bin directory of the web server. Although PHP can be used as a standalone interpreter, its design makes it prevent the following types of attacks:
Accessing system files: http://my.host/cgi-bin/php?/etc/passwd in URL requests The information after the question mark (?) will be passed to the CGI interface as a parameter of the named line. Other interpreters will open and execute the file specified by the first argument on the command line. However, when the PHP interpreter installed in CGI mode is called, it refuses to interpret these parameters.
Access any directory on the server: http://my.host/cgi-bin/php/secret/doc.html In the above case, the URL information /secret/doc.html behind the directory where the PHP interpreter is located will Will be routinely passed to the CGI program and interpreted. Usually some web server will redirect it to a page such as http://my.host/secret/script.php. If this is the case, some servers will check the user's permission to access the /secret directory before creating a redirect to the page at http://my.host/cgi-bin/php/secret/script.php . Unfortunately, many servers do not check the user's permission to access /secret/script.php, but only check the permission of /cgi-bin/php, so that any user who can access /cgi-bin/php can access the web directory of any file. In PHP, the compile-time configuration option --enable-force-cgi-redirect and the run-time configuration instructions doc_root and user_dir can add restrictions to files and directories on the server to prevent such attacks. The settings of each option will be explained in detail below.
Scenario 1: Only run public files
If everything in the web server is restricted by password or IP address, there is no need to set these options. If the web server does not support redirection, or the web server cannot communicate with PHP to make access requests more secure, you can specify the --enable-force-cgi-redirect option in the configure script. In addition, make sure that the PHP program does not rely on other methods of calling, such as direct access to http://my.host/cgi-bin/php/dir/script.php or redirection to access http://my .host/dir/script.php.
In Apache, redirection can be set up using AddHandler and Action statements.
Case 2: Use the --enable-force-cgi-redirect option
This compilation option prevents anyone from directly accessing URLs such as http://my.host/cgi-bin/php/secretdir/script.php Call PHP. PHP in this mode will only parse URLs that have passed the web server's redirect rules.
Usually redirection settings in Apache can be completed with the following command:
Action php-script /cgi-bin/php AddHandler php-script .php
This option has only been tested under Apache and relies on the non-standard CGI environment variable REDIRECT_STATUS set by Apache in the redirection operation. If the web server does not support any way to determine whether a request is direct or redirected, this option cannot be used and other methods should be used.
Scenario 3: Setting doc_root or user_dir
Including dynamic content such as scripts and executable programs in the main document directory of a web server is sometimes considered an unsafe practice. If the script fails to execute due to a configuration error and is displayed as a normal HTML document, it may lead to the leakage of intellectual property or password information. Therefore, many system administrators will specially set up a directory that can only be accessed through PHP CGI, so that the contents in the directory will only be parsed and not displayed as they are.
For the above-mentioned situation where it is impossible to determine whether to redirect, it is necessary to create a doc_root directory dedicated to scripts outside the main document directory.
You can define the PHP script home directory through doc_root in the configuration file or by setting the environment variable PHP_DOCUMENT_ROOT. If this option is set, PHP will only interpret files in the doc_root directory and ensure that scripts outside the directory will not be executed by the PHP interpreter (except user_dir mentioned below).
Another available option is user_dir. When user_dir is not set, doc_root is the only option that controls where files are opened. When accessing a URL such as http://my.host/~user/doc.php, the file in the user's home directory will not be opened, but only ~user/doc.php in the doc_root directory will be executed (this subdirectory ends with [ ~] as the beginning).
If user_dir is set, such as public_php, then a request like http://my.host/~user/doc.php will execute the doc.php file in the public_php subdirectory under the user's home directory. Assuming that the absolute path of the user's home directory is /home/user, the executed file will be /home/user/public_php/doc.php.
user_dir 的设置与 doc_root 无关,所以可以分别控制 PHP 脚本的主目录和用户目录。
情形四:PHP 解释器放在 web 目录以外
一个非常安全的做法就是把 PHP 解释器放在 web 目录外的地方,比如说 /usr/local/bin。这样做唯一不便的地方就是必须在每一个包含 PHP 代码的文件的第一行加入如下语句:
#!/usr/local/bin/php
还要将这些文件的属性改成可执行。也就是说,要像处理用 Perl 或 sh 或其它任何脚本语言写的 CGI 脚本一样,使用以 #! 开头的 shell-escape 机制来启动它们。
在这种情况下,要使 PHP 能正确处理 PATH_INFO 和 PATH_TRANSLATED 等变量的话,在编译 PHP 解释器时必须加入 --enable-discard-path 参数。