WEB安全新玩法 [2] 防范前端驗證繞過


用戶登錄,幾乎是所有 Web 應用所必須的環節。Web 應用通常會加入一些驗證手段,以防止攻擊者使用機器人自動登錄,如要求用戶輸入圖形驗證碼、拖動滑動條等。但是,如果驗證的邏輯僅僅在前端執行,是很容易被攻擊者繞過的。iFlow 業務安全加固平台可以為只使用前端驗證的應用打上動態虛擬補丁,使之成為需要前后端配合執行的驗證邏輯,大幅度提高攻擊者的攻擊難度。


以某個開源購物網站為例,其管理員后台登錄只使用了前端驗證。我們嘗試一下,如何在不修改網站源代碼的前提下,使用iFlow實現前后端配合身份驗證。

一、前端驗證的原始網站

原始網站設置了滑動條拖動驗證,但僅使用了前端驗證,極易被攻擊者甚至一般用戶繞過。

1.1 正常用戶訪問

網站管理員在輸入賬號口令后,必須拖動下方的滑動條到最右端,才能點擊登錄按鈕發送登錄信息。

圖1

反映在 HTTP 協議層面,是如下交互的:

sequenceDiagram participant 正常用戶 participant 瀏覽器 participant Web服務器 正常用戶->>瀏覽器: 地址欄輸入:/shopx/admin.php 瀏覽器->>Web服務器: 請求:/shopx/admin.php Web服務器->>瀏覽器: 返回:登錄頁面 瀏覽器->>Web服務器: 請求:/shopx/js/drag.js Web服務器->>瀏覽器: 返回:drag.js 瀏覽器->>正常用戶: 顯示:登錄頁面 正常用戶->>瀏覽器: 填寫賬號口令 正常用戶->>瀏覽器: 拖動滑動條 Note over 瀏覽器: 設置前端元素 正常用戶->>瀏覽器: 點擊登錄按鈕 Note over 瀏覽器: 前端元素驗證通過 瀏覽器->>Web服務器: 發送:登錄信息 Web服務器->>瀏覽器: 返回:登錄結果頁面 瀏覽器->>正常用戶: 顯示:登錄結果頁面

在實現上,當用戶將滑動條拖到最右端時,前端代碼將 DOM 中的一個數據元素 validate-status 的值設置為 1

1.2 攻擊者訪問

使用瀏覽器自帶的開發者工具 (F12) 或者使用瀏覽器自動化工具 (如 WebDriver),將數據元素 validate-status 的值直接設置為 1

下圖顯示的是僅使用瀏覽器自帶工具來修改元素:

圖2

如此,攻擊者無需實際拖動滑動條驗證,同樣能夠發出登錄信息。HTTP 協議層面交互如下:

sequenceDiagram participant 攻擊者 participant 瀏覽器 participant Web服務器 攻擊者->>瀏覽器: 地址欄輸入:/shopx/admin.php 瀏覽器->>Web服務器: 請求:/shopx/admin.php Web服務器->>瀏覽器: 返回:登錄頁面 瀏覽器->>Web服務器: 請求:/shopx/js/drag.js Web服務器->>瀏覽器: 返回:drag.js 瀏覽器->>攻擊者: 顯示:登錄頁面 攻擊者->>瀏覽器: 填寫賬號口令 rect rgb(250, 128, 128) 攻擊者->>瀏覽器: 【自行修改前端元素】 end 攻擊者->>瀏覽器: 點擊登錄按鈕 Note over 瀏覽器: 前端元素驗證通過 瀏覽器->>Web服務器: 發送:登錄信息 Web服務器->>瀏覽器: 返回:登錄結果頁面 瀏覽器->>攻擊者: 顯示:登錄結果頁面

二、iFlow虛擬補丁后的網站

我們在 Web 服務器前部署 iFlow 業務安全加固平台,它有能力攔截、計算和修改雙向 HTTP 報文並具備存儲能力,成為 Web 應用的虛擬補丁。本例中,iFlow 通過在前端動態插入代碼和在后端基於會話的狀態保存,使得滑動條驗證邏輯在前后端同時進行。

2.1 正常用戶訪問

iFlow 在前端的拖動滑動條前端腳本中動態插入了一段代碼,使得用戶在完成拖動滑動條時,瀏覽器自動向 iFlow 發送一條信息並被 iFlow 保存為一個標記。用戶在發送登錄信息時,iFlow 檢查該標記,對於一個正常用戶,這個標記一定是存在的,於是登錄過程正常繼續。

正常用戶的 HTTP 協議交互過程如下:

sequenceDiagram participant 正常用戶 participant 瀏覽器 participant iFlow participant Web服務器 正常用戶->>瀏覽器: 地址欄輸入:/shopx/admin.php 瀏覽器->>Web服務器: 請求:/shopx/admin.php Web服務器->>瀏覽器: 返回:登錄頁面 瀏覽器->>Web服務器: 請求:/shopx/js/drag.js Web服務器->>iFlow: 返回:drag.js rect rgb(160, 250, 160) iFlow->>瀏覽器: 修改:在drag.js插入代碼 end 瀏覽器->>正常用戶: 顯示:登錄頁面 正常用戶->>瀏覽器: 填寫賬號口令 正常用戶->>瀏覽器: 拖動滑動條 Note over 瀏覽器: 設置前端元素 瀏覽器->>iFlow: 請求:/iflow/dragged.dummy rect rgb(160, 250, 160) Note over iFlow: 為會話設置drag_ok標志 end 正常用戶->>瀏覽器: 點擊登錄按鈕 Note over 瀏覽器: 前端元素驗證通過 瀏覽器->>iFlow: 發送:登錄信息 rect rgb(160, 250, 160) Note over iFlow: 會話中有drag_ok標志 end iFlow->>Web服務器: 發送:登錄信息 Web服務器->>瀏覽器: 返回:登錄結果頁面 瀏覽器->>正常用戶: 顯示:登錄結果頁面

2.2 攻擊者訪問

如前所示,攻擊者強行修改前端元素,可以通過前端驗證。但當發送登錄信息而 iFlow 檢查標記時,由於攻擊者之前並未實際拖動滑動條發送標記請求,因此該標記並不存在。iFlow 可以據此判斷這是一個攻擊者在訪問,於是終止登錄過程。

攻擊者的 HTTP 協議交互過程如下:

sequenceDiagram participant 攻擊者 participant 瀏覽器 participant iFlow participant Web服務器 攻擊者->>瀏覽器: 地址欄輸入:/shopx/admin.php 瀏覽器->>Web服務器: 請求:/shopx/admin.php Web服務器->>瀏覽器: 返回:登錄頁面 瀏覽器->>Web服務器: 請求:/shopx/js/drag.js Web服務器->>iFlow: 返回:drag.js rect rgb(160, 250, 160) iFlow->>瀏覽器: 修改:在drag.js中插入代碼 end 瀏覽器->>攻擊者: 顯示:登錄頁面 攻擊者->>瀏覽器: 填寫賬號口令 rect rgb(250, 128, 128) 攻擊者->>瀏覽器: 【自行修改前端元素】 end 攻擊者->>瀏覽器: 點擊登錄按鈕 Note over 瀏覽器: 前端元素驗證通過 瀏覽器->>iFlow: 發送:登錄信息 rect rgb(160, 250, 160) Note over iFlow: 會話中無drag_ok標志 end iFlow->>瀏覽器: 拒絕訪問 rect rgb(250, 128, 128) 瀏覽器->>攻擊者: 拒絕訪問 end

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 應用了。(張戈 | 天存信息)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM