原理
跨站腳本(Cross site script,簡稱xss)是一種“HTML注入”,由於攻擊的腳本多數時候是跨域的,所以稱之為“跨域腳本”。
我們常常聽到“注入”(Injection),如SQL注入,那么到底“注入”是什么?注入本質上就是把輸入的數據變成可執行的程序語句。SQL注入是如此,XSS也如此,只不過XSS一般注入的是惡意的腳本代碼,這些腳本代碼可以用來獲取合法用戶的數據,如Cookie信息。
其原理如下圖所示:
XSS從攻擊原理上,分為三類:
1:反射型XSS
將用戶輸入“反射”回瀏覽器,即將用戶的輸入變成HTML傳輸回客戶端。如:
Response.Write(“<script>alert(/xss/);</script>”)
就是一個典型的反射型XSS。
2:存儲性XSS
存儲性XSS本質上也是一種反射型XSS,但是它把攻擊腳本放置在服務器端,一旦被注入,可被多人多次利用。如,發表博文,就可以引入存儲性的XSS。
3:DOM BASED XSS
如果用戶的輸入被用於修改原有HTML的DOM內容,就會引入這一類攻擊。
最典型的是輸入的內容用於作為某個節點的innerHTML,如果不對輸入作驗證,則會被注入攻擊代碼。
如下的一段腳本注入后,就會獲取用戶的Cookie
<script language=”javascript”>
var cockieInfo =window.cockie;
//send cockieInfo to luminji
</javascript>
實際案例
使用Fiddler,查看到某系統添加公共信息有一處Post,我們偽造如下的請求:
POST xxx.com/AddPublicInfo HTTP/1.1
Accept: */*
Accept-Language: zh-cn
Content-Type: application/json; charset=utf-8
Accept-Encoding: gzip, deflate
Host: 192.168.80.136
Content-Length: 187
Cookie: ASP.NET_SessionId=qk1qvprjrikp2peveg2ini45; LanguageKey=zh_cn; LoginId=dean;
{"type":"ExtBulletin","title":"1111asdf11","content":"22sdfs22<script>alert(/xss/);</script>","validPeriod":"1","beginDate":"","endDate":"","language":"None","linkFile":"0","fileName":""}
然后,刷新公共信息頁面,發現注入代碼成功。如果該站點同時存在會話劫持方法的漏洞,則將注入腳本改稱獲取cookie,攻擊者就可以偽造任意訪問了本信息的用戶來登錄系統。
通過該例子我們也可以看到,對於XSS的防范,所有的處理應該是在服務器端的,因為客戶端的驗證,如使用JS來驗證輸入是完全可以通過偽造請求被繞過的。所以在安全架構方面對於JS腳本的定位為:JS僅用於改善用戶體驗。
應對策略
1. 在服務器段限制輸入格式,輸入類型,輸入長度以及輸入字符
要注意避免使用一些有潛在危險的html標簽,這些標簽很容易嵌入一些惡意網頁代碼。如<img> <iframe><script><frameset><embed><object>< style>等。
注意,不要僅僅在客戶端使用js代碼加以驗證。因為客戶端的js腳本可以被繞過。
2. 格式化輸出。將輸入的內容通過HttpUtility.HtmlEncode處理,這樣就不能直接看出輸出的內容。
3:對於asp.net站點,可以確保:
<configuration>
<system.web>
<pages validateRequest="true" />
</system.web>
</configuration>
注意,默認情況下為true。
4:IE本身也有機制阻止跨站腳本
存在跨站腳本威脅,如果使用的IE8,則這個請求會被攔截,提示“Internet Explorer 已對此頁面進行了修改,以幫助阻止跨站腳本。單擊此處,獲取詳細信息...”。
這個錯誤是由於 IE8 的跨站腳本(Cross-site scripting, XSS)防護阻止了跨站發送的請求。
以下是如何配置它:點擊 IE8 的“工具”-“Internet 選項”,進入“安全”選項卡,打開“Internet”下方的“自定義級別”,在“安全設置”對話框中找到“啟用 XSS 篩選器”,改為“禁用”即可。 注意,“啟用”是默認配置。
當然,瀏覽器本身的這種機制是不可靠的。
具體措施
n 查找所有code behind中的”.Text”
通過文件查找出所有的為文本賦值的代碼行;
n 為賦值Encode
對上一步驟查找出來的賦值,首先Encode。
n 查找所有的WCF方法中返回字符串的
通過文件查找”.svc”,找到全部的WCF方法,篩選出返回string的方法
n 處理字符串再返回
對上一步驟查找出來的返回的string,先找到序列化方法,然后對實體的可能被用於輸出為html的屬性,首先Encode
以上統計納入到如下表格:
序號 |
文件 |
代碼行 |
處理完成否 |
|
|
|
|
n 查找所有的文本輸入控件
通過文件查找前台所有的””text””,”’text’”,”type=text”,”textarea”,”textbox”字樣,篩選出含文本輸入的控件,這些控件包括:
<input type="text" />
<textarea></textarea>
<asp:TextBox runat="server"></asp:TextBox>
n 查找所有帶參數的URL
通過文件查找所有的”aspx?”,”html?”,”htm?”,”.svc”(隨系統的文件后綴方案而定),篩選出所有帶參數的URL。
n 查找所有的ajax
通過文件查找前台中所有的”ajax”,篩選出所有的ajax輸入。
n 查找所有cookie
通過文件查找所有的”cookie”,找出所有設置cookie的地方。
n 查找所有session
通過文件查找所有的” session”,找出所有設置session的地方。
n 處理以上查找的結果
分別將其對應的輸出查找出來,然后匯集為如下的表格:
序號 |
前台文件 |
輸入出代碼行 |
輸出文件 |
為輸出賦值的代碼行 |
處理完成否 |
|
|
|
|
|
|
n 查找遺漏
為了防止遺漏,需要直接查找輸出,通過文件查找所有的”Response.Write”(后台),” innerHTML”(前台),”document.write”(前台)。將遺漏更新到上面的表格中。
注意,實際上,如果將應用程序變量和數據庫內容賦值給前台控件,通過這種方式還是不能找到遺漏的,只能依賴於前面的輸入的查找來一定程度上避免這種情況。
n 根據以下表格中的處理方法來處理上面統計出來的表格中的代碼行,為輸出Encode
為了防范XSS攻擊,我們可以使用Anti-Cross Site Scripting Library(查看http://msdn.microsoft.com/en-us/library/aa973813.aspx,不過當前版本已經到了4.2.1,下載地址為:http://www.microsoft.com/en-us/download/details.aspx?id=28589)
該Library提供如下的幾個函數,分別對不同的應用場景作出處理:
Encoding Method |
Should Be Used If … |
Example/Pattern |
HtmlEncode |
Untrusted input is used in HTML output except when assigning to an HTML attribute. |
<a href="http://www.contoso.com">Click Here [Untrusted input]</a> |
HtmlAttributeEncode |
Untrusted input is used as an HTML attribute |
<hr noshade size=[Untrusted input]> |
JavaScriptEncode |
Untrusted input is used within a JavaScript context |
<script type="text/javascript"> … [Untrusted input] … </script> |
UrlEncode |
Untrusted input is used in a URL (such as a value in a querystring) |
<a href="http://search.msn.com/results.aspx?q=[Untrusted-input]">Click Here!</a> |
VisualBasicScriptEncode |
Untrusted input is used within a Visual Basic Script context |
<script type="text/vbscript" language="vbscript"> … [Untrusted input] … </script> |
XmlEncode |
Untrusted input is used in XML output, except when assigning to an XML attribute |
<xml_tag>[Untrusted input]</xml_tag> |
XmlAttributeEncode |
Untrusted input is used as an XML attribute |
<xml_tag attribute=[Untrusted input]>Some Text</xml_tag> |
n 確保配置web.config中的validateRequest="true"
n 確保Cookie的httponly
通過文件查找所有的”cookie”,找出所有設置cookie的地方,為用於認證的cookie設置如下的格式:
Set-Cookie: cookieName=cookieValue;httponly
參考: