XSS:跨站腳本(Cross-site scripting,一般簡稱爲XSS)是一種網站應用程序的安全漏洞攻擊,是代碼注入的一種。它容許惡意用戶將代碼注入到網頁上,其餘用戶在觀看網頁時就會受到影響。這類攻擊一般包含了HTML以及用戶端腳本語言。
CSRF:跨站請求僞造(英語:Cross-site request forgery),也被稱爲 one-click attack 或者 session riding,一般縮寫爲 CSRF 或者 XSRF, 是一種挾制用戶在當前已登陸的Web應用程序上執行非本意的操做的攻擊方法。javascript
簡單理解就是:html
XSS: 經過客戶端腳本語言(最多見如:JavaScript)
在一個論壇發帖中發佈一段惡意的JavaScript代碼就是腳本注入,若是這個代碼內容有請求外部服務器,那麼就叫作XSS!java
CSRF:又稱XSRF,冒充用戶發起請求(在用戶不知情的狀況下),完成一些違背用戶意願的請求(如惡意發帖,刪帖,改密碼,發郵件等)。程序員
一、繞過 XSS-Filter,利用 <> 標籤注入 Html/JavaScript 代碼;瀏覽器
二、利用 HTML 標籤的屬性值進行 XSS 攻擊。例如:<img src=「javascript:alert(‘xss’)」/>
;(固然並非全部的 Web 瀏覽器都支持 Javascript 僞協議,因此此類 XSS 攻擊具備必定的侷限性)安全
三、空格、回車和 Tab。若是 XSS Filter 僅僅將敏感的輸入字符列入黑名單,好比 javascript,用戶能夠利用空格、回車和 Tab 鍵來繞過過濾,例如:<img src=「javas cript:alert(/xss/);」/>
;服務器
四、利用事件來執行跨站腳本。例如:<img src=「#」 onerror= 「alert(1)」/>
,當 src 錯誤的視乎就會執行 onerror 事件;cookie
五、利用 CSS 跨站。例如:body {backgrund-image: url(「javascript:alert(‘xss’)」)}
;session
六、擾亂過濾規則。例如:<IMG SRC=「javaSCript: alert(/xss/);」/>
;併發
七、利用字符編碼,經過這種技巧,不只能讓 XSS 代碼繞過服務端的過濾,還能更好地隱藏 Shellcode;( JS 支持 unicode、eacapes、十六進制、十進制等編碼形式);
八、拆分跨站法,將 XSS 攻擊的代碼拆分開來,適用於應用程序沒有過濾 XSS 關鍵字符(如<、>)卻對輸入字符長度有限制的狀況下;
九、DOM 型的 XSS 主要是由客戶端的腳本經過 DOM 動態地輸出數據到頁面上,它不依賴於提交數據到服務器,而是從客戶端得到DOM中的數據在本地執行。容易致使 DOM 型的 XSS 的輸入源包括:Document.URL、Location(.pathname|.href|.search|.hash)、Document.referrer、Window.name、Document.cookie、localStorage/globalStorage
;
從上面的介紹可知,XSS 漏洞是因爲對用戶提交的數據沒有通過嚴格的過濾處理形成的,因此防護的原則就是不相信用戶輸入的數據,對輸入進行過濾,對輸出進行編碼。
一、使用 XSS Filter
針對用戶提交的數據進行有效的驗證,只接受咱們規定的長度或內容的提交,過濾掉其餘的輸入內容。好比:
表單數據指定值的類型:年齡只能是 int 、name 只能是字母數字等。
過濾或移除特殊的 html 標籤:<script>
、<iframe>
等。
過濾 js 事件的標籤:onclick
、onerror
、onfocus
等。
二、html 實體
當須要往 HTML 標籤之間插入不可信數據的時候,首先要作的就是對不可信數據進行 HTML Entity 編碼,在 html 中有些字符對於 HTML 來講是具備特殊意義的,因此這些特殊字符不容許在文本中直接使用,須要使用實體字符。 html 實體的存在是致使 XSS 漏洞的主要願意之一,所以咱們須要將實體轉化爲相應的實體編號。
顯示結果 | 描述 | 實體編號 |
---|---|---|
空格 |   ; | |
< | 小於 | < ; |
> | 大於 | > ; |
& | 和 | & ; |
'' | 引號 | " ; |
三、JavaScript編碼
這條原則主要針對動態生成的JavaScript代碼,這包括腳本部分以及HTML標籤的事件處理屬性(如onerror, onload等)。在往JavaScript代碼裏插入數據的時候,只有一種狀況是安全的,那就是對不可信數據進行JavaScript編碼,而且只把這些數據放到使用引號包圍起來的值部分(data value)之中,除了上面的那些轉義以外,還要附加上下面的轉義: \
轉成 \\
/
轉成 \/
;
轉成 ;
(全角;)
注意:在對不可信數據作編碼的時候,不能圖方便使用反斜槓\
對特殊字符進行簡單轉義,好比將雙引號 」
轉義成 \」
,這樣作是不可靠的,由於瀏覽器在對頁面作解析的時候,會先進行HTML解析,而後纔是JavaScript解析,因此雙引號極可能會被當作HTML字符進行HTML解析,這時雙引號就能夠突破代碼的值部分,使得攻擊者能夠繼續進行XSS攻擊;另外,輸出的變量的時候,變量值必須在引號內部,避免安全問題;更加嚴格的方式,對除了數字和字母之外的全部字符,使用十六進制\xhh 的方式進行編碼。
四、Http Only cookie
許多 XSS 攻擊的目的就是爲了獲取用戶的 cookie,將重要的 cookie 標記爲 http only,這樣的話當瀏覽器向服務端發起請求時就會帶上 cookie 字段,可是在腳本中卻不能訪問 cookie,這樣就避免了 XSS 攻擊利用 js 的 document.cookie
獲取 cookie。
不少地方均可能產生 XSS 漏洞,而且產生的方式不同,因此對於這些漏洞,咱們須要找到正確的方法來防護。XSS 漏洞在不斷的發展,上面介紹的防護方法幾乎可以解決大部分的 XSS 漏洞,即使這樣,咱們也不能掉以輕心,爲了讓 Web 應用更安全,咱們還須要結合其餘的方法來增強 XSS 防護。
隨着科技的不斷髮展,Web 應用變得愈來愈複雜,隨之而產生的漏洞(不只限於 XSS ) 也愈來愈多。沒有什麼方法可以一次性解決全部安全問題,咱們只能在實際的工做過程當中,針對不一樣的安全漏洞進行鍼對性的防護。
CSRF攻擊攻擊原理及過程以下:
1. 用戶C打開瀏覽器,訪問受信任網站A,輸入用戶名和密碼請求登陸網站A;
2.在用戶信息經過驗證後,網站A產生Cookie信息並返回給瀏覽器,此時用戶登陸網站A成功,能夠正常發送請求到網站A;
3. 用戶未退出網站A以前,在同一瀏覽器中,打開一個TAB頁訪問網站B;
4. 網站B接收到用戶請求後,返回一些攻擊性代碼,併發出一個請求要求訪問第三方站點A;
5. 瀏覽器在接收到這些攻擊性代碼後,根據網站B的請求,在用戶不知情的狀況下攜帶Cookie信息,向網站A發出請求。網站A並不知道該請求實際上是由B發起的,因此會根據用戶C的Cookie信息以C的權限處理該請求,致使來自網站B的惡意代碼被執行。
CSRF漏洞檢測:
檢測CSRF漏洞是一項比較繁瑣的工做,最簡單的方法就是抓取一個正常請求的數據包,去掉Referer字段後再從新提交,若是該提交還有效,那麼基本上能夠肯定存在CSRF漏洞。
隨着對CSRF漏洞研究的不斷深刻,不斷涌現出一些專門針對CSRF漏洞進行檢測的工具,如CSRFTester,CSRF Request Builder等。
以CSRFTester工具爲例,CSRF漏洞檢測工具的測試原理以下:使用CSRFTester進行測試時,首先須要抓取咱們在瀏覽器中訪問過的全部連接以及全部的表單等信息,而後經過在CSRFTester中修改相應的表單等信息,從新提交,這至關於一次僞造客戶端請求。若是修改後的測試請求成功被網站服務器接受,則說明存在CSRF漏洞,固然此款工具也能夠被用來進行CSRF攻擊。
防護CSRF攻擊:
目前防護 CSRF 攻擊主要有三種策略:驗證 HTTP Referer 字段;在請求地址中添加 token 並驗證;在 HTTP 頭中自定義屬性並驗證。
(1)驗證 HTTP Referer 字段
根據 HTTP 協議,在 HTTP 頭中有一個字段叫 Referer,它記錄了該 HTTP 請求的來源地址。在一般狀況下,訪問一個安全受限頁面的請求來自於同一個網站,好比須要訪問 http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory,用戶必須先登錄 bank.example,而後經過點擊頁面上的按鈕來觸發轉帳事件。這時,該轉賬請求的 Referer 值就會是轉帳按鈕所在的頁面的 URL,一般是以 bank.example 域名開頭的地址。而若是黑客要對銀行網站實施 CSRF 攻擊,他只能在他本身的網站構造請求,當用戶經過黑客的網站發送請求到銀行時,該請求的 Referer 是指向黑客本身的網站。所以,要防護 CSRF 攻擊,銀行網站只須要對於每個轉帳請求驗證其 Referer 值,若是是以 bank.example 開頭的域名,則說明該請求是來自銀行網站本身的請求,是合法的。若是 Referer 是其餘網站的話,則有多是黑客的 CSRF 攻擊,拒絕該請求。
這種方法的顯而易見的好處就是簡單易行,網站的普通開發人員不須要操心 CSRF 的漏洞,只須要在最後給全部安全敏感的請求統一增長一個攔截器來檢查 Referer 的值就能夠。特別是對於當前現有的系統,不須要改變當前系統的任何已有代碼和邏輯,沒有風險,很是便捷。
然而,這種方法並不是萬無一失。Referer 的值是由瀏覽器提供的,雖然 HTTP 協議上有明確的要求,可是每一個瀏覽器對於 Referer 的具體實現可能有差異,並不能保證瀏覽器自身沒有安全漏洞。使用驗證 Referer 值的方法,就是把安全性都依賴於第三方(即瀏覽器)來保障,從理論上來說,這樣並不安全。事實上,對於某些瀏覽器,好比 IE6 或 FF2,目前已經有一些方法能夠篡改 Referer 值。若是 bank.example 網站支持 IE6 瀏覽器,黑客徹底能夠把用戶瀏覽器的 Referer 值設爲以 bank.example 域名開頭的地址,這樣就能夠經過驗證,從而進行 CSRF 攻擊。
即使是使用最新的瀏覽器,黑客沒法篡改 Referer 值,這種方法仍然有問題。由於 Referer 值會記錄下用戶的訪問來源,有些用戶認爲這樣會侵犯到他們本身的隱私權,特別是有些組織擔憂 Referer 值會把組織內網中的某些信息泄露到外網中。所以,用戶本身能夠設置瀏覽器使其在發送請求時再也不提供 Referer。當他們正常訪問銀行網站時,網站會由於請求沒有 Referer 值而認爲是 CSRF 攻擊,拒絕合法用戶的訪問。
(2)在請求地址中添加 token 並驗證
CSRF 攻擊之因此可以成功,是由於黑客能夠徹底僞造用戶的請求,該請求中全部的用戶驗證信息都是存在於 cookie 中,所以黑客能夠在不知道這些驗證信息的狀況下直接利用用戶本身的 cookie 來經過安全驗證。要抵禦 CSRF,關鍵在於在請求中放入黑客所不能僞造的信息,而且該信息不存在於 cookie 之中。能夠在 HTTP 請求中以參數的形式加入一個隨機產生的 token,並在服務器端創建一個攔截器來驗證這個 token,若是請求中沒有 token 或者 token 內容不正確,則認爲多是 CSRF 攻擊而拒絕該請求。
這種方法要比檢查 Referer 要安全一些,token 能夠在用戶登錄後產生並放於 session 之中,而後在每次請求時把 token 從 session 中拿出,與請求中的 token 進行比對,但這種方法的難點在於如何把 token 以參數的形式加入請求。對於 GET 請求,token 將附在請求地址以後,這樣 URL 就變成 http://url?csrftoken=tokenvalue。 而對於 POST 請求來講,要在 form 的最後加上 <input type=」hidden」 name=」csrftoken」 value=」tokenvalue」/>,這樣就把 token 以參數的形式加入請求了。可是,在一個網站中,能夠接受請求的地方很是多,要對於每個請求都加上 token 是很麻煩的,而且很容易漏掉,一般使用的方法就是在每次頁面加載時,使用 javascript 遍歷整個 dom 樹,對於 dom 中全部的 a 和 form 標籤後加入 token。這樣能夠解決大部分的請求,可是對於在頁面加載以後動態生成的 html 代碼,這種方法就沒有做用,還須要程序員在編碼時手動添加 token。
該方法還有一個缺點是難以保證 token 自己的安全。特別是在一些論壇之類支持用戶本身發表內容的網站,黑客能夠在上面發佈本身我的網站的地址。因爲系統也會在這個地址後面加上 token,黑客能夠在本身的網站上獲得這個 token,並立刻就能夠發動 CSRF 攻擊。爲了不這一點,系統能夠在添加 token 的時候增長一個判斷,若是這個連接是鏈到本身本站的,就在後面添加 token,若是是通向外網則不加。不過,即便這個 csrftoken 不以參數的形式附加在請求之中,黑客的網站也一樣能夠經過 Referer 來獲得這個 token 值以發動 CSRF 攻擊。這也是一些用戶喜歡手動關閉瀏覽器 Referer 功能的緣由。
(3)在 HTTP 頭中自定義屬性並驗證
這種方法也是使用 token 並進行驗證,和上一種方法不一樣的是,這裏並非把 token 以參數的形式置於 HTTP 請求之中,而是把它放到 HTTP 頭中自定義的屬性裏。經過 XMLHttpRequest 這個類,能夠一次性給全部該類請求加上 csrftoken 這個 HTTP 頭屬性,並把 token 值放入其中。這樣解決了上種方法在請求中加入 token 的不便,同時,經過 XMLHttpRequest 請求的地址不會被記錄到瀏覽器的地址欄,也不用擔憂 token 會透過 Referer 泄露到其餘網站中去。
然而這種方法的侷限性很是大。XMLHttpRequest 請求一般用於 Ajax 方法中對於頁面局部的異步刷新,並不是全部的請求都適合用這個類來發起,並且經過該類請求獲得的頁面不能被瀏覽器所記錄下,從而進行前進,後退,刷新,收藏等操做,給用戶帶來不便。另外,對於沒有進行 CSRF 防禦的遺留系統來講,要採用這種方法來進行防禦,要把全部請求都改成 XMLHttpRequest 請求,這樣幾乎是要重寫整個網站,這代價無疑是不能接受的。