Home  >  Article  >  Backend Development  >  A brief analysis of the security risks of open_basedir in PHP_PHP Tutorial

A brief analysis of the security risks of open_basedir in PHP_PHP Tutorial

WBOY
WBOYOriginal
2016-07-13 10:47:591267browse

In php, open_basedir is a rarely used function in php, but the open_basedir function may accidentally allow someone to access your server. Let’s take a look at how magical open_basedir is.

Let’s first look at a piece of code where we don’t consider open_basedir security issues

I wrote require_once ‘../Zend/Loader.php’ in php; Error:
Warning: require_once() [function.require-once]: open_basedir restriction in effect. File(../Zend/Loader.php) is not within the allowed path(s): (D:/phpnow/vhosts/zf.com ;C:/Windows/Temp;) in D:/phpnow/vhosts/zf.com/index.php on line 6

Warning: require_once(../Zend/Loader.php) [function.require-once]: failed to open stream: Operation not permitted in D:/phpnow/vhosts/zf.com/index.php on line 6

Fatal error: require_once() [function.require]: Failed opening required '../Zend/Loader.php' (include_path='D:/phpnow/vhosts/zf.comZend;.;C: /php5/pear') in D:/phpnow/vhosts/zf.com/index.php on line 6 Literal analysis is restricted by open_basedir, resulting in Operation not permitted.


Open php.ini and jump to the relevant settings section of open_basedir:

; open_basedir, if set, limits all file operations to the defined directory
; and below. This directive makes most sense if used in a per-directory
; or per-virtualhost web server configuration file. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.

;open_basedir =If open_basedir is set, all files that can be operated can only be limited to the directory specified by open_basedir. This command is quite useful in a virtual host. This command is not affected whether safe mode is turned on or not. It seems that php.ini does not set open_basedir. Open the apache virtual host configuration file:

The code is as follows Copy code
 代码如下 复制代码


   
        Options -Indexes FollowSymLinks
   

    ServerAdmin admin@zf.com
    DocumentRoot "../vhosts/zf.com"
    ServerName zf.com:80
    ServerAlias *.zf.com
    ErrorLog logs/zf.com-error_log
    php_admin_value open_basedir "D:/phpnow/vhosts/zf.com;C:/Windows/Temp;"

Options -Indexes FollowSymLinks

ServerAdmin admin@zf.com

DocumentRoot "../vhosts/zf.com"

ServerName zf.com:80

ServerAlias ​​*.zf.com

ErrorLog logs/zf.com-error_log
 代码如下 复制代码
$file = $_GET['file'];
preg_match("/^img/", $file) or die('error_file');
$file='/home/www/upload/'.$file;
file_exists($file) or die('no_such_file');
$f = fopen("$file", 'r');
$jpeg = fread($f, filesize("$file"));
fclose($f);
Header("Content-type: image/jpeg");
Header("Content-disposition: inline; filename=test.jpg");
echo $jpeg;
?>
php_admin_value open_basedir "D:/phpnow/vhosts/zf.com;C:/Windows/Temp;"
The php_admin_value open_basedir inside limits the operating directory. This is a local test. I don’t consider security factors. I just delete php_admin_value open_basedir “D:/phpnow/vhosts/zf.com;C:/Windows/Temp;” and restart apache. If you finish using the above, you can delete the server files at will, but fortunately, the current security configuration of the PHP site is basically open_basedir+safemode, which is indeed invincible and safe, even in an environment where permissions are not well set. , this configuration is quite safe, of course, without considering some situations that can be bypassed. This article discusses two potential security risks (encountered in reality) that may be caused by turning on open_basedir. One may be a small bug in PHP, and the other may be caused by improper configuration. 1. When processing file paths in open_basedir, the existence of directories is not strictly considered, which will lead to the bypass of local inclusion or local file reading. Look at an example of arbitrary reading of local files:
The code is as follows Copy code
$file = $_GET['file'];<🎜> preg_match("/^img/", $file) or die('error_file');<🎜> $file='/home/www/upload/'.$file;<🎜> file_exists($file) or die('no_such_file');<🎜> $f = fopen("$file", 'r');<🎜> $jpeg = fread($f, filesize("$file"));<🎜> fclose($f);<🎜> Header("Content-type: image/jpeg");<🎜> Header("Content-disposition: inline; filename=test.jpg");<🎜> echo $jpeg;<🎜> ?>

Although the file can be submitted arbitrarily, the prefix is ​​restricted to img. If we want to read the file out of the directory, for example, to read config.php in the root directory of the website, we have to submit?file=img/../ ../config.php, but there is a restriction here, that is, the img folder does not exist in the upload directory. In the Windows file system, the system will not consider whether the directory exists, and will directly jump to the directory, causing a vulnerability; However, the Linux file system is very strict. It will carefully determine whether each directory exists. For example, since img does not exist here, it will directly report an error when it jumps out to read the file. Look at the following diagram:


Let’s look at a similar example of local inclusion:

The code is as follows Copy code
代码如下 复制代码
include "aaa".$_GET['lang'].".php";
?>
include "aaa".$_GET['lang'].".php";

?>

Due to the limitations of the Linux file system, we cannot use side comments to include files under tmp.

 代码如下 复制代码

……
/* normalize and expand path */
if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {
return -1;
}

path_len = strlen(resolved_name);
memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
……

The rigorous considerations of Linux are obviously not deeply understood in PHP. When open_basedir is turned on, PHP processes the incoming file path to obtain the real path, and then compares it with the path set in open_basedir:

The code is as follows Copy code
……

/* normalize and expand path */

if (expand_filepath(path, resolved_name TSRMLS_CC) == NULL) {

return -1;

}

path_len = strlen(resolved_name);

memcpy(path_tmp, resolved_name, path_len + 1); /* safe */

……
 代码如下 复制代码

……
/* Resolve open_basedir to resolved_basedir */
if (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL) {
/* Handler for basedirs that end with a / */
resolved_basedir_len = strlen(resolved_basedir);
if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) {
if (resolved_basedir[resolved_basedir_len - 1] != PHP_DIR_SEPARATOR) {
resolved_basedir[resolved_basedir_len] = PHP_DIR_SEPARATOR;
resolved_basedir[++resolved_basedir_len] = '/0';
}
} else {
resolved_basedir[resolved_basedir_len++] = PHP_DIR_SEPARATOR;
resolved_basedir[resolved_basedir_len] = '/0';
}
……

But PHP ignores checking whether the path exists during processing, so when open_basedir is turned on, in the above example of file reading, we can use ?file=img/../../config.php to directly After reading, the submitted path has been processed to /home/www/config.php, so there is no reading problem. The problem was caused by a bypass situation during the penetration test, which led to doubts. After analyzing the environment differences, xi4oyu Niu pointed out that it might be a problem with open_basedir. After testing, it was concluded that this was a small bug in PHP, but it is very important. May cause safety hazards. 2. Improper configuration of the open_basedir value may lead to directory spanning. Many administrators know how to set open_basedir, but directory spanning problems may occur when the configuration is improper. Incorrect configuration: /tmp:/home/www, correct configuration: /tmp/:/home/www/
The code is as follows Copy code
…… /* Resolve open_basedir to resolved_basedir */ if (expand_filepath(local_open_basedir, resolved_basedir TSRMLS_CC) != NULL) { /* Handler for basedirs that end with a / */ resolved_basedir_len = strlen(resolved_basedir); if (basedir[strlen(basedir) - 1] == PHP_DIR_SEPARATOR) { if (resolved_basedir[resolved_basedir_len - 1] != PHP_DIR_SEPARATOR) { resolved_basedir[resolved_basedir_len] = PHP_DIR_SEPARATOR; resolved_basedir[++resolved_basedir_len] = '/0'; } } else { resolved_basedir[resolved_basedir_len++] = PHP_DIR_SEPARATOR; resolved_basedir[resolved_basedir_len] = '/0'; } ……

php considers the path ending with /, but if there is no /, it will be directly brought into the following comparison.

So, when a new website is /home/wwwoldjun/ (open_basedir has been set separately), if the configuration is wrong, you can jump from the /home/www/ directory to the /home/wwwoldjun/ directory.

As an example of penetration, an IDC provider allocates space /home/wwwroot/userxxx/, /home/wwwroot/useryyy/... when renting a virtual host, and open_basedir is misconfigured like this: /tmp: /home/wwwroot/userxxx, /tmp:/home/wwwroot/useryyy. If we want to easily penetrate the userxxx site through configuration errors, what should we do?


The special value . specifies that the script's working directory will be used as the base directory. But this is somewhat dangerous, because the script's working directory can be easily changed by chdir().

In the httpd.conf file, open_basedir can be turned off like any other configuration option using the "php_admin_value open_basedir none" method (such as in some virtual hosts).

In Windows, separate directories with semicolons. Use colons to separate directories on any other system. As an Apache module, the open_basedir path in the parent directory is automatically inherited.

The restrictions specified with open_basedir are actually prefixes, not directory names. That is to say "open_basedir = /dir/incl" will also allow access to "/dir/include" and "/dir/incls" if they exist. If you want to restrict access to only the specified directory, end the pathname with a slash. For example: "open_basedir = /dir/incl/".

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/632831.htmlTechArticleIn php, open_basedir is a rarely used function in php, but the open_basedir function accidentally gives Someone has entered your server, let’s see how amazing open_basedir is...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn