同源策略
同源策略(Same origin policy)是一種約定,一種非常重要的安全措施,也是最基本的安全功能,它禁止了來自不同源的指令碼對當前頁面的讀取或修改,從而限制了跨域訪問甚至修改資源,防止出現A頁面可以隨意更改B頁面資訊這樣子的極其糟糕的情況發生。
同源策略做了怎樣的限制呢?怎樣才會被認為是跨域的,不同源的呢?
以http://www.a.com為例:
正常情況 | http://www.a.com | 允許 |
不同域名 | http://www.b.com | 不允許 |
不同協議 | https://www.a.com | 不允許 |
不同埠 | http://www.a.com:10 | 不允許 |
不同子域名 | http://bp.a.com | 不允許 |
值得注意是:同源策略是在瀏覽器實現的所以它無法阻止請求和響應的傳送,當跨域請求發起後,實際上已經接收到了所請求的資源,如果我們攔截來響應包,就可以發現,所請求的資源已經包含在響應的包中了,瀏覽器發現跨域,根據同源策略,瀏覽器不讓所請求的資源載入出來。
hack.com將從test.com上請求資料
發現瀏覽器遵守同源策略阻止了跨域讀取的資源的載入,那麼這些想讀取的資源究竟是根本就沒有傳送還是已經傳送了卻被瀏覽器給禁止載入了呢?
可以很明顯的看出,已經接收了所請求的資源,但因為不同源被瀏覽器攔截了。
CORS是什麼?
隨著時代的發展,技術的進步,新的需求逐漸產生。人們開始有了跨域請求資源的需要,同源策略這樣一股腦的禁止所有的跨域請求顯然不合適,但放棄同源策略更是不可能的,允許不同源的頁面相互作用是一場災難。在這樣的需求與矛盾下,CORS應運而生。
跨域資源共享(Cross-origin resource sharing),簡稱CORS,它使某些頁面可以跨域請求來自特定的不同源的頁面資源。
CORS依託於瀏覽器,如果瀏覽器不支援CORS,那麼便無法使用,不過現在幾乎沒有不支援CORS的瀏覽器。
當發出跨域請求時,瀏覽器會在請求報文頭中加入欄位 Origin:xxx 來說明發起跨域請求的源,當另一端的伺服器接受到了帶有Origin的請求時,它會將所請求的資源放入響應報文中返回,並在響應頭中加入一些以 Access-Control- 開頭的欄位,我們需要關注的只有其中兩個:
- Access-Control-Allow-Origin: 它的值只能是一個外域的URI或者是*(只能有一個URI或*,不能寫像 Access-Control-Allow-Origin:http://a.com,http://b.com 這樣的,雖然這樣很方便,但它是不被允許的,該欄位後只允許有唯一一個URI,下文會說一種設定多個允許跨站的域的方法),這個值是允許進行跨域請求的源,瀏覽器接收響應後先比對這個欄位中的URI是不是發起請求的Origin,若為*則允許所有域名的請求。如果兩者一樣,則允許這次跨域請求,響應中的所請求的資源將會被載入到瀏覽器上。
- Access-Control-Allow-Credentials: 這個欄位的值只能是true,則接收的資料中包含cookie,若不設定該欄位,則不傳送cookie。
如此,通過CORS,可以實現幾個特定的域之間的跨域的訪問。
CORS設定:
修改一下hosts,模擬兩個不同的站點:
192.168.10.103 www.test.com 192.168.10.103 www.hack.com
按照自己的情況修改ip,
如果跨站請求成功會顯示success,
被請求的url,http://www.test.com/test/test.php
<?php
echo 'success'; ?>
發起跨域請求的url,http://www.hack.com/test/1.html
<!DOCTYPE> <html> <p>Hello<p> <script type="text/javascript"> function test() { var ajax = new XMLHttpRequest(); ajax.onreadystatechange=function() { if(ajax.readyState == 4 && ajax.status == 200) { var text = ajax.responseText; document.write(text) } } ajax.open("GET","http://www.test.com/test/test.php","true") ajax.send(); } test(); </script> </html>
在hack.com的頁面上請求test.com的資源:
顯示禁止跨域發出xmlhttprequest請求
<?php header('Access-Control-Allow-Origin:http://www.hack.com'); echo 'success'; ?>
加入Access-Control-Allow-Origin欄位允許hack.com的源跨站請求資源。
跨站訪問成功。
當我們把Access-Control-Allow-Origin改為http://www.a.com時:
又失敗了。
漏洞的產生
漏洞產生的原因可分為兩個,它們的原因都出在Access-Control-Allow-Origin上,當配置為星號*時,來自任何一個域名上的指令碼都可以請求這個頁面上的所有資訊,相當於手動禁止了同源策略,這個原因的可能性極小,因為除非是一個全無經驗的人,否則沒有人會將其設定為*。另一個原因出現的機率就遠遠大於第一個了,其原因為由程式設計師的大意或疏忽導致匹配的不嚴謹。
不完全匹配:
這種問題是由於當按一定的規則來確認發起跨域請求的源是否應該允許訪問時,匹配的規則有紕漏,只確認了其中某一部分符合規則就認為源一定是可信任的,例如:
將http://www.test.com/test/test.php進行更改
<?php $origin = $_SERVER['HTTP_ORIGIN']; $pattern = '#www.a.com#'; preg_match($pattern,$origin,$match); if ($match) { header('Access-Control-Allow-Origin:'.$origin); } echo 'success'; ?>
這段程式碼中,只要匹配到www.hack.com,並沒有確認其他部分的內容就簡單的判斷允許跨域請求,當攻擊者使用 www.a.com.hack.com 時,很容易就騙過了規則,成功發起跨域請求並接收。
再舉個例子,當匹配規則為確認 a.com 在Origin末尾時才允許訪問,顯然上面一個例子中的方法不再適用,這時仍可以構造 bbbbbbba.com 這樣的域名來突破限制。
道高一尺魔高一丈,匹配規則有很多,突破方法有更多,這裡就不一一列舉了。
沒有轉義:
當用正規表示式進行匹配時,URI中存在著許多點 . 像 bp.a.com , tieba.baidu.com , www.billbill.com 小數點.這個符號在正規表示式可以代替著任意一個字元,如果想讓其僅僅代表.這個符號本身而不是匹配任何一個字元的話,應當使用轉義符\. ,但很多人往往總會忘記轉義,如在上述的程式碼中就沒有進行轉義:
http://www.test.com/test/test.php中注意:
$pattern = '#www.a.com#';
當我們使用 www.aacom.com , www.wwwaaacom.com , www.wwwaa.com 在 . 的位置隨意寫上一個字元就可以突破限制,正確寫法應該是www\.a\.com
當頭設定了Access-Control-Allow-Credentials:true時,恰巧產生了CORS漏洞,危害會大大增加,因為向其發起跨域請求時,它會將cookie一起傳送,這是及其不希望看到的,也是非常危險的,讀取了頁面上的一些資訊有時或許無傷大雅,但讀取了cookie很多時候都是非常恐怖的。
漏洞檢測與利用
CORS漏洞會加強xss的攻擊力,哪怕是反射型的xss也增加了許多可能性。
檢測CORS的方式可以通過不斷修改Origin,檢測響應中的Access-Control-Allow-Origin的值是否與Origin相同,如若相同,則存在CORS漏洞,github上有一個CORS漏洞的檢測工具CORScanner,當檢測到CORS時,可以這樣利用:
<script> var ajax = new XMLHttpRequest(); ajax.open('GET','http://xxx','true'); ajax.onload = main; ajax.withCredentials = true; ajax.send() function main(){ xxx }
其中,ajax.withCredentials = true;這一段程式碼的作用是將Access-Control-Allow-Credentials:true設定為true以允許讀取cookie,提升危害,main中寫入可以讀取敏感資料birucookie並將其傳送給攻擊者的程式碼,誘使受害者執行這段程式碼,就可以達到獲取重要資訊的目的。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
總體來說,CORS漏洞現在看來危害並不是特別大,但是千里之堤潰於蟻穴,無論怎樣的漏洞都要有足夠的重視,既是對自己負責,也是對他人負責、