用戶登錄,幾乎是所有 Web 應用所必須的環節。Web 應用通常會加入一些驗證手段,以防止攻擊者使用機器人自動登錄,如要求用戶輸入圖形驗證碼、拖動滑動條等。但是,如果驗證的邏輯僅僅在前端執行,是很容易被攻擊者繞過的。iFlow 業務安全加固平台可以為只使用前端驗證的應用打上動態虛擬補丁,使之成為需要前后端配合執行的驗證邏輯,大幅度提高攻擊者的攻擊難度。
以某個開源購物網站為例,其管理員后台登錄只使用了前端驗證。我們嘗試一下,如何在不修改網站源代碼的前提下,使用iFlow實現前后端配合身份驗證。
一、前端驗證的原始網站
原始網站設置了滑動條拖動驗證,但僅使用了前端驗證,極易被攻擊者甚至一般用戶繞過。
1.1 正常用戶訪問
網站管理員在輸入賬號和口令后,必須拖動下方的滑動條到最右端,才能點擊登錄按鈕發送登錄信息。
反映在 HTTP 協議層面,是如下交互的:
在實現上,當用戶將滑動條拖到最右端時,前端代碼將 DOM 中的一個數據元素 validate-status
的值設置為 1
。
1.2 攻擊者訪問
使用瀏覽器自帶的開發者工具 (F12) 或者使用瀏覽器自動化工具 (如 WebDriver),將數據元素 validate-status
的值直接設置為 1
。
下圖顯示的是僅使用瀏覽器自帶工具來修改元素:
如此,攻擊者無需實際拖動滑動條驗證,同樣能夠發出登錄信息。HTTP 協議層面交互如下:
二、iFlow虛擬補丁后的網站
我們在 Web 服務器前部署 iFlow 業務安全加固平台,它有能力攔截、計算和修改雙向 HTTP 報文並具備存儲能力,成為 Web 應用的虛擬補丁。本例中,iFlow 通過在前端動態插入代碼和在后端基於會話的狀態保存,使得滑動條驗證邏輯在前后端同時進行。
2.1 正常用戶訪問
iFlow 在前端的拖動滑動條前端腳本中動態插入了一段代碼,使得用戶在完成拖動滑動條時,瀏覽器自動向 iFlow 發送一條信息並被 iFlow 保存為一個標記。用戶在發送登錄信息時,iFlow 檢查該標記,對於一個正常用戶,這個標記一定是存在的,於是登錄過程正常繼續。
正常用戶的 HTTP 協議交互過程如下:
2.2 攻擊者訪問
如前所示,攻擊者強行修改前端元素,可以通過前端驗證。但當發送登錄信息而 iFlow 檢查標記時,由於攻擊者之前並未實際拖動滑動條發送標記請求,因此該標記並不存在。iFlow 可以據此判斷這是一個攻擊者在訪問,於是終止登錄過程。
攻擊者的 HTTP 協議交互過程如下:
2.3 代碼
iFlow 內置的 W2 語言是一種專門用於實現 Web 應用安全加固的類編程語言。它介於配置和通用語言之間,具備編程的基本要素和針對 HTTP 協議的特有擴展,能為業務系統編寫涉及復雜判斷和動態修改的邏輯。
考慮到安全產品的使用者通常為非程序員,他們習慣面對配置文件而非一段代碼。因此,W2 語言雖包含語言要素,仍以規則文件方式呈現,並采用可以體現層次結構和方便詞法校驗的 JSON 格式。
用 W2 語言實現上述虛擬補丁的代碼如下:
[
{
"if": [
"REQUEST_FILENAME == '/shopx/js/drag.js'"
],
"then": {
"execution": {
"directive": "alterResponseBody",
"op": "string",
"target": "function dragOk(){",
"substitute": "function dragOk(){$.get('/iflow/dragged.dummy');"
}
}
},
{
"if": [
"REQUEST_FILENAME == '/iflow/dragged.dummy'"
],
"then": {
"execution": [
"SESSION.drag_ok@60 = true"
]
}
},
{
"if": [
"REQUEST_FILENAME == '/shopx/admin.php'",
"@ARGS.s == 'login'",
"!SESSION.drag_ok"
],
"then": {
"verdict": {
"action": "deny",
"log": "Drag verifycode is not ok!"
}
}
}
]
示例代碼中有三條規則,分別作用如下——
第一條規則
當瀏覽器請求 drag.js
時,iFlow 攔截響應報文,在 dragOK()
函數中插入一個代碼片段,其作用是當用戶拖拽驗證框完成后向服務器發送一條驗證請求,即下一條規則中的 /iflow/dragged.dummy
;
第二條規則
當瀏覽器請求 /iflow/dragged.dummy
時 (用戶拖動完成后由 dragOK()
函數自動發出),iFlow 攔截此請求,將該會話 (SESSION) 存儲中的 drag_ok
標志設置為 true
;
第三條規則
當用戶點擊登錄按鈕時發出請求時,iFlow 攔截此請求,檢查會話 (SESSION) 存儲中的 drag_ok
標志是否為 true
(正常用戶操作在上一條規則中應該被設置),如果不為 true
則 iFlow 阻止該用戶的繼續操作。
注意:上述會話中的
drag_ok
標志是保存在服務器端的 iFlow 存儲中的,在瀏覽器端是看不到數據更無法進行修改的。
三、總結
iFlow 使用三條規則在不修改服務器端代碼的前提下,透明地實現了在后端執行的拖動驗證邏輯。
此外我們可以看到,iFlow 的規則是根據應用的實際情況和對安全功能的特定需求量身定制的,它不具備開箱即用的特點但卻適合構造復雜的防護邏輯。
當然,這僅是一個入門的例子,主要是為了體現防御思路和 iFlow 的能力。聰明的讀者一定會想到——攻擊者可以針對這個防御手段采取對應的攻擊方式 (如主動發出后端驗證請求),而防御者也可以將防御手段制作得更高明一些 (如 js 混淆、檢查滑動速度和時間等),這些我們在以后的例子中再慢慢展開。至少,比起原始的網站系統,現在攻擊者沒那么容易欺騙 Web 應用了。(張戈 | 天存信息)