淺談XSS和CSRF

淺談XSS與CSRF

一、XSS

1.什麼是XSS攻擊
XSS也叫CSS,是Cross Site Script的簡稱,爲了和CSS(樣式)區分開來,所以改名爲XSS。XSS是web常見的攻擊手段之一,是通過向目標網站注入可執行的惡意代碼,以達到攻擊的目的。黑客能夠通過XSS攻擊,竊取用戶的信息想要進行XSS攻擊,盜取用戶的登陸憑證發起CSRF攻擊。想要達到XSS攻擊必須達到兩個條件,第一是向目標網站注入惡意代碼,第二是這部分代碼是可以被客戶端瀏覽器執行的。從攻擊的方式劃分,XSS攻擊又分爲反射型XSS和持久型XSS。

2.反射型XSS:
反射型XSS,是用戶點擊惡意鏈接,服務器接收解析響應後,在返回的響應中包含惡意的代碼,被客戶端瀏覽器執行,這樣一來,XSS的攻擊代碼,是通過服務器的響應反射回來的,所以被稱爲反射型XSS攻擊。一般攻擊者會在郵件,聊天記錄,釣魚網站中添加惡意的URL,用戶在不知情的情況下點擊,就很容易發生XSS反射攻擊。
比如:

<div>
    <img id="img1" src="~/StaticFiles/Backend/Images/@Request.QueryString["Id"].ToString()" />
</div>

在這裏插入圖片描述
單從源碼中看,這是一個正常的頁面,每次當頁面加載的時候,會讀取QueryString的值,加載相應的圖片。但是黑客往往就會利用這個安全漏洞,在釣魚網站,郵件,貼吧中發出一個惡意鏈接:

http://localhost:7286/Home/Test?Id=default_user.jpg“/><script>console.log(/xss/)<script/>

用戶在不知情的情況下,點擊了這個惡意鏈接,則瀏覽器會執行這一段腳本:

<script>console.log(/xss/)<script/>

用戶在不知情的情況下就已經遭受到XSS攻擊。

3. 持久型XSS
持久型XSS,持久型XSS具有較強的隱祕性和持久性,攻擊者通常通過在博客,論壇等社交網站評論內容,將惡意的代碼保存到web服務器中,當用戶加載頁面內容時,客戶端瀏覽器會加載並執行這部分惡意代碼。持久型XSS具有兩個特點:一是惡意代碼保存到了web服務器中,二是攻擊者一般是利用博客,論壇等社交網站中評論留言功能,將惡意代碼注入到web服務器。比起反射型XSS,持久型XSS的隱祕性更強,而且每當用戶瀏覽論壇,博客的評論或留言時,就會受到XSS攻擊,攻擊範圍非常廣。

比如:
黑客會在評論留言中添加這麼一串代碼:

<script>console.log(XSS)</script>

每當用戶加載評論區中的內容時,就會將這部分的惡意代碼加載到客戶端的瀏覽器中,並能夠成功執行,這時,用戶在不知道的情況下,就遭受到了XSS攻擊。可以看出,持久型XSS具有很強的隱祕性,用戶在刷博客,刷論壇的時候,不知不覺可能就已經被攻擊了,而且這種攻擊的範圍非常的廣泛,並不是只針對某一用戶。

4. XSS攻擊能夠誘發CSRF攻擊
爲什麼XSS攻擊能夠誘發CSRF攻擊呢?(什麼是CSRF攻擊?本文後面會詳細講解。)原理很簡單,上面我們說過了,XSS攻擊是將惡意的代碼注入帶我們的網站中,那麼用戶在不知情的情況下,攻擊者則可以通過document.cookie這個腳本,將我們的cookie發到黑客的指定網站,當黑客竊取到我們當前的登陸憑據(cookie)後,會以我們的用戶身份做一個僞造請求,登陸我們的網站,做一系列的違規操作,竊取我們的數據。

5. 如何防禦XSS攻擊:

  1. 想要進行XSS防禦,就是要對用戶輸入的內容,請求URL和web服務端返回給瀏覽器的內容進行過濾轉譯。
    比如:
<“ 轉成 ”&lt;”
”>“ 轉成 ”&gt;"&” 轉成 "&amp;"
\" 轉成 "&quot;"
“'” 轉成 "&#39"
“\” 轉成 “\\”
“/” 轉成 "\/"
  1. XSS一般是通過腳本(document.cookie)獲取瀏覽器的cookie,那麼如果我們在服務端將cookie的HttpOnly屬性設置成true,則在客戶端中,黑客就無法通過js腳本獲取到我們的cookie,但是在每次請求的時候,cookie又會以請求頭的形式,能夠被服務器訪問,不會影響到正常的使用。
    以C#爲例,如果設置cookie的HttpOnly屬性爲true,
var cookie = new HttpCookie("username", "lyq");
cookie.HttpOnly=true;

但是將cookie的HttpOnly屬性設置成true也不是萬無一失的方法,因爲在低版本的瀏覽器中,是不支持HttpOnly屬性的。

二、CSRF

1. 什麼是CSRF攻擊?
CSRF是跨站請求僞造(Cross Site Request Forgery)的簡稱,是通過盜取客戶端用戶的合法登陸憑據,冒用了用戶的合法身份,對服務器發起請求,但是這種請求對服務器來說又是合法合理的。比如:黑客能夠盜用我們的合法身份,對他們的博客進行關注,評論,也能夠向他們的銀行賬戶轉賬。用戶被攻擊,首先要具備兩個條件:一是用戶成功登陸A網站,並且沒有登出,在客戶端瀏覽器保留了登陸憑據(cookie),二是用相同的瀏覽器訪問惡意的網站。

