Fortify Audit Workbench 筆記 Cross-Site Scripting-Persistent


Cross-Site Scripting: Persistent

Abstract

向 Web 瀏覽器發送非法數據會導致瀏覽器執行惡意代碼。

Explanation

Cross-Site Scripting (XSS) 漏洞在以下情況下發生:

1.

數據通過一個不可信賴的數據源進入 Web 應用程序。 對於 Persistent(也稱為 Stored) XSS,不可信賴的源通常為數據庫或其他后端數據存儲,而對於Reflected XSS,該源通常為 Web 請求。

2.

在未檢驗包含數據的動態內容是否存在惡意代碼的情況下,便將其傳送給了 Web 用戶。 傳送到 Web 瀏覽器的惡意內容通常采用 JavaScript 代碼片段的形式,但也可能會包含一些 HTML、 Flash 或者其他任意一種可以被瀏覽器執行的代碼。 基於 XSS 的攻擊手段花樣百出,幾乎是無窮無盡的,但通常它們都會包含傳輸給攻擊者的私人數據(如 Cookie 或者其他會話信息)。在攻擊者的控制下,指引受害者進入惡意的網絡內容;或者利用易受攻擊的站點,對用戶的機器進行其他惡意操作。
例 1
: 下面的 JSP 代碼片段可根據一個已知的雇員 ID 查詢數據庫,並輸出該雇員的姓名。

<%...
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from emp where id="+eid);
if (rs != null) {
rs.next();
String name = rs.getString("name");
}
%>
Employee Name: <%= name %>

如果對 name 的值處理得當,該代碼就能正常地執行各種功能;如若處理不當,就會對代碼的盜取行為無能為力。 這段代碼暴露出的危險較小,因為 name 的值是從數據庫中讀取的,而且顯然這些內容是由應用程序管理的。 然而,如果 name 的值是由用戶提供的數據產生,數據庫就會成為惡意內容溝通的通道。 如果不對數據庫中存儲的所有數據進行恰當的輸入驗證,那么攻擊者便能在用戶的 Web 瀏覽器中執行惡意命令。 這種類型的 Persistent XSS(也稱為 Stored XSS)盜取極其陰險狡猾,因為數據存儲導致的間接性使得辨別威脅的難度增大,而且還提高了一個攻擊影響多個用戶的可能性。 XSS 盜取會從訪問提供留言簿 (guestbook)的網站開始。 攻擊者會在這些留言簿的條目中嵌入 JavaScript,接下來所有訪問該留言簿的用戶都會執行這些惡意代碼。
例 2: 下面的 JSP 代碼片段可從 HTTP 請求中讀取雇員的 ID, eid,並將其顯示給用戶。

<% String eid = request.getParameter("eid"); %>
...
Employee ID: <%= eid %>

如例 1 中所述,如果 eid 只包含標准的字母或數字文本,此代碼就能正確運行。 如果 eid 里有包含元字符或源代碼中的值,那么 Web 瀏覽器就會像顯示 HTTP 響應那樣執行代碼。 起初,這個例子似乎是不會輕易遭受攻擊的。 畢竟,有誰會輸入導致惡意代碼的 URL,並且還在自己的電腦上運行呢? 真正的危險在於攻擊者會創建惡意的 URL,然后采用電子郵件或者社會工程的欺騙手段誘使受害者訪問此 URL 的鏈接。 當受害者單擊這個鏈接時,他們不知不覺地通過易受攻擊的網絡應用程序,將惡意內容帶到了自己的電腦中。 這種對易受攻擊的 Web 應用程序進行盜取的機制通常被稱為反射式 XSS。 正如例子中所顯示的, XSS 漏洞是由於 HTTP 響應中包含了未經驗證的數據代碼而引起的。 受害者遭受 XSS 攻擊的途徑有三種:

如例 1 所述, 應用程序將危險數據儲存在一個數據庫或其他可信賴的數據存儲器中。 這些危險數據隨后會被回寫到應用程序中,並包含在動態內容中。 Persistent XSS 盜取發生在如下情況:攻擊者將危險內容注入到數據存儲器中,且該存儲器之后會被讀取並包含在動態內容中。 從攻擊者的角度看,注入惡意內容的最佳位置莫過於一個面向許多用戶,尤其是相關用戶顯示的區域。 相關用戶通常在應用程序中具備較高的特權,或相互之間交換敏感數據,這些數據對攻擊者來說有利用價值。 如果某一個用戶執行了惡意內容,攻擊者就有可能以該用戶的名義執行某些需要特權的操作,或者獲得該用戶個人所有的敏感數據的訪問權限。

