[web] - url路径不一致
程序员文章站
2022-05-15 21:30:01
...
Flag:
首先根据老师上课的提示尝试路径不一致漏洞:
- 查看源码,并在本地将源码对于检测关键字符串的回馈信息进行调整:
<?php
require_once('core.php');
function check($path) {
// $path = clean($path);
if (strpos($path, 'core') !== false) {
return "core";
}
if (strpos($path, '/var/www/html/') !== 0) {
return "www";
}
if (strpos($path, '..') !== false) {
return "..";
}
return false;
}
if (isset($_GET['path'])) {
$path = $_GET['path'];
if (check($path)) {
echo check($path);
} else {
if ( file_exists($path) &&(strpos($path, 'flag') !== false)) {
echo "No flag read";
} else {
echo file_get_contents($path);
}
}
} else {
highlight_file(__file__);
}
?>
- 根据check函数的约束规则,要求必须以
/var/www/html
开头且path参数里面不能出现core
和..
- 御剑扫描后台只发现了一个core.php,源代码中发现导入了core.php函数并且使用了其中的clean函数。
- 试着在url中输入
/var/www/html///../index.php
和/var/www/html/index.php
的结果一样,而没有提示检测到..
因此猜测clean函数里面对路径进行了类似spring的解读,也就是将$path
中的//
看成是一个空目录,与相邻的/../
目录合并抵销。顺着这个猜想尝试进入/var/www/html/
的逐层上找查询flag在哪级目录中:
发现是在根目录中,然后致力于绕过下面的if ( file_exists($path) &&(strpos($path, 'flag') !== false))
分支进入else
从而读取flag
这个if分支由两个条件相与共同限制,只要破坏其中一个就可以,基于从小对于file_exists的刻板印象选择先从后面的strpos突破,试了编码、字符串拼接、数据类型转换等方法都无果然后想到和上文的strpos($path,'core')
是相同的限制,如果这里能突破strpos上文就能直接看到core.php的源码了,因为上面就放弃了所以转而去研究有没有可能file_exists
存在和file_get_content
之间的差别,使得能够file_exists
返回false而file_get_content
成功读到内容。
这时经同学提示看到了两篇文章:
https://www.techug.com/post/php-file_exists-problem.html
https://www.freebuf.com/articles/web/53656.html
其中有解释:
意味着在中间目录中插入/anystring/…/会不经检验的直接抵消。
试了一下在原有url后面追加/6666/../flag
变成path=/var/www/html///..///..///../6666/../flag
得出报告一开头出现的flag。
Note:
然而仔细想其实这两篇文章跟我们这个题目的逻辑实际是相互矛盾的:
上文两篇博客的目的都是为了在中间加入命令行而又能浑水摸鱼通过file_exists函数的检验,使用eval执行命令,而我们这个题则是希望从file_exists
这儿卡住目录转而进入file_ge_contents
。
网上的博客file_exists说的是会把url中/anystring/和/…/这一对不加检查直接抵销掉,但是这个题里面从结果能绕过if分支来看是他需要就检查出来了每一小段/anystring/目录是否存在,而get_content那个函数只检查最终文件是否存在所以把/ anystring/和/…/抵消了读出文件,这样来看这个题中的file_exist和php原版的file_exists检测规则是不一样的。有理由怀疑core.php中可能重写了一个file_exists,但是core.php的源码又尚未获得所以可以说这个题是误打误撞了。