2. CSRF攻擊的原理:

  1. 用戶lyq登陸了A網站,服務器在接收到請求後,會在服務端存放一個session,並響應客戶端一個cookie,這就在用戶lyq電腦的客戶端保留了一個合法的登陸憑據。

  2. 用戶lyq在保留了A網站的登陸憑據的前提下,用相同的瀏覽器訪問了B網站(惡意的釣魚網站)

  3. B網站盜取到了A網站的登陸憑據,則黑客可以利用lyq的登陸憑據,成功的訪問了A網站,並且竊取到了用戶LYQ的信息,做一系列的違規操作。

3.實例分析:
現在A網站是通過這麼一個接口向可以向某人轉賬:

 http://www.lyq.com:5002/Home/TransferMoney?transferTo=someone&money=100

碰巧lyq在A網站有一個賬戶。某天,lyq登陸了A網站。正常情況下,lyq登陸A網站後,會在服務器內存中存放一個session, 並且服務器會響應一個cookie給客戶端瀏覽器,作爲登陸憑據。
在這裏插入圖片描述
粗心大意的lyq在沒有登出A網站的情況下(登陸憑據沒有註銷),用相同的瀏覽器訪問了B網站。

http://www.hacker.com:5003/

B網站是一個釣魚網站。在B網站中有這麼一串代碼。

<iframe src="http://www.lyq.com:5002/Home/TransferMoney?transferTo=Jack&money=1000"></iframe>

當lyq訪問B網站時,黑客Jack在lyq不知情的情況下,就盜用了lyq的登陸憑據,仿造lyq的請求,向A網站發送了一個轉賬的請求。服務器在接收到這個請求後,後認爲這就是lyq自己發起的請求,認爲是一個合法的請求,這就將lyq賬戶中的1000元轉到黑客Jack的賬戶下。
在這裏插入圖片描述
由於iframe的src屬性,B網站跨站的調用了A網站的轉賬接口,B網站發起的轉賬請求和A網站在客戶端存留的cookie在同一個域下,則B網站每次向A網站服務器請求的時候,都會自動帶上這個合法的登陸憑據(cookie),僞造成一個合法的請求。
知道這個安全漏洞後,A網站的工作人員迅速修復了這麼一個安全漏洞,將這個接口設置成post請求。但是道高一尺,魔高一丈。黑客Jack也迅速對B網站做了升級。

<form action="http://www.lyq.com:5002/Home/TransferMoney" method="post" id="form1">
    <input type="text" name="transferTo" value="Jack" />
    <input type="text" name="money" value="1000" />
    <button type="submit" id="btnSubmit">提交</button>
</form>

<script>
    window.onload = function () {
        document.getElementById("form1").submit();
    }
</script>

當lyq訪問到B網站時,同樣會對A網站發送一個合理post請求,將lyq賬戶中的前轉到黑客jack的帳下。當然,爲了增加B網站的隱祕性,還可以下B網站下面再次嵌套一個ifram,防止頁面的刷新。

4. 那如何能做到有效的防禦CSRF攻擊呢?

  1. 對於敏感的請求,儘量使用post請求代替get請求。這樣會增加CSRF攻擊的難度,從一定程度上能避免CSRF攻擊。

  2. 對於表單請求,可以加上一個驗證碼。客戶端在每次請求時,都要帶上這個驗證碼,和服務器上的驗證碼進行匹配,如果匹配失敗,則請求無效。這樣能夠有效的避免90% 以上的CSRF攻擊。但是這樣缺點也十分的明顯,若對於一個項目來說,有很多的表單請求,如果每一個表單請求都要用驗證碼驗證,對於用戶來說會是一個很糟糕的體驗。

  3. 服務器在每次接收http請求時,先判斷這個http請求的來源地址Refer。如果這個http請求不是從受信任的域名發起的,我們則認爲這是一個非法的請求。
    在這裏插入圖片描述
    以 ASP.NET MVC爲例:

public void OnActionExecuting(ActionExecutingContext filterContext)
       {        
           //獲取受信任域名        
           var TrustedDomain = Initialize.GetTrustedDomain;
           var httpContext = filterContext.HttpContext;                     

           if (httpContext.Request.UrlReferrer != null && !TrustedDomain.Contains(httpContext.Request.UrlReferrer.Host))
           {
               if (httpContext.Request.IsAjaxRequest())
               {
                   filterContext.Result = new JsonResult()
                   {
                       Data = new JsonData() { Info = $"403 Forbidden.", Status = "403" },
                       JsonRequestBehavior = JsonRequestBehavior.AllowGet
                   };
               }
               else filterContext.Result = new RedirectResult("/Error/NotFound");
           }
       }

但是缺點就是依賴於瀏覽器的Refer屬性,如果用戶關閉掉客戶端瀏覽器的這一功能後,則正常的用戶每次訪問網站時,都會被視爲一個非法的請求,無法正常使用。

  1. 一般我們現在的web應用程序,都是用Ajax做無刷新訪問的,因此我們可以利用XmlHttpRequest對象。當我們每次向服務器發起請求時,服務器接收並完成時,可以客戶端響應一個新的token,這時候通過Ajax的XmlHttpRequest對象,我們可以獲取到這個token,在下一次的請求時,將這個token放到請求的請求頭中,下次服務器在接收請求時,就會判斷請求Header的token是否有效,判斷這是否時一個有效的請求。但是這樣的缺點時侷限性很多,對於請求地址來說,很難在請求頭寫入token。
    因此,我們也可以將token放到請求地址中,方便我們接收。(什麼是token,請看ASP.NET MV使用JWT代替session,實現單點登陸
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章