如例 2 所述,系統從 HTTP 請求中直接讀取數據,並在 HTTP 響應中返回數據。 當攻擊者誘使用戶為易受攻擊的 Web 應用程序提供危險內容,而這些危險內容隨后會反饋給用戶並在 Web 瀏覽器中執行,就會發生反射式 XSS 盜取。 發送惡意內容最常用的方法是,把惡意內容作為一個參數包含在公開發表的 URL 中,或者通過電子郵件直接發送給受害者。 以這種手段構造的 URL 構成了多種“網絡釣魚”(phishing) 陰謀的核心,攻擊者借此誘騙受害者訪問指向易受攻擊站點的 URL。 站點將攻擊者的內容反饋給受害者以后,便會執行這些內容,接下來會把用戶計算機中的各種私密信息(比如包含會話信息的 cookie)傳送給攻擊者,或者執行其他惡意活動。

-

應用程序以外的源代碼會在數據庫或其他數據存儲器中儲存危險數據,這些危險數據隨后會被應用程序當作可信賴的數據讀取並包含在動態內容之中。 許多現代 Web 框架都提供對用戶輸入執行驗證的機制。 其中包括 Struts 和 Struts 2。 為了突出顯示未經驗證的輸入源,該規則包會對 HP Fortify Static Code Analyzer(HP Fortify 靜態代碼分析器)報告的問題動態地重新調整優先級,具體方法是在采用框架驗證機制時降低這些問題被利用的可能性並提供相應的依據。 我們將這種功能稱之為上下文敏感排序。 為了進一步幫助 HPFortify 用戶執行審計過程, Fortify 安全研究團隊開發了 Data Validation(數據驗證)項目模板,該模板根據應用於輸入源的驗證機制按文件夾對問題進行了分組。

Recommendation

