Ajax 構建於動態 HTML(DHTML)技術之上,其中包括以下這些最多見的技術:javascript
在 Ajax 中,客戶端 JavaScript 經過動態地修改 DOM 樹和樣式表來更新 Web 頁面。此外,異步通訊(能夠經過下面介紹的技術實現)容許動態地更新數據,而無需從新加載整個 Web 頁面:css
XMLHttpRequest
:XMLHttpRequest
是一個 API,它容許客戶端的 JavaScript 與遠程服務器創建 HTTP 鏈接和交換數據,好比說純文本、XML 和 JSON(JavaScript Serialized Object Notation)。注意,Ajax 應用程序中還有一些其餘經常使用的格式能夠替代 JSON,好比說 XML 和無格式的純文本。此處咱們選擇討論 JSON,其緣由在於它具備一些隱藏的安全問題,稍後咱們將在文章中對其進行研究。html
建議對 Ajax 還不熟悉的讀者先閱讀 參考資料 中的文章。java
當來自多個始發源的內容以某種方式被集成到一個單一的應用程序中時,一些內容相互之間可能具備不一樣的信任級別,或者它們可能根本沒有必要相互信任。這樣天然而然會產生某種需求,即把來自不一樣始發者的內容分離開來,把它們之間的衝突減至最少。ajax
同源策略是當前瀏覽器的保護機制的一部分,該機制未來自不一樣域(假設域表明的是始發者)的 Web 應用程序分離開來。也就是說,若是多個窗口或框架中的一些應用程序是從不一樣的服務器下載的,那麼它們沒法相互訪問數據和腳本。注意,同源策略只能應用於 HTML 文檔。經過 <script src="..." >
標記導入 HTML 文檔的 JavaScript 文件被認爲是該 HTML 文檔的同源的一部分。該策略在全部主要瀏覽器實現中都有執行。正則表達式
在 XMLHttpRequest
的上下文中,同源策略的目的是控制應用程序與遠程服務器的交互。然而,同源策略對 Web 2.0 應用程序的影響力比較有限,這有以下幾個緣由:編程
document.domain
屬性重寫爲 abc.com 或者就是 com(在 Firefox 中)。大多數最新的瀏覽器只容許訪問已經把它們的 document.domain
屬性重寫爲相同值的窗口或框架中的窗口對象。然而,一些版本比較老的瀏覽器容許與 document.domain
屬性中指定的域創建 XMLHttpRequest
鏈接。
因爲 JSON 只是一種含有簡單括號結構的純文本,所以許多通道均可以交換 JSON 消息。由於同源策略的限制,咱們不能在與外部服務器進行通訊的時候使用 XMLHttpRequest
。JSONP(JSON with Padding)是一種能夠繞過同源策略的方法,即經過使用 JSON 與 <script>
標記相結合的方法,如 清單 1 所示。跨域
當 JavaScript 代碼動態地插入 <script>
標記時,瀏覽器會訪問 src
屬性中的 URL。這樣會致使將查詢字符串中的信息發送給服務器。在 清單 1 中,所傳遞的是 username
和 reservation
做爲名稱值對傳遞。此外,查詢字符串還包含向服務器請求的輸出格式和回調函數的名稱(即 showItinerary
)。<script>
標記加載後,會執行回調函數,並經過回調函數的參數把從服務返回的信息傳遞給該回調函數。
Ajax 代理是一種應用級代理服務器,用於調解 Web 瀏覽器和服務器之間的 HTTP 請求和響應。Ajax 代理容許 Web 瀏覽器繞過同源策略,這樣即可以使用 XMLHttpRequest
訪問第三方服務器。要實現這種繞過,有以下兩種方法可供選擇:
Greasemonkey 是一個 Firefox 擴展,它容許用戶動態地對 Web 頁面的樣式和內容進行修改。Greasemonkey 用戶能夠把用戶腳本(user script) 文件與一個 URL 集合創建關聯。當瀏覽器經過該 URL 集合加載頁面時,便會執行這些腳本。Greasemonkey 爲用戶腳本的 API 提供了額外的許可(與運行在瀏覽器沙盒中的腳本的許可相比較)。
GM_XMLHttpRequest
是其中的一個 API,它從本質上說就是一個不具備同源策略的 XMLHttpRequest
。用戶腳本能夠將瀏覽的內置 XMLHttpRequest
替代爲 GM_XMLHttpRequest
,從而許可 XMLHttpRequest
執行跨域訪問。
GM_XMLHttpRequest
的使用只能經過用戶贊成的途徑才能受到保護。也就是說,Greasemonkey 只有在創建新用戶腳本與特定 URL 的集合之間的關聯時纔會要求用戶配置。然而,不難想象一些用戶可能會被欺騙,在沒有徹底理解其後果時就接受該安裝。
不只開發人員在避免同源策略時會向惡意用戶露出攻擊面,當惡意代碼被插入 Web 應用程序中時當前的應用程序也易於受到攻擊。遺憾的是,惡意代碼進入 Web 應用程序的方法多種多樣。咱們將簡要討論其中兩種可能的途徑,這對於 Web 2.0 的下上文來講也日漸相關。
跨站腳本(Cross-site scripting,XSS)
XSS 是一種很常見的攻擊手段,在該攻擊中攻擊者將一個惡意代碼段注入到一個運行良好的站點中。XSS 攻擊有以下兩種基本的類型:
reflected XSS 攻擊利用了 Web 應用程序安全性低的弱點,該應用程序在瀏覽器中顯示輸入參數而不對其中是否存在活動內容進行檢查。一般,攻擊者會誘使受害者單擊 URL,如 清單 2 所示。
清單 2. reflected XSS 攻擊的一個示例 URL
假設 trusted.com 提供了一個服務,該服務具備一個搜索特性能把搜索結果和輸入的關鍵字一塊兒提交回來。若是搜索應用程序沒有過濾 URL 中的一些特殊字符(如小於號 (<) 和大於號 (>)),則 <script>
標記也將被插入到用戶 Web 頁面中,這樣將會把文檔的 cookie 發送給遠程服務器 evil.com。
隨着 Web 2.0 的普及 stored XSS 攻擊愈來愈嚴重。Web 2.0 成功的關鍵是大衆之間的共享、交互和協做,所以用戶有更多的機會能夠經過一些服務(好比說社會網絡服務(social network services,SNS)、wiki 或 blog)看到其餘用戶(具備潛在惡意性)的輸入。
無論怎樣,輸入值驗證和數據消毒(sanitation)是防止 XSS 攻擊的關鍵因素。一般,Web 服務器從用戶輸入中移除腳本,可是攻擊者常常會利用服務器的弱點繞過這些過濾器,從而形成一些重大的攻擊,好比說 Yamanner 或 MySpaceIn 蠕蟲。
mashup 應用程序是一種 Web 應用程序,它能夠把來自多個來源的內容和服務結合到一個集成的用戶體驗中。一般,mashup 應用程序會形成一個單一的客戶端應用程序,所以 mashup 中的不一樣部分能夠經過一些瀏覽器資源(好比說 DOM 樹或瀏覽器窗口工具)來進行信息共享和交互。當 mashup 中的某些部分是出於惡意目的編寫的(或者被攻擊了),它能夠將惡意代碼注入到應用程序中。這樣會致使各類類型的攻擊(相似於 XSS),包括盜取用戶的敏感信息。
咱們已經知道攻擊者是如何將代碼注入應用程序的,接下來再看看一些常見攻擊所帶來的影響。
對於攻擊者而言,最直接的受益就是得到用戶的敏感信息,好比說用戶密碼或 cookies。由於注入腳本能夠訪問 DOM 樹的任何部分,因此它們能夠從登陸表單的文本字段中竊取密碼信息。例如,清單 3 中展現的代碼可以竊取信息並將其發送到某個攻擊者的服務器。
在本例中,攻擊者須要等待一段時間,直到用戶單擊提交按鈕以後才能接收到他的數據。Ajax 使攻擊者的工做更加簡單,這是由於它容許攻擊者向遠程服務發送任意信息,而不用等待利用用戶的動做,好比說點擊一個按鈕或單擊一個連接。這種類型的通訊量 一般會被視爲可疑行爲,可是因爲 Ajax 具備異步性,因此這種通訊量經常不會被檢測到。
使用相似的方法,攻擊者還可以竊取敏感 Web 應用程序中的文檔 cookies(好比說在線金融應用程序)。文檔 cookies 能夠容許攻擊者劫持會話或使用所竊取的憑證進行登陸。
注意,Microsoft® Internet Explorer® 6 或更高版本對 HttpOnly
cookies 提供了支持,這樣能夠防止客戶端腳本訪問文檔 cookies。然而,因爲大多數 Web 應用程序都不能依賴瀏覽器來實現,因此這種方法也無濟於事。
清單 4 展現了一個簡單的鍵盤記錄工具示例,該工具竊取 Web 頁面中的鍵盤事件並將它們發送給遠程服務器。鍵盤記錄工具容許攻擊者劫持任何用戶輸入;好比說,若是某個用戶在使用一個基於 Web 的電子郵件服務,那麼鍵盤記錄工具將記錄下任何文本輸入並將其發送給攻擊者。而後,攻擊者可以經過分析記錄數據檢索出憑證信息,好比說密碼和憑證信息。
軟鍵盤是防止鍵盤記錄工具竊取敏感輸入信息(好比說用於在線金融服務的登陸 PIN 碼)的一個經常使用技巧。然而,鼠標嗅探器可使用相似於鍵盤記錄工具所使用的技巧。經過竊取鼠標事件的 X 和 Y 座標,推算出鼠標在軟鍵盤上所點擊的鍵也是有可能的。清單 5 演示了一個簡單的鼠標嗅探器的示例。
使用 DOM 接口,攻擊者可以修改 DOM 樹中的任何信息。好比說,當某個用戶正在進行在線轉賬操做時,攻擊者把目標賬戶修改成屬於他本身的賬戶也是可行的。其結果是,轉賬的金額將被存入攻擊者的賬戶中。
在另外一種攻擊類型中,攻擊者可能會修改樣式表,把信息隱藏起來不讓用戶發現。好比說,假設某個 Web 頁面包含有一個警告消息,如 清單 6 所示。
攻擊者可能會修改樣式表,消除警告。好比說,清單 7 中展現的 JavaScript 代碼修改了警告的樣式,使它在白色的背景中不可見。
咱們對攻擊有可能的實現和其所帶來的後果有了基本的瞭解,接下來再看看一些技巧,並應用這些技巧改善 Ajax 應用程序的安全性。
正如咱們在 XSS 示例中所看到的,大多數的攻擊都利用了服務器端的弱點,注入惡意腳本。所以,要保護 Web 應用程序,第一步須要添加輸入驗證。輸入驗證和數據消毒會從不可信的輸入中過濾掉全部可能的活動或惡意的內容。
輸入驗證的兩種類型:
不能把黑名單或白名單做爲一種絕對安全的解決方案。可是,人們一般認爲白名單是更加安全的選擇。所以,推薦您使用白名單來清除具備潛在危險性的輸入。
對發送給瀏覽器並在其上顯示的字符串中的特殊字符(好比說把小於號 (<) 換成 "<")進行轉義是加強安全性的另外一種方法。有些程序語言提供了一些內置的函數用於轉義特殊字符。
因爲應用程序中的程序錯誤都比較相似,所以許多 Web 應用程序都易於受到攻擊。因此,安全專家開發了一些工具,用於檢測這些不安全的編程實踐。此類工具稱爲漏洞檢查工具,它們能預先檢測出潛在的漏洞。這些工 具檢測出的最多見的漏洞之一就是程序員忘記對潛在的惡意輸入調用消毒例程。
可使用若干種方法在 JavaScript 程序中動態地生成代碼。最著名的函數之一就是 eval()
函數,該函數容許您將任意字符串作爲 JavaScript 代碼執行。然而,肆無忌憚地使用該函數是很是危險的。遺憾的是,一些使用普遍的 JavaScript 庫在內部直接使用 eval()
函數。
因爲 JSON 是以 JavaScript 的一個子集爲基礎的,因此腳本內容會潛在地包含惡意代碼。然而,JSON 是 JavaScript 的一個安全的子集,不含有賦值和調用。所以,許多 JavaScript 庫使用 eval()
函數將 JSON 轉換成 JavaScript 對象。要利用這點,攻擊者能夠向這些庫發送畸形的 JSON 對象,這樣 eval()
函數就會執行這些惡意代碼。能夠採起一些方法來保護 JSON 的使用。第一個方法是使用 RFC 4627 中所定義的正則表達式確保 JSON 數據中不包含活動的部分。清單 8 演示瞭如何使用正則表達式檢查 JSON 字符串。
另外一種更具安全性的方法是使用 JSON 解析器對 JSON 進行解析。因爲 JSON 的語法至關的簡單,您能夠輕易地實現這種解析器,而不會帶來顯著的性能差別。
您能夠利用同源策略使攻擊者沒法輕易地訪問整個 DOM 樹。當您把不一樣域中的數據加載到一個 <iframe>
中時,應該給予該數據一個屬於本身的 JavaScript 執行上下文和 DOM 樹。這樣能夠防止攻擊者從主頁面中竊取信息。儘量多地 <iframe>
限制不可信的外部內容是一個良好的實踐。
在這篇文章中,咱們概述了在 Web 2.0 應用程序中避免同源策略的各類不一樣的方法。咱們還演示了這些方法如何在 Web 應用程序中公開一些新的攻擊點。咱們討論了一些常見的攻擊類型和這些攻擊所帶來的後果。最後,咱們在簡短的最佳實踐部分中對文章進行了總結,使用這些最佳 實踐能夠避免一些最多見的攻擊。
來源:https://www.ibm.com/developerworks/cn/xml/x-ajaxsecurity.html