CSRF & CORS
下面轉的兩篇文章分別說明了以下兩個概念和一些解決方法:
1. CSRF - Cross-Site Request Forgery - 跨站請求偽造
2. CORS - Cross Origin Resourse-Sharing - 跨站資源共享
(1. CSRF)轉自:http://www.h3c.com.cn/About_H3C/Company_Publication/IP_Lh/2012/04/Home/Catalog/201208/751467_30008_0.htm
從下面文章中可以知道為什么要設置csrf_token,以及為什么一些網站把csrf_token放入header或url。
1 CSRF漏洞簡介
CSRF(Cross-Site Request Forgery,跨站點偽造請求)是一種網絡攻擊方式,該攻擊可以在受害者毫不知情的情況下以受害者名義偽造請求發送給受攻擊站點,從而在未授權的情況下執行在權限保護之下的操作,具有很大的危害性。具體來講,可以這樣理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義發送惡意請求,對服務器來說這個請求是完全合法的,但是卻完成了攻擊者所期望的一個操作,比如以你的名義發送郵件、發消息,盜取你的賬號,添加系統管理員,甚至于購買商品、虛擬貨幣轉賬等。
CSRF攻擊方式并不為大家所熟知,實際上很多網站都存在CSRF的安全漏洞。早在2000年,CSRF這種攻擊方式已經由國外的安全人員提出,但在國內,直到2006年才開始被關注。2008年,國內外多個大型社區和交互網站先后爆出CSRF漏洞,如:百度HI、NYTimes.com(紐約時報)、Metafilter(一個大型的BLOG網站)和YouTube等。但直到現在,互聯網上的許多站點仍對此毫無防備,以至于安全業界稱CSRF為“沉睡的巨人”,其威脅程度由此“美譽”便可見一斑。
2 CSRF攻擊原理及實例
CSRF攻擊原理
CSRF攻擊原理比較簡單,如圖1所示。其中Web A為存在CSRF漏洞的網站,Web B為攻擊者構建的惡意網站,User C為Web A網站的合法用戶。
圖1 CSRF攻擊原理
- 用戶C打開瀏覽器,訪問受信任網站A,輸入用戶名和密碼請求登錄網站A;
2.在用戶信息通過驗證后,網站A產生Cookie信息并返回給瀏覽器,此時用戶登錄網站A成功,可以正常發送請求到網站A;
用戶未退出網站A之前,在同一瀏覽器中,打開一個TAB頁訪問網站B;
網站B接收到用戶請求后,返回一些攻擊性代碼,并發出一個請求要求訪問第三方站點A;
瀏覽器在接收到這些攻擊性代碼后,根據網站B的請求,在用戶不知情的情況下攜帶Cookie信息,向網站A發出請求。網站A并不知道該請求其實是由B發起的,所以會根據用戶C的Cookie信息以C的權限處理該請求,導致來自網站B的惡意代碼被執行。
CSRF攻擊分類
CSRF漏洞一般分為站外和站內兩種類型。
CSRF站外類型的漏洞本質上就是傳統意義上的外部提交數據問題。通常程序員會考慮給一些留言或者評論的表單加上水印以防止SPAM問題(這里,SPAM可以簡單的理解為垃圾留言、垃圾評論,或者是帶有站外鏈接的惡意回復),但是有時為了提高用戶的體驗性,可能沒有對一些操作做任何限制,所以攻擊者可以事先預測并設置請求的參數,在站外的Web頁面里編寫腳本偽造文件請求,或者和自動提交的表單一起使用來實現GET、POST請求,當用戶在會話狀態下點擊鏈接訪問站外Web頁面,客戶端就被強迫發起請求。
CSRF站內類型的漏洞在一定程度上是由于程序員濫用
REQUEST類變量造成的。在一些敏感的操作中(如修改密碼、添加用戶等),本來要求用戶從表單提交發起POST請求傳遞參數給程序,但是由于使用了_REQUEST等變量,程序除支持接收POST請求傳遞的參數外也支持接收GET請求傳遞的參數,這樣就會為攻擊者使用CSRF攻擊創造條件。一般攻擊者只要把預測的請求參數放在站內一個貼子或者留言的圖片鏈接里,受害者瀏覽了這樣的頁面就會被強迫發起這些請求。
CSRF攻擊實例
下面以Axous 1.1.1 CSRF Add Admin Vulnerability(漏洞CVE編號:CVE-2012-2629)為例,介紹CSRF攻擊具體實施過程。
Axous是一款網上商店應用軟件。Axous 1.1.1以及更低版本在實現上存在一個CSRF漏洞,遠程攻擊者可以通過構造特制的網頁,誘使該軟件管理員訪問,成功利用此漏洞的攻擊者可以添加系統管理員。利用此漏洞主要包含以下三個過程:
攻擊者構造惡意網頁。在實施攻擊前,攻擊者需要構造一個與正常添加管理員用戶基本一樣的網頁,在該惡意網頁中對必要的參數項進行賦值,并將該網頁的action指向正常添加管理員用戶時訪問的URL,核心代碼如圖2所示;
攻擊者利用社會工程學誘使Axous系統管理員訪問其構造的惡意網頁;
執行惡意代碼。當系統管理員訪問惡意網頁時,惡意代碼在管理員不知情的情況下以系統管理員的合法權限被執行,攻擊者偽造的管理員賬戶添加成功。
圖2 CSRF攻擊添加管理員核心代碼
3 CSRF 漏洞檢測
檢測CSRF漏洞是一項比較繁瑣的工作,最簡單的方法就是抓取一個正常請求的數據包,去掉Referer字段后再重新提交,如果該提交還有效,那么基本上可以確定存在CSRF漏洞。
隨著對CSRF漏洞研究的不斷深入,不斷涌現出一些專門針對CSRF漏洞進行檢測的工具,如CSRFTester,CSRF Request Builder等。
以CSRFTester工具為例,CSRF漏洞檢測工具的測試原理如下:使用CSRFTester進行測試時,首先需要抓取我們在瀏覽器中訪問過的所有鏈接以及所有的表單等信息,然后通過在CSRFTester中修改相應的表單等信息,重新提交,這相當于一次偽造客戶端請求。如果修改后的測試請求成功被網站服務器接受,則說明存在CSRF漏洞,當然此款工具也可以被用來進行CSRF攻擊。
4 CSRF漏洞防御
CSRF漏洞防御主要可以從三個層面進行,即服務端的防御、用戶端的防御和安全設備的防御。
4.1 服務端的防御
目前業界服務器端防御CSRF攻擊主要有三種策略:驗證HTTP Referer字段,在請求地址中添加token并驗證,在HTTP頭中自定義屬性并驗證。下面分別對這三種策略進行簡要介紹。
4.1.1 驗證HTTP Referer字段
根據HTTP協議,在HTTP頭中有一個字段叫Referer,它記錄了該HTTP請求的來源地址。在通常情況下,訪問一個安全受限頁面的請求必須來自于同一個網站。比如某銀行的轉賬是通過用戶訪問http://bank.test/test?page=10&userID=101&money=10000頁面完成,用戶必須先登錄bank. test,然后通過點擊頁面上的按鈕來觸發轉賬事件。當用戶提交請求時,該轉賬請求的Referer值就會是轉賬按鈕所在頁面的URL(本例中,通常是以bank. test域名開頭的地址)。而如果攻擊者要對銀行網站實施CSRF攻擊,他只能在自己的網站構造請求,當用戶通過攻擊者的網站發送請求到銀行時,該請求的Referer是指向攻擊者的網站。因此,要防御CSRF攻擊,銀行網站只需要對于每一個轉賬請求驗證其Referer值,如果是以bank. test開頭的域名,則說明該請求是來自銀行網站自己的請求,是合法的。如果Referer是其他網站的話,就有可能是CSRF攻擊,則拒絕該請求。
4.1.2 在請求地址中添加token并驗證
CSRF攻擊之所以能夠成功,是因為攻擊者可以偽造用戶的請求,該請求中所有的用戶驗證信息都存在于Cookie中,因此攻擊者可以在不知道這些驗證信息的情況下直接利用用戶自己的Cookie來通過安全驗證。由此可知,抵御CSRF攻擊的關鍵在于:在請求中放入攻擊者所不能偽造的信息,并且該信息不存在于Cookie之中。鑒于此,系統開發者可以在HTTP請求中以參數的形式加入一個隨機產生的token,并在服務器端建立一個攔截器來驗證這個token,如果請求中沒有token或者token內容不正確,則認為可能是CSRF攻擊而拒絕該請求。
4.1.3 在HTTP頭中自定義屬性并驗證
自定義屬性的方法也是使用token并進行驗證,和前一種方法不同的是,這里并不是把token以參數的形式置于HTTP請求之中,而是把它放到HTTP頭中自定義的屬性里。通過XMLHttpRequest這個類,可以一次性給所有該類請求加上csrftoken這個HTTP頭屬性,并把token值放入其中。這樣解決了前一種方法在請求中加入token的不便,同時,通過這個類請求的地址不會被記錄到瀏覽器的地址欄,也不用擔心token會通過Referer泄露到其他網站。
4.2 用戶端的防御
對于普通用戶來說,都學習并具備網絡安全知識以防御網絡攻擊是不現實的。但若用戶養成良好的上網習慣,則能夠很大程度上減少CSRF攻擊的危害。例如,用戶上網時,不要輕易點擊網絡論壇、聊天室、即時通訊工具或電子郵件中出現的鏈接或者圖片;及時退出長時間不使用的已登錄賬戶,尤其是系統管理員,應盡量在登出系統的情況下點擊未知鏈接和圖片。除此之外,用戶還需要在連接互聯網的計算機上安裝合適的安全防護軟件,并及時更新軟件廠商發布的特征庫,以保持安全軟件對最新攻擊的實時跟蹤。
跨域資源共享(CORS)安全性淺析
(轉自http://netsecurity.51cto.com/art/201311/419179.htm)
一、背景
提起瀏覽器的同源策略,大家都很熟悉。不同域的客戶端腳本不能讀寫對方的資源。但是實踐中有一些場景需要跨域的讀寫,所以出現了一些hack的方式來跨域。比如在同域內做一個代理,JSON-P等。但這些方式都存在缺陷,無法完美的實現跨域讀寫。所以在XMLHttpRequest v2標準下,提出了CORS(Cross Origin Resourse-Sharing)的模型,試圖提供安全方便的跨域讀寫資源。目前主流瀏覽器均支持CORS。
二、技術原理
CORS定義了兩種跨域請求,簡單跨域請求和非簡單跨域請求。當一個跨域請求發送簡單跨域請求包括:請求方法為HEAD,GET,POST;請求頭只有4個字段,Accept,Accept-Language,Content-Language,Last-Event-ID;如果設置了Content-Type,則其值只能是application/x-www-form-urlencoded,multipart/form-data,text/plain。說起來比較別扭,簡單的意思就是設置了一個白名單,符合這個條件的才是簡單請求。其他不符合的都是非簡單請求。
之所以有這個分類是因為瀏覽器對簡單請求和非簡單請求的處理機制是不一樣的。當我們需要發送一個跨域請求的時候,瀏覽器會首先檢查這個請求,如果它符合上面所述的簡單跨域請求,瀏覽器就會立刻發送這個請求。如果瀏覽器檢查之后發現這是一個非簡單請求,比如請求頭含有X-Forwarded-For字段。這時候瀏覽器不會馬上發送這個請求,而是有一個preflight,跟服務器驗證的過程。瀏覽器先發送一個options方法的預檢請求。下圖是一個示例。如果預檢通過,則發送這個請求,否則就不拒絕發送這個跨域請求。
下面詳細分析一下實現安全跨域請求的控制方式。先看一下非簡單請求的預檢過程。瀏覽器先發送一個options方法的請求。帶有如下字段:
Origin: 普通的HTTP請求也會帶有,在CORS中專門作為Origin信息供后端比對,表明來源域。
Access-Control-Request-Method: 接下來請求的方法,例如PUT, DELETE等等
Access-Control-Request-Headers: 自定義的頭部,所有用setRequestHeader方法設置的頭部都將會以逗號隔開的形式包含在這個頭中
然后如果服務器配置了cors,會返回對應對的字段,具體字段含義在返回結果是一并解釋。
Access-Control-Allow-Origin:
Access-Control-Allow-Methods:
Access-Control-Allow-Headers:
然后瀏覽器再根據服務器的返回值判斷是否發送非簡單請求。簡單請求前面講過是直接發送,只是多加一個origin字段表明跨域請求的來源。然后服務器處理完請求之后,會再返回結果中加上如下控制字段:
Access-Control-Allow-Origin: 允許跨域訪問的域,可以是一個域的列表,也可以是通配符"*"。這里要注意Origin規則只對域名有效,并不會對子目錄有效。即http://foo.example/subdir/ 是無效的。但是不同子域名需要分開設置,這里的規則可以參照同源策略
Access-Control-Allow-Credentials: 是否允許請求帶有驗證信息,這部分將會在下面詳細解釋
Access-Control-Expose-Headers: 允許腳本訪問的返回頭,請求成功后,腳本可以在XMLHttpRequest中訪問這些頭的信息(貌似webkit沒有實現這個)
Access-Control-Max-Age: 緩存此次請求的秒數。在這個時間范圍內,所有同類型的請求都將不再發送預檢請求而是直接使用此次返回的頭作為判斷依據,非常有用,大幅優化請求次數
Access-Control-Allow-Methods: 允許使用的請求方法,以逗號隔開
Access-Control-Allow-Headers: 允許自定義的頭部,以逗號隔開,大小寫不敏感
然后瀏覽器通過返回結果的這些控制字段來決定是將結果開放給客戶端腳本讀取還是屏蔽掉。如果服務器沒有配置cors,返回結果沒有控制字段,瀏覽器會屏蔽腳本對返回信息的讀取。
三、安全隱患
大家注意這個流程。服務器接收到跨域請求的時候,并沒有先驗證,而是先處理了請求。所以從某種程度上來說。在支持cors的瀏覽器上實現跨域的寫資源,打破了傳統同源策略下不能跨域讀寫資源。
再一個就是如果程序猿偷懶將Access-Control-Allow-Origin設置為允許來自所有域的跨域請求。那么cors的安全機制幾乎就無效了。不過先別高興的太早。其實這里在設計的時候有一個很好的限制。xmlhttprequest發送的請求需要使用“withCredentials”來帶上cookie,如果一個目標域設置成了允許任意域的跨域請求,這個請求又帶著cookie的話,這個請求是不合法的。(就是如果需要實現帶cookie的跨域請求,需要明確的配置允許來源的域,使用任意域的配置是不合法的)瀏覽器會屏蔽掉返回的結果。javascript就沒法獲取返回的數據了。這是cors模型最后一道防線。假如沒有這個限制的話,那么javascript就可以獲取返回數據中的csrf token,以及各種敏感數據。這個限制極大的降低了cors的風險。
四、攻擊模型
從思路上講,有兩種類型的攻擊方式。一種是在攻擊者自己控制的網頁上嵌入跨域請求,用戶訪問鏈接,執行了跨域請求,從而攻擊目標,比如訪問了內網敏感資源。還有一種是正常的網頁被嵌入了到攻擊者控制頁面的跨域請求,從而劫持用戶的會話。
五、攻擊場景
先看第一種思路的攻擊場景:
1,復雜csrf。傳統的csrf都是利用html標簽和表單來發送請求。沒有辦法實現一些復雜步驟的csrf,比如模擬購物,先加購物車,結算,填寫信息,等等。比如上傳文件。具體可以參考利用csrf上傳文件
2,訪問內網敏感資源。這個在一定的條件下是可以實現的。比如內網的服務器配置了
Access-Control-Allow-Origin: * 允許任何來自任意域的跨域請求
用戶訪問惡意網頁的時候,執行了到內網服務器192.168.1.123/password.txt的請求,腳本在接收到服務器返回之后,將內容發送到攻擊者的服務器上。
第二種思路的場景:
1,交互式xss。參考揭密HTML5帶來的攻擊手法中講到的shell of the future工具。通過cors,繞過一些反會話劫持的方法,如HTTP-Only限制的cookie,綁定IP地址的會話ID等,劫持用戶會話。
2,程序猿在寫ajax請求的時候,對目標域限制不嚴。有點類似于url跳轉。facebook出現過這樣一個案例。javascript通過url里的參數進行ajax請求。通過控制這個參數實現注入攻擊。