針對 XSS 的解決方法是,確保在適當位置進行驗證,並檢驗其屬性是否正確。 由於 XSS 漏洞出現在應用程序的輸出中包含惡意數據時,因此,合乎邏輯的做法是在數據流出應用程序的前一刻對其進行驗證。 然而,由於 Web 應用程序常常會包含復雜而難以理解的代碼,用以生成動態內容,因此,這一方法容易產生遺漏錯誤(遺漏驗證)。 降低這一風險的有效途徑是對 XSS 也執行輸入驗證。 由於 Web 應用程序必須驗證輸入信息以避免其他漏洞(如 SQL Injection),因此,一種相對簡單的解決方法是,加強一個應用程序現有的輸入驗證機制,將 XSS 檢測包括其中。 盡管有一定的價值,但 XSS 輸入驗證並不能取代嚴格的輸出驗證。 應用程序可能通過共享的數據存儲或其他可信賴的數據源接受輸入,而該數據存儲所接受的輸入源可能並未執行適當的輸入驗證。 因此,應用程序不能間接地依賴於該數據或其他任意數據的安全性。 這就意味着,避免XSS 漏洞的最佳方法是驗證所有進入應用程序或由應用程序傳送至用戶端的數據。 針對 XSS 漏洞進行驗證最安全的方式是,創建一份安全字符白名單,允許其中的字符出現在 HTTP 內容中,並且只接受完全由這些經認可的字符組成的輸入。 例如,有效的用戶名可能僅包含字母數字字符,電話號碼可能僅包含 0-9 的數字。 然而,這種解決方法在 Web 應用程序中通常是行不通的,因為許多字符對瀏覽器來說都具有特殊的含義, 在寫入代碼時,這些字符仍應被視為合法的輸入,比如一個 Web 設計版就必須接受帶有 HTML 代碼片段的輸入。 更靈活的解決方法稱為黑名單方法,但其安全性較差,這種方法在進行輸入之前就有選擇地拒絕或避免了潛在的危險字符。 為了創建這樣一個列表,首先需要了解對於 Web 瀏覽器具有特殊含義的字符集。 雖然 HTML 標准定義了哪些字符具有特殊含義,但是許多 Web 瀏覽器會設法更正 HTML 中的常見錯誤, 並可能在特定的上下文中認為其他字符具有特殊含義。 卡耐基梅隆大學 (Carnegie Mellon University) 軟件工程學院 (Software Engineering Institute) 下屬的 CERT(R) (CERT(R) Coordination Center) 合作中心提供了有關各種上下文中認定的特殊字符的具體信息 [1]:在有關塊級別元素的內容中(位於一段文本的中間): - "<" 是一個特殊字符,因為它可以引入一個標簽。 - "&" 是一個特殊字符,因為它可以引入一個字符實體。 - ">" 是一個特殊字符,之所以某些瀏覽器將其認定為特殊字符,是基於一種假設,即該頁的作者本想在前面添加一個 "<",卻錯誤地將其遺漏了。 下面的這些原則適用於屬性值: - 對於外加雙引號的屬性值, 雙引號是特殊字符,因為它們標記了該屬性值的結束。 - 對於外加單引號的屬性值,單引號是特殊字符, 因為它們標記了該屬性值的結束。 - 對於不帶任何引號的屬性值,空格字符(如空格符和制表符)是特殊字符。 - "&" 與某些特定變量一起使用時是特殊字符,因為它引入了一個字符實體。 例如,在 URL 中,搜索引擎可能會在結果頁面內提供一個鏈接,用戶可以點擊該鏈接來重新運行搜索。 可以將這一方法運用於編寫 URL 中的搜索查詢語句,這將引入更多特殊字符: - 空格符、制表符和換行符是特殊字符,因為它們標記了 URL 的結束。 - "&" 是特殊字符,因為它可引入一個字符實體或分隔 CGI 參數變量。 - 非 ASCII 字符(即 ISO-8859-1 編碼表中所有高於 128 的字符)不允許出現在 URL 中,因此在此上下文中也被視為特殊字符。 - 在服務器端對在 HTTP 轉義序列中編碼的參數進行解碼時,必須過濾掉輸入中的 "%" 符號。 例如, 當輸入中出現 "%68%65%6C%6C%6F" 時,只有從輸入的內容中過濾掉 "%",上述字符串才能在網頁上顯示為 "hello"。 在 的正文內: - 如果可以將文本直接插入到已有的腳本標簽中,應該過濾掉分號、省略號、 中括號和換行符。 服務器端腳本: - 如果服務器端腳本會將輸入中的感嘆號 (!) 轉換成輸出中的雙引號("),則可能需要對此進行更多過濾。 其他可能出現的情況: - 如果攻擊者在 UTF-7 中提交了一個請求,那么特殊字符 "<" 可能會顯示為 "+ADw-",並可能會繞過過濾。 如果輸出包含在沒有確切定義編碼格式的網頁中, 有些瀏覽器就會設法根據內容自動識別編碼(此處采用 UTF-7 格式)。 一旦在應用程序中確定了針對XSS 攻擊執行驗證的正確要點,以及驗證過程中要考慮的特殊字符,下一個難點就是定義驗證過程中處理各種特殊字符的方式。 如果應用程序認定某些特殊字符為無效輸入,那么您可以拒絕任何帶有這些無效特殊字符的輸入。 第二種選擇就是采用過濾手段來刪除這些特殊字符。 然而,過濾的負面作用在於,過濾內容的顯示將發生改變。在需要完整顯示輸入內容的情況下,過濾的這種負面作用可能是無法接受的。 如果必須接受帶有特殊字符的輸入,並將其准確地顯示出來,驗證機制一定要對所有特殊字符進行編碼,以便刪除其具有的含義。 官方的 HTML 規范提供了特殊字符對應的 ISO 8859-1 編碼值的完整列表。 許多應用程序服務器都試圖避免應用程序出現 Cross-Site Scripting 漏洞,具體做法是為負責設置特定 HTTP 響應內容的函數提供各種實現方式,以檢驗是否存在進行 Cross-Site Scripting 攻擊必需的字符。 不要依賴運行應用程序的服務器, 以此確保該應用程序的安全。 開發了某個應用程序后,並不能保證在其生命周期中它會在哪些應用程序服務器中運行。 由於標准和已知盜取方式的演變,我們不能保證應用程序服務器也會保持同步。


免責聲明!

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



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