1、概念
SSTI是一種常見的Web安全漏洞,它允許攻擊者通過注入惡意模板代碼,使服務器在渲染模板時執行非預期的操作。
(1)渲染模版
至于什么是渲染模版:服務器端渲染模板是一種Web開發技術,它允許在服務器端動態生成HTML頁面或其他格式的輸出內容,而不是在客戶端(瀏覽器)生成。這種技術的核心是模板引擎,它允許開發者將動態內容嵌入到靜態模板中,從而生成最終的頁面
<1>模版引擎的作用
模版引擎的主要作用是將模板(一種包含占位符的靜態文件)與數據(動態內容)結合,生成最終的輸出內容。
<2>模版引擎的功能:
變量替換:將模板中的占位符替換為實際的數據。
條件語句:根據條件動態生成內容。
循環語句:根據數據集合生成重復的內容。
模版繼承:允許一個模板繼承另一個模板的結構。
而常見的模版引擎有:Django、jinja2、Twig、EJS
<3>服務器端渲染模版的工作原理
假設有一個Web應用,用戶訪問某個頁面時,服務器需要動態生成HTML內容。
服務器端渲染模板的基本工作流程為:
用戶請求頁面:用戶通過瀏覽器發送HTTP請求,請求某個頁面。
服務器接收請求:服務器接收到請求后,解析請求參數。
加載模版文件:服務器加載預定義的模板文件,模板文件中包含占位符。
數據綁定:服務器將動態數據綁定到模板中的占位符
生成最終內容:模板引擎將模板和數據結合,生成最終的HTML內容。
返回響應:服務器將生成的HTML內容返回給瀏覽器,瀏覽器渲染并顯示頁面。
<4>示例 (使用Python的Jinja2模板引擎)
假設此刻有一個簡單的web應用,使用Flask框架和Jinja2模板引擎來動態生成HTML頁面。
模版文件(template.html)
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title>
</head>
<body><h1>{{ heading }}</h1><p>{{ content }}</p>
</body>
</html>
這個模板文件中包含了三個占位符:{{title}}、{{heading}} 和 {{content}}。
假如在Jinja2模版中,我們用Python代碼這樣來渲染文件(app.py):
from flask import Flask, render_templateapp = Flask(__name__)@app.route('/')
def index():# 動態數據data = {'title': 'My Page','heading': 'Welcome to My Page','content': 'This is a dynamic content.'}# 使用render_template渲染模板return render_template('template.html', **data)if __name__ == '__main__':app.run(debug=True)
在這個代碼中:
1、render_template 函數 將模板文件? template.html? 和動態數據 data 結合起來。
2、模板引擎會將 {{title} 替換為 "My Page",? {{"heading"}}? 替換為 'Welcome to My Page' , {{'content'}} ? 替換為 'This is a dynamic content'
3、最終生成的HTML內容會發送給瀏覽器。
然后當我們訪問這個Web應用時,瀏覽器會收到以下HTML內容:
<!DOCTYPE html>
<html>
<head><title>My Page</title>
</head>
<body><h1>Welcome to My Page</h1><p>This is a dynamic content.</p>
</body>
</html>
這個過程就是服務器端渲染模板。?
(2)非預期操作
而非預期操作又指的是什么呢:別看這些詞這么高大尚,其實通俗的講就是指在軟件或系統中執行的、未被設計或預期的操作。(非預期操作)在Web安全領域,非預期操作通常是指攻擊者通過漏洞或缺陷,使應用程序執行了開發者未預期的操作.
<1>非預期操作的類型
信息泄露:攻擊者通過漏洞獲取服務器上的敏感信息,如配置文件內容、環境變量等。
代碼執行:攻擊者通過漏洞執行任意代碼,從而控制服務器。
權限提升:攻擊者通過漏洞提升系統權限,進一步控制服務器。
拒絕服務攻擊(Dos):攻擊者通過漏洞使服務器無法正常提供服務。
輸入驗證不足、錯誤的邏輯實現、配置錯誤都是非預期操作的成因。
<2>示例(還是使用Python的Jinja2模板引擎)
同樣假設我們有一個簡單的Web應用,允許用戶輸入一些內容,然后將這些內容顯示在頁面上。但是,我們沒有對用戶輸入進行過濾。
模版文件(template.html)
給一個html模版:
<!DOCTYPE html>
<html>
<head><title>User Input</title>
</head>
<body><p>You entered: {{ user_input }}</p>
</body>
</html>
Python代碼(app.py):
from flask import Flask, request, render_templateapp = Flask(__name__)@app.route('/')
def index():# 獲取用戶輸入user_input = request.args.get('input', '')# 渲染模板并顯示用戶輸入return render_template('template.html', user_input=user_input)if __name__ == '__main__':app.run(debug=True)
兩種情況:
1、正常情況
如果用戶通過URL? /?input=Hello? 訪問頁面,頁面會顯示:
<!DOCTYPE html>
<html>
<head><title>User Input</title>
</head>
<body><p>You entered: Hello</p>
</body>
</html>
2、非預期操作
如果用戶通過URL? /?inpput={{5+3}}?? 訪問頁面,Jinja2模板引擎會執行 5+3 ,頁面會顯示:
<!DOCTYPE html>
<html>
<head><title>User Input</title>
</head>
<body><p>You entered: 8</p>
</body>
</html>
這是開發者未預期的操作,因為用戶輸入的模板代碼被模板引擎執行了,所以叫非預期操作。
那么要是再嚴重一點:
如果用戶通過URL? /?input={{config.items}}? 訪問頁面,Jinja2模板引擎會執行? config.items() ,可能會返回應用程序的配置信息,導致信息泄露。
2、SSTi的原理
之前說模板引擎允許開發者將動態內容嵌入到靜態模板中,以便生成最終的HTML頁面或其他格式的輸出。but,如果沒有對用戶輸入進行嚴格的驗證和過濾,攻擊者可以注入惡意的模板代碼,從而在服務器端執行一系列操作(非預期,不可知)。
3、SSTI的危害
所以總的來說還是有三個危害:
信息泄露;
代碼執行;
權限提升
4、分類
SSTI 漏洞主要分為兩類:簡單的模板注入和復雜的模板注入。
(1)簡單模版注入
攻擊者直接注入模板代碼,使服務器在渲染模板時執行惡意操作
(2)復雜模版注入
攻擊者通過構造復雜的模板代碼,繞過應用程序的輸入驗證和過濾機制。
5、例題
NSSCTF
【HDCTF 2023】SearchMeaster
啟動
你可以使用POST請求給我發送DATA
也不知道發送什么,注意到題目search,用dirsearch掃描一下目錄
結果掃了一下又沒掃出來
那就還是用nikto掃一下ip
可以看到Target IP 為1.14.71.254
結果還是沒連上
后面在端口前面加冒號:就連上了(我也納悶,在kali里有時候接端口是空格,冒號不行,有時候又得冒號,但物理機url包是冒號的)
可以看到有一個composer.json可用
訪問一下
直接得到提示是smart模版
說明存在ssti模版注入
?返回原頁面傳? data={? ,報錯,證明存在RCE漏洞(報錯表明模板引擎嘗試解析和執行了我傳遞的模板代碼。)因為之前說過RCE漏洞是應用調用代碼執行函數或系統命令執行函數,導致遠程代碼執行或系統命令執行 ,這里典型的是嘗試執行了命令然后無果
這樣一來就可以利用SSTI模版注入結合RCE漏洞執行命令來達到目的了
想確認smart模版的話試試{4*4}是否能回顯16
可以看到有16,無疑存在smart模版 (沒被騙haha)
那直接構造payload就可以了
data={if system('ls /f*')}{/if}
smart模版引擎的條件語法
{if} {/if} 標簽
{if}:開始條件判斷;
{/if}:結束條件判斷
在該模版引擎中執行 system函數 system()不用說了
'ls /f*':要執行的系統命令,用于列出? /f* (f字符開頭,用于提高查找flag的效率)目錄下的文件
?執行后得到flag路徑
繼續替換system命令即可
data={if system('cat /flag_13_searchmaster')}{/if}
get flag