HFCTF2021Quals-Unsetme
知识点概要:命令执行
首页
源码逻辑分析:
- 引入base.php启动框架,并将框架实例赋值给$f3。
- 设置框架的DEBUG模式为启用。
- 检查PCRE(Perl兼容正则表达式)的版本是否低于8.0,如果低于则抛出错误。
- 使用highlight_file()函数高亮显示当前文件内容。
- 获取GET参数a的值,赋值给
$a
。 - 使用unset()删除框架实例
$f3
上的属性$a
。 - 运行框架。
下面还有三处报错,涉及两个文件:index.php和base.php,应该是一条控制流
FatFree框架:https://github.com/bcosca/fatfree
本地调试
1.下载官方源码(笔者调试版本是fatfree-3.7.3)
2.在源码根目录(即index.php同级目录),新建一个test.php,把题目源码复制进去
3.开启调试环境,浏览器访问test.php
因为可控参数为GET参数a
,所以调试的时候重点关注此参数的流向
(1)什么参数都不传递的情况下
控制流会从test.php的12行unset()函数进入base.php的__unset()
魔术方法
然后进入offsetunset()方法
进入clear()
后,会一路执行到530行
执行eval('unset('.$val.');');
时,跳转到2337行,执行完2338行,web端返回如题目首页的错误
(2)GET传参?a=1
时,前面的控制流路线和无参时是一样的,只不过执行eval('unset('.$val.');');
时,会跳转到如下位置
从上述分析可见,eval()函数是危险函数,又因为变量$val
是@hive
拼接$key
经过compile()方法处理得到,$key
是从GET参数a
一路传递过来的,可控,所以就有了执行命令的机会。关键在于compile()做了什么处理,跟踪关键代码如下
这段代码功能相当于把@hive string $a
替换成$hive['string']
,又由于$val
变量赋值的最外层正则会将$hive
替换为$this->hive
,所以相当于传进GET参数a=string
,得到$var
=$this->hive['string']
可以在eval()之前添加echo调试一下:
echo '<br>'.$val.'<br>';
echo 'unset('.$val.');';
传参?a=test
,结果如下
传参?a=test%0a);phpinfo(
,结果如下
所以,读flag可用如下payload
?a=test%0a);echo file_get_contents(%27/flag%27
?a=test%0a);readfile(%27/flag%27
?a=test%0a);system(%27cat%20/flag%27