摘要:Jinja2 模板的應(yīng)用使得網(wǎng)站代碼結(jié)構(gòu)清晰,耦合度降低,開發(fā)、維護(hù)、更新都更容易。該文通過采用不同類型的傳參對(duì)Jinja2 模板的安全性進(jìn)行了測(cè)試,并在測(cè)試中發(fā)現(xiàn)了一些安全性問題,通過實(shí)踐,給出了相應(yīng)的安全防范措施,供同行人員參考。
關(guān)鍵詞:Flask;安全性;Jinja2模板
中圖分類號(hào):TP311? ? ?文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1009-3044(2022)27-0073-03
開放科學(xué)(資源服務(wù))標(biāo)識(shí)碼(OSID):
本文所涉及的Jinja2模板本質(zhì)即Python腳本文件,在大型項(xiàng)目中,視圖函數(shù)把業(yè)務(wù)邏輯和展現(xiàn)內(nèi)容集成在一起,使得代碼更為復(fù)雜,維護(hù)成本也更高。使用模板讓視圖函數(shù)只進(jìn)行業(yè)務(wù)邏輯方面的業(yè)務(wù)邏輯和數(shù)據(jù)處理,視圖函數(shù)的處理后的數(shù)據(jù)結(jié)果發(fā)送到模板進(jìn)行展示,讓代碼結(jié)構(gòu)清晰,耦合度大幅降低,開發(fā)、維護(hù)、更新等成本都大幅降低[1]。
1 Jinja2模板簡(jiǎn)介
該P(yáng)ython模板文件中包含響應(yīng)文本,用占位符“{{ }}”標(biāo)志動(dòng)態(tài)變量位置,模板引擎需要從腳本中標(biāo)志的動(dòng)態(tài)變量位置獲取外部某個(gè)具體的值。使用實(shí)際的值替換變量占位符的位置,得到最終的字符串,該工作過程為“渲染”。本文講解的Jinja2模板就是Flask用來進(jìn)行渲染的模板引擎[2]。
Jinja2模板是一個(gè)廣泛應(yīng)用的Python模板引擎,該模板由Python語言實(shí)現(xiàn),其設(shè)計(jì)思路源于Django的模板引擎,并擴(kuò)展了Django模板語法和其一系列強(qiáng)大的功能,是Flask框架的內(nèi)置模板,F(xiàn)lask框架下的render template函數(shù)封裝了Jinja2模板引擎,該函數(shù)的第一個(gè)參數(shù)是文件名(如index.html),后面的參數(shù)都是鍵值對(duì),表示模板中變量對(duì)應(yīng)的真實(shí)值,使用占位符{{}}來表示變量,這里{{}}成為變量代碼塊,render template函數(shù)根據(jù)后面?zhèn)魅氲膮?shù),對(duì)index.html進(jìn)行渲染[3]。
2 Jinja2模板安全性測(cè)試準(zhǔn)備
2.1測(cè)試環(huán)境搭建
測(cè)試系統(tǒng)是安全性檢測(cè)的前置條件,測(cè)試環(huán)境搭建本著真實(shí)、無毒、獨(dú)立、可復(fù)用、前沿、干凈、簡(jiǎn)潔、實(shí)用等原則[4],本文Jinja2模板安全性測(cè)試環(huán)境搭建操作系統(tǒng)采用Windows10專業(yè)版,使用Visual Studio Code編程軟件 ,使用Python版本為Python3.9的編程語言,安裝flask框架(內(nèi)含jinja2模板)。
項(xiàng)目部分基本源代碼如圖1所示。
2.2安全性測(cè)試方案
訪問本地環(huán)境:http://127.0.0.1:5000/ ,在URL中使用GET方式傳參,“?name=xiaoyi”,頁面得到正確的預(yù)期響應(yīng),回顯為“hello,xiaoyi”,整個(gè)請(qǐng)求與響應(yīng)過程分析如圖2。
(1)用戶通過瀏覽器提交請(qǐng)求給服務(wù)器,Web服務(wù)器將請(qǐng)求解包后發(fā)給App;
(2)App接收到請(qǐng)求后,通過指定route找到給定的視圖函數(shù),然后視圖函數(shù)處理、渲染后,返回一個(gè)響應(yīng)response;
(3)App將響應(yīng)返回給服務(wù)器的Web服務(wù);
(4)服務(wù)器將響應(yīng)返回給瀏覽器,瀏覽器展示出來給用戶瀏覽。
3 Jinja2模板安全性測(cè)試
3.1非預(yù)期傳參測(cè)試
功能性測(cè)試是系統(tǒng)處理了正常用戶請(qǐng)求的過程,下面輸入非預(yù)期的代碼進(jìn)行測(cè)試。輸入內(nèi)容為:{{7*9}},傳遞到參數(shù)進(jìn)行執(zhí)行,結(jié)果如圖3所示:
此時(shí)的后臺(tái)代碼執(zhí)行了7*9,得到運(yùn)算結(jié)果63,所以此時(shí)這里就存在安全性問題。接下來進(jìn)一步構(gòu)造惡意代碼嘗試進(jìn)行遠(yuǎn)程命令執(zhí)行。
3.2構(gòu)造代碼實(shí)現(xiàn)遠(yuǎn)程RCE原理
在Python中一切皆是對(duì)象,因此很多的基礎(chǔ)類都是object類的子類中,想要調(diào)用這些類中的方法就需要先通過object類,這樣就可以利用子類(這里以str類為例子)來調(diào)用父類object類,再利用object類調(diào)用其子類os類,從而實(shí)現(xiàn)遠(yuǎn)程RCE(遠(yuǎn)程命令執(zhí)行)[5],整個(gè)過程如圖4所示。
3.3 構(gòu)造代碼實(shí)現(xiàn)遠(yuǎn)程RCE
構(gòu)造惡意碼的具體步驟具體如下:
就是給定一個(gè)變量,這個(gè)變量可以是int型、str型、bool型、數(shù)組、元組、字典、集合等可以識(shí)別類型,也可是未定義的類型,從這個(gè)變量通過.__class__獲取其參數(shù)類型,如:
輸入:'aa'.__class__ ,返回為class
再通過__base__返回它的基類(也稱父類),如:
輸入:'aa'.__class__.__base__ ,返回為class
再通過__subclasses__()查詢object類中所有子類,并查詢到想要用的類的具體位置,本文中以調(diào)用os._wrap_close子類為例,輸入:'aa'.__class__.__base__.__subclasses__()[134],結(jié)果如圖5所示。
在Python中所有的類都要經(jīng)過初始化才能使用,也就是默認(rèn)調(diào)用__init__,因此我們?cè)谑褂妙愔耙惨{(diào)用__init__,通過使用__globals__讀出當(dāng)前的環(huán)境變量,輸入:{{'aa'.__class__.__base__.__subclasses__()[134].__init__.__globals__}},得到結(jié)果如圖6所示。
顯示當(dāng)前位于模塊os.py中,在該模塊中,找到popen方法,進(jìn)行系統(tǒng)命令執(zhí)行,輸入{{'aa'.__class__.__base__.__subclasses__()[134].__init__.__globals__['popen']('dir').read()}},實(shí)現(xiàn)了遠(yuǎn)程命令執(zhí)行,結(jié)果如圖8所示:
4 Jinja2模板安全防護(hù)建議
4.1防護(hù)思路與方法
針對(duì)上面漏洞的防護(hù),思路和其他的注入防御類似,這里對(duì)特殊字符自定義黑名單數(shù)組blacklist,在獲取用戶輸入的內(nèi)容后,檢測(cè)輸入內(nèi)容是否為字符串,再將用戶輸入的字符串中的字符逐一與blacklist數(shù)組中每一個(gè)值比較,如若檢測(cè)到用戶輸入中存在敏感字符,則提醒用戶規(guī)范輸入,結(jié)束程序,反之,如果安全則傳入模板,進(jìn)行渲染,整體應(yīng)用到Python代碼中,實(shí)現(xiàn)代碼具體如圖8所示:
4.2 防護(hù)代碼安全性測(cè)試
對(duì)上面防護(hù)后代碼進(jìn)行安全性測(cè)試,在前端瀏覽器傳入“{}”,返回響應(yīng)如圖9所示,整體測(cè)試結(jié)果如表1。
根據(jù)響應(yīng)結(jié)果分析,用戶輸入的特殊符號(hào)被檢測(cè)到存在敏感字符,給用戶友好提示,并終止程序運(yùn)行,用戶安全輸入信息,經(jīng)過模板正常渲染回顯,功能不受影響,從而確保了服務(wù)器及數(shù)據(jù)的安全,是有效的防護(hù)措施。
5 總結(jié)
本文通過環(huán)境搭建、傳參測(cè)試,發(fā)現(xiàn)了Jinja2模板存在的安全性問題,主要是由于開發(fā)人員信任了用戶的輸入,未對(duì)用戶輸入進(jìn)行審查而導(dǎo)致的,引發(fā)了用戶可以通過輸入惡意代碼實(shí)現(xiàn)遠(yuǎn)程RCE,讀取服務(wù)器內(nèi)重要信息,甚至獲取到服務(wù)器的權(quán)限。作者對(duì)存在的問題進(jìn)行了系統(tǒng)地分析,制訂了問題解決方案,設(shè)計(jì)了安全編碼。經(jīng)過測(cè)試,程序功能正常,能有效防護(hù)用戶的惡意輸入,突顯了安全編碼的重要性。
參考文獻(xiàn):
[1] 劉丹,李志軍,朱書村.基于云端服務(wù)檢測(cè)設(shè)備的虛擬控制面板開發(fā)[J].吉林大學(xué)學(xué)報(bào)(信息科學(xué)版),2021,39(4):463-469.
[2] 任丹,侯英姿,王方雄,等.基于Flask和Vue的AIS數(shù)據(jù)分析系統(tǒng)設(shè)計(jì)與開發(fā)[J].軟件,2019,40(10):111-114,120.
[3] 曾思亮.基于Flask框架的微博用戶分類及推薦系統(tǒng)的實(shí)現(xiàn)[D].廈門:廈門大學(xué),2017.
[4] 石春宏.Addslashes函數(shù)安全性分析[J].電腦知識(shí)與技術(shù),2018,14(33):46,54.
[5] 石春宏.淺議ARP攻擊及其防御[J].電腦知識(shí)與技術(shù),2016,12(30):26-27.
【通聯(lián)編輯:梁書】