1. 程式人生 > 實用技巧 >CSRF攻擊&XSS攻擊&SQL注入

CSRF攻擊&XSS攻擊&SQL注入

概述

​在 HTML 中,<a>, <form>, <img>, <script>, <iframe>, <link> 等標籤以及 Ajax 都可以指向一個資源地址,而所謂的跨域請求就是指:當前發起請求的域與該請求指向的資源所在的域不一樣。這裡的域指的是這樣的一個概念:我們認為若協議 + 域名 + 埠號均相同,那麼就是同域。

​ 舉個例子:假如一個域名為aaa.cn的網站,它發起一個資源路徑為aaa.cn/books/getBookInfo的 Ajax 請求,那麼這個請求是同域的,因為資源路徑的協議、域名以及埠號與當前域一致(例子中協議名預設為http,埠號預設為80)。但是,如果發起一個資源路徑為bbb.com/pay/purchase

的 Ajax 請求,那麼這個請求就是跨域請求,因為域不一致,與此同時由於安全問題,這種請求會受到同源策略限制。

跨域請求的安全問題

​通常,瀏覽器會對上面提到的跨域請求作出限制。瀏覽器之所以要對跨域請求作出限制,是出於安全方面的考慮,因為跨域請求有可能被不法分子利用來發動CSRF攻擊。

一、csrf攻擊

  CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF。CSRF攻擊者在使用者已經登入目標網站之後,誘使使用者訪問一個攻擊頁面,利用目標網站對使用者的信任,以使用者身份在攻擊頁面對目標網站發起偽造使用者操作的請求,達到攻擊目的。、 

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能夠做的事情包括:以你名義傳送郵件,發訊息,盜取你的賬號,甚至於購買商品,虛擬貨幣轉賬......造成的問題包括:個人隱私洩露以及財產安全。

CSRF攻擊是源於WEB的隱式身份驗證機制!WEB的身份驗證機制雖然可以保證一個請求是來自於某個使用者的瀏覽器,但卻無法保證該請求是使用者批准傳送的!

​ 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 請求,這樣幾乎是要重寫整個網站,這代價無疑是不能接受的。

二、XSS攻擊

XSS又叫CSS (Cross Site Script) ,跨站指令碼攻擊。它指的是惡意攻擊者往Web頁面裡插入惡意html程式碼,當用戶瀏覽該頁之時,嵌入其中Web裡面的html程式碼會被執行,從而達到惡意的特殊目的。XSS屬於被動式的攻擊,因為其被動且不好利用,所以許多人常呼略其危害性。

在WEB2.0時代,強調的是互動,使得使用者輸入資訊的機會大增,在這個情況下,我們作為開發者,在開發的時候,要提高警惕。

XSS攻擊的主要途徑

XSS攻擊方法只是利用HTML的屬性,作各種的嘗試,找出注入的方法。現在對三種主要方式進行分析。
第一種:對普通的使用者輸入,頁面原樣內容輸出。

開啟http://go.ent.163.com/goproducttest/test.jsp(限公司IP),輸 入:<script>alert(‘xss’)</script>, JS指令碼順利執行。當攻擊者找到這種方法後,就可以傳播這種連結格式的連結 (http://go.ent.163.com/goproducttest/test.jsp?key=JSCODE)如:http: //go.ent.163.com/goproducttest/test.jsp?key=<script>alert(‘xss’)& lt;/script>,並對JSCODE做適當偽裝,如:

http://go.ent.163.com/goproducttest/test.jsp?key=%3c%73%63%72%69%70 %74%3e%61%6c%65%72%74%28%27%78%73%73%27%29%3c%2f%73%63%72%69%70%74%3e,當其 它使用者當點此連結的時候,JS就運行了,造成的後果會很嚴重,如跳去一個有木馬的頁面、取得登陸使用者的COOKIE等。

第二種:在程式碼區裡有使用者輸入的內容

原則就是,程式碼區中,絕對不應含有使用者輸入的東西。

第三種:允許使用者輸入HTML標籤的頁面。

使用者可以提交一些自定義的HTML程式碼,這種情況是最危險的。因為,IE瀏覽器預設採用的是UNICODE編碼,HTML編碼可以用&#ASCII方式來寫,又可以使用”/”連線16進位制字串來寫,使得過濾變得異常複雜,如下面的四個例子,都可以在IE中執行。

1,直接使用JS指令碼。

<img src=”javascript:alert(‘xss’)” />

2,對JS指令碼進行轉碼。

<img src=”javascript:alert(‘xss’)” />

3,利用標籤的觸發條件插入程式碼並進行轉碼。

<img onerror=”alert(‘xss’)” />

4,使用16進位制來寫(可以在傲遊中執行)

<img STYLE=”background-image: /75/72/6c/28/6a/61/76/61/73/63/72/69/70/74/3a/61/6c/65/72/74/28/27/58/53/53/27/29/29″> 以上寫法等於<img STYLE=”background-image: url(javascript:alert(‘XSS’))”>

XSS攻擊解決辦法

請記住兩條原則:過濾輸入和轉義輸出。具體執行的方式有以下幾點:
第一、在輸入方面對所有使用者提交內容進行可靠的輸入驗證,提交內容包括URL、查詢關鍵字、http頭、post資料等. 第二、在輸出方面,在使用者輸內容中使用<XMP>標籤。標籤內的內容不會解釋,直接顯示。 第三、嚴格執行字元輸入字數控制。 第四、在指令碼執行區中,應絕無使用者輸入。