這篇文章主要講目前互聯網上get方法被不規范使用帶來的一些安全漏洞。其中重點會講get請求在賬號登陸體系中被濫用的場景和攻擊方式。
在客戶機和服務器之間進行請求-響應時,兩種最常被用到的方法是:GET 和 POST
GET - 從指定的資源請求數據
POST - 向指定的資源提交要被處理的數據
GET 方法的查詢字符串是在 GET 請求的 URL 中發送的,常見的場景是地址欄請求和超鏈接。
根據HTTP規范,GET用于信息獲取,是安全的和冪等的。安全的意思是get請求不會讓服務端的資源或狀態改變。冪等的意思是無論請求多少次,返回的結果都一樣,都不會對服務端資源有任何副作用。
所以從被設計和現實中被使用的場景來看,get請求有如下特性
所以get請求的使用應該遵循
當你的實現不符合別人對你的預期,就可能產生漏洞,如
會被重放,導致服務端資源狀態發生改變
get操作的csrf防護很難實施,因為get沒有防偽造的需求,它的場景不一定配合你的防護。referrer信任可能被利用,token可能被偷。舉個例子,一個塑料盒子,它本就不是被設計用來存錢的,你若非要用它存錢,并還要加上一把鎖,效果肯定不會好。見下面例子:
常見的場景:一些使用了mvc框架的程序,直接用urlrewrite后的url來實現了增刪改等操作
互聯網上常見的敏感信息舉例:
隱私信息
http://weibo.com/lvwei
大家可能覺得微博id不算隱私,但一旦你的id和某些操作綁定的時候,那就算是隱私了
校驗信息
https://mp.weixin.qq.com/cgi-bin/home?t=home/index&lang=zh_CN&token=371767643
這是微博公眾平臺管理后臺的首頁,首頁url里會包含csrf防護的token
認證信息
http://XXX.XXXXXX.XXX/index.php?ticket=*****************
http://XXX.XXXXXX.XXX/index.php?gsid=******************
很多登錄認證如單點登錄,綁定第三方賬號登錄等會用get請求來完成登錄
如果你的get請求中包含如上一些信息,那么你的敏感信息將會被偷被泄露,然后你會被搞!!!
隱私信息泄露舉例
用戶登錄微博后,首頁的url會含有用戶ID信息。所以timeline上的鏈接的主人會通過referrer知道哪些用戶訪問了它。可能大家都不會在意,它可能會幫你逮微博馬甲、捉奸在網……
比如如下場景:
某天你男友出差,長夜漫漫,你很無聊,寫了一篇博客,記錄下了盛夏夜中你此刻的心情。喝完咖啡,你正打算上床睡覺了,突然你又好奇想知道自己青春的文采已被多少人閱讀。于是你打開電腦,登上服務器,去查看你博客的訪問日志,從referrer中你發現,你的男朋友和你的男同事在凌晨一點,都訪問了你發的鏈接,并且IP一樣。這個時候,作為一個男子漢,你可能要考慮下,應該哭多大聲才不會吵到鄰居……當然,你還可以安慰自己,他們是一起在網吧通宵玩游戲
我還曾經用此方法幫人揪出了一些人的微博馬甲。只要你夠無聊,你還可以玩些別的,比如在用戶打開的頁面上再放上些興趣愛好治病尋醫類的廣告,如果他點了,你就可能會知道她平時愛逛的是不是三里屯的優衣庫了。
我不清楚微博的首頁地址為何要這樣設計,服務端若要讀當前用戶id,完全從當前會話中就可讀取,而且從安全的角度考慮,也不應該會從url中讀取用戶id信息。那為什么要顯示用戶的id呢…
token信息泄露舉例
如上圖,這是微信公眾平臺后臺管理員點擊了網友發來的信息后的打開第三方頁面的請求,referrer字段中的url中包含了管理后臺的csrf防護的token
微信公眾后臺的操作大多是post,csrf的防護有token和referrer,但在每個頁面的get請求中,也會含有這個token。這樣的話token很容易被referrer偷,見上圖,token已經發給了第三方域了。這樣csrf的防護體系就被削弱了
順便說一句,這個后臺是https的,所以我們的鏈接也要是https的才會發送referrer。在網上申請個免費的https站點即可
好在這個問題目前沒什么危害,管理后臺的csrf防護是referrer和token都做了的,而且用戶想給公眾號發一個鏈接需要一些小技巧,直接發鏈接在后臺是不可以形成鏈接的。
認證信息泄露舉例——被referrer發到第三方
上圖是現在的烏云的廠商用戶的查看漏洞詳情的臨時頁面,原來的頁面是沒有查看密碼的,是可以通過地址欄里那個含有auth信息的get請求直接查看漏洞詳情的
但某一漏洞詳情頁包含了一個優酷的視頻,這個查看詳情的鏈接會在優酷的視頻頁顯示。因為優酷為了告訴用戶展示來源,顯示了referrer信息。這樣這個漏洞詳情的臨時查看頁面就可以被網友在網上無意撞見了,廠商的漏洞詳情可能會被提前泄露。見下圖
詳情可參考 WooYun: 烏云某臨時授權查看鏈接在某些極小可能性下有泄露的可能
然后我想看看這個查看漏洞的授權頁在網上泄露了多少,去百度搜了下
一個月內泄露的烏云廠商用戶的臨時查看鏈接竟然有十二頁之多,我覺得應該不可能全是廠商管理員分享出去的。所以我有了一個猜測,不一定是錯的,那就是:烏云的所有get請求都已被百度云加速收集,用來幫助用戶進行搜索的seo優化。
使用get請求認證的一些場景
Xss偷不了httponly的cookie了?
首先我們了解些背景知識,我簡單介紹下單點登陸
下文中將大量出現如下示例站點
舉例:用戶訪問http://passport.wangzhan.com/login.php?url=http://www.t99y.com/a.php
B站檢驗A站是白名單域后,然后302跳轉到
http://www.t99y.com/a.php?ticket=******
然后a.php用ticket參數去B站驗證用戶合法后,再給用戶種認證cookie
偷認證信息的大概流程如下,后面會細講。總之攻擊的目的就是,拿到用戶的ticket信息
互聯網上常見的幾個單點登陸場景,通行證或第三方站給的登陸憑的證使用的方式各有不同,分別該怎么偷
場景一,直接使用票據來做驗證,get型csrf的token和此類似
http://t99y.com/a.php?ticket=XXXXXXXXXXXXXXXX
服務端使用此ticket去sso驗證此用戶身份,然后在本域種認證cookie
偷的思路:
讓我們構造的頁面獲取到憑證后請求我們控制的服務器上的資源,這樣referrer里就有ticket信息了
偷的幾種方式
示意圖如下,如下是我畫的一個chrome瀏覽器,地址欄里ticket參數會被包含到下面的一些元素的請求的referrer中
參考案例: WooYun: 微博上你點我發的鏈接我就可以登上你的微博(web版和app端均可兩個漏洞一并提交)
場景二,當我們在一個app內打開其公司產品的一些鏈接,會被加上認證信息去讓用戶自動登陸
偷的幾種方式
見場景一的各種方式
用戶甚至會通過app的分享功能把認證信息分享到郵件或朋友圈。曾經遇過一個案例,一個活動推廣頁面在app內被打開后,被app加上了get參數去完成了自動登陸,因為頁面要得到用戶的一些相關信息。然后這個帶著認證參數的推廣頁面會被用戶分享出去,然后別人點擊了這個鏈接,就登陸了分享人的賬號
場景三,中間頁接收ticket完成認證,然后用js跳轉到我們的目標頁http://t99y.com/login.php?ticket=XXXXXXXXXXXXXXXX&url=http://t99y.com/a.php 此時會種上認證cookie
然后頁面會使用js跳轉到 http://t99y.com/a.php
location.href=“http://t99y.com/a.php”;
參考示例:某綁定了微博賬號后可以自動登陸的網站
偷的思路:
因為js的跳轉,ticket已經通過referrer發給了a.php了,那我們只要讓a.php成為我們控制的頁面就可以了,恰好302跳轉可以幫我們實現
偷的幾種方式
場景四,中間頁接收ticket完成認證,然后用302跳轉到我們的目標頁http://t99y.com/login.php?ticket=XXXXXXXXXXXXXXXX&url=http://t99y.com/a.php
此時會種上認證cookie
然后頁面會再302跳轉到 http://t99y.com/a.php
參考示例:好幾個大的互聯網網站……
偷的幾種方式
這種情況是多個302的跳轉,跳轉路徑如下
請求1:http://passport.wangzhan.com/login.php?url=http://www.t99y.com/a.php
請求2:http://t99y.com/login.php?ticket=XXXXXXXXXXXXXXXX&url=http://t99y.com/a.php
請求3:http://t99y.com/a.php
偷的思路:
在xss中,用iframe包含單點登錄的請求1,登錄跳轉后,我們通過src屬性可以讀到請求1的url,使用iframe.contentWindow.location.href可以讀到跳轉最后的請求3的url。但我們需要的是中間的請求2。所以我們想,可不可以讓它跳到請求2后,不再繼續跳轉了,這樣我們通過iframe.contentWindow.location.href就可以讀到請求2的url了。這時候我想起,cookie超長的拒絕服務終于可以派上用場了
偷的方式
拒絕服務還有個好處,可以繞過某些ticket的防重放。因為有些票據在受害者端只要被使用后,可能我們盜取后也無法利用了。使用這種方式偷,可以讓票據在受害者端不會被使用。
還有,根據path設置cookie可以精準的讓我們的iframe停在我們想讓它停的url上。
示例代碼如下:
#!javascript
var iframe =document.createElement('iframe');
iframe.src="http://passport.wangzhan.com/login.php?url=http://www.t99y.com/a.php";
document.body.appendChild(iframe);
for (i = 0; i < 20; i++) {
document.cookie = i + ‘=’ + ‘X’.repeat(2000);//可以根據需求設置path
}
iframe.addEventListener('load', function(){
document.write(iframe.contentWindow.location.href);
for (i = 0; i < 20; i++) {
document.cookie = i + '=' + 'X';
}
}, false);
場景五,跨域從通行證獲取登陸ticket
形式為類似http://www.wangzhan.com/sso/getst.php?callback=jsonp
,然后通行證會返回個jsonp格式的數據,里面包含認證信息
參考案例 WooYun: 微博上你點我發的鏈接我就可以登上你的微博(web版和app端均可兩個漏洞一并提交)
偷的幾種方式
綜上所述,get請求的濫用大家都沒重視過,但綜合一些小漏洞,可能會產生一些意想不到的大漏洞
修復方案其實很簡單,不要使用get方法進行非讀操作,不要使用get方法傳輸敏感信息,因為你不可能控制你所有頁面不向第三方發起帶referrer的資源請求,而且get請求很難保護。它只是個天真爛漫的孩子,你不要讓它承載太多責任
在前幾天的阿里安全峰會上,我講了這個議題,最后的觀眾提問環節有人問使用https可不可以解決上面的問題。答案當然是不可以,https解決的只是客戶端到服務端的傳輸加密防篡改。但get請求的數據在兩個端,尤其是客戶端,https是保護不了的。
至于單點登錄問題的修復方案,有很多層面都可以去解決,比如不使用get,不讓攻擊者發起偽造的單點登錄請求等等, 這些細節需要具體問題具體對待,這里就不細講了。有需求的女網友可以私下找我交流,共同為互聯網的安全學習進步