GET來的漏洞

wyzsk發表於2020-08-19
作者: 呆子不開口 · 2015/07/15 10:04

0x00 前言


這篇文章主要講目前網際網路上get方法被不規範使用帶來的一些安全漏洞。其中重點會講get請求在賬號登陸體系中被濫用的場景和攻擊方式。

0x01 Get方法的定義


在客戶機和伺服器之間進行請求-響應時,兩種最常被用到的方法是:GET 和 POST

GET - 從指定的資源請求資料 
POST - 向指定的資源提交要被處理的資料

GET 方法的查詢字串是在 GET 請求的 URL 中傳送的,常見的場景是位址列請求和超連結。

0x02 Get請求常見於如下場景中


  • 瀏覽器位址列中可見,會被別人看到
  • 瀏覽器歷史記錄
  • 被雲加速的cdn服務商收集,proxy
  • 被運營商或網路裝置收集重放
  • 在不安全的網路環境中被網路嗅探
  • 使用者的收藏夾
  • http的header的referrer欄位中
  • web伺服器日誌、應用日誌
  • 被搜尋引擎爬到,或者被客戶端軟體不規範收集
  • 被使用者郵件或微信分享出去
  • 各種可能的地方,甚至山崗上田野上(一個駭客盜取了你的get請求後,路過一個山崗時,被大灰狼吃掉了,隨身碟掉在了山崗上)

0x03 Get請求的風險


根據HTTP規範,GET用於資訊獲取,是安全的和冪等的。安全的意思是get請求不會讓服務端的資源或狀態改變。冪等的意思是無論請求多少次,返回的結果都一樣,都不會對服務端資源有任何副作用。

所以從被設計和現實中被使用的場景來看,get請求有如下特性

  • 因為是獲取資源的請求,所以會在客戶端、快取端和伺服器端等地方到處出現,容易洩露被第三方獲得
  • 因為是安全和冪等的,所以各環節重放get請求時不用顧忌,不用提示使用者。重放post有時瀏覽器會提示使用者是否確定要重新傳送資料

所以get請求的使用應該遵循

  • 不應有增刪改的操作
  • 不應包含敏感資訊

當你的實現不符合別人對你的預期,就可能產生漏洞,如

  • 隱私洩露,被csrf漏洞利用,賬號被盜……

0x04 若你非要用get實現增刪改


會被重放,導致服務端資源狀態發生改變

  • 瀏覽器的重新開啟可能會重放請求,而不會提示使用者
  • 爬蟲或安全掃描會重放你的請求
  • 獲取到你get請求的各種勢力可能會重放此請求,如安全廠商,搜尋引擎,神秘力量(除了山崗上那個駭客,因為他已經被大灰狼吃掉了)

get操作的csrf防護很難實施,因為get沒有防偽造的需求,它的場景不一定配合你的防護。referrer信任可能被利用,token可能被偷。舉個例子,一個塑膠盒子,它本就不是被設計用來存錢的,你若非要用它存錢,並還要加上一把鎖,效果肯定不會好。見下面例子:

  • 網站允許使用者發表第三方連結、圖片等,那麼使用者構造的csrf請求的referrer是可信域的url,可以繞過referrer的防護
  • 存在js端的跳轉漏洞跳到第三方,同理可以繞過referrer
  • Get請求中防護的token容易被偷,原理同上,後面的章節會細講

常見的場景:一些使用了mvc框架的程式,直接用urlrewrite後的url來實現了增刪改等操作

0x06 若你非用get傳輸敏感資訊


網際網路上常見的敏感資訊舉例:

隱私資訊

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請求中包含如上一些資訊,那麼你的敏感資訊將會被偷被洩露,然後你會被搞!!!

0x07 敏感資訊洩露舉例


隱私資訊洩露舉例

enter image description here

使用者登入微博後,首頁的url會含有使用者ID資訊。所以timeline上的連結的主人會透過referrer知道哪些使用者訪問了它。可能大家都不會在意,它可能會幫你逮微博馬甲、捉姦在網……

比如如下場景:

某天你男友出差,長夜漫漫,你很無聊,寫了一篇部落格,記錄下了盛夏夜中你此刻的心情。喝完咖啡,你正打算上床睡覺了,突然你又好奇想知道自己青春的文采已被多少人閱讀。於是你開啟電腦,登上伺服器,去檢視你部落格的訪問日誌,從referrer中你發現,你的男朋友和你的男同事在凌晨一點,都訪問了你發的連結,並且IP一樣。這個時候,作為一個男子漢,你可能要考慮下,應該哭多大聲才不會吵到鄰居……當然,你還可以安慰自己,他們是一起在網咖通宵玩遊戲

我還曾經用此方法幫人揪出了一些人的微博馬甲。只要你夠無聊,你還可以玩些別的,比如在使用者開啟的頁面上再放上些興趣愛好治病尋醫類的廣告,如果他點了,你就可能會知道她平時愛逛的是不是三里屯的優衣庫了。

我不清楚微博的首頁地址為何要這樣設計,服務端若要讀當前使用者id,完全從當前會話中就可讀取,而且從安全的角度考慮,也不應該會從url中讀取使用者id資訊。那為什麼要顯示使用者的id呢…

token資訊洩露舉例

enter image description here

如上圖,這是微信公眾平臺後臺管理員點選了網友發來的資訊後的開啟第三方頁面的請求,referrer欄位中的url中包含了管理後臺的csrf防護的token

微信公眾後臺的操作大多是post,csrf的防護有token和referrer,但在每個頁面的get請求中,也會含有這個token。這樣的話token很容易被referrer偷,見上圖,token已經發給了第三方域了。這樣csrf的防護體系就被削弱了

順便說一句,這個後臺是https的,所以我們的連結也要是https的才會傳送referrer。在網上申請個免費的https站點即可

好在這個問題目前沒什麼危害,管理後臺的csrf防護是referrer和token都做了的,而且使用者想給公眾號發一個連結需要一些小技巧,直接發連結在後臺是不可以形成連結的。

認證資訊洩露舉例——被referrer發到第三方

enter image description here

上圖是現在的烏雲的廠商使用者的檢視漏洞詳情的臨時頁面,原來的頁面是沒有檢視密碼的,是可以透過位址列裡那個含有auth資訊的get請求直接檢視漏洞詳情的

但某一漏洞詳情頁包含了一個優酷的影片,這個檢視詳情的連結會在優酷的影片頁顯示。因為優酷為了告訴使用者展示來源,顯示了referrer資訊。這樣這個漏洞詳情的臨時檢視頁面就可以被網友在網上無意撞見了,廠商的漏洞詳情可能會被提前洩露。見下圖

enter image description here

詳情可參考 WooYun: 烏雲某臨時授權檢視連結在某些極小可能性下有洩露的可能

然後我想看看這個檢視漏洞的授權頁在網上洩露了多少,去百度搜了下

enter image description here

enter image description here

一個月內洩露的烏雲廠商使用者的臨時檢視連結竟然有十二頁之多,我覺得應該不可能全是廠商管理員分享出去的。所以我有了一個猜測,不一定是錯的,那就是:烏雲的所有get請求都已被百度雲加速收集,用來幫助使用者進行搜尋的seo最佳化。

0x08 偷最敏感的資訊——認證資訊


使用get請求認證的一些場景

  • 單點登陸從sso拿ticket資訊,引數名如ticket、auth
  • 網站繫結第三方賬號登陸,由第三方給的登陸憑證
  • App給內嵌頁面請求加上認證資訊,引數名如sid、gsid

Xss偷不了httponly的cookie了?

  • 你可以試試偷上面的這些認證資訊
  • Xss能做的比你想象的要多,它畢竟是個程式碼執行漏洞
  • 如果Xss不好找?你還可以試試referrer,它不產生漏洞,但它是漏洞的搬運工

首先我們瞭解些背景知識,我簡單介紹下單點登陸

  • 需求:如果使用者已經登陸B站,則自動登陸A站
  • 實現:使用者訪問A站,A站把使用者跳轉到B站,B站驗證使用者已登陸,給使用者一張票,使用者拿著票去找A站,A拿著票去B那,驗證成功後放使用者進去

下文中將大量出現如下示例站點

  • A:http://www.t99y.com
  • B:http://passport.wangzhan.com

舉例:使用者訪問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資訊

enter image description here

0x09 How


網際網路上常見的幾個單點登陸場景,通行證或第三方站給的登陸憑的證使用的方式各有不同,分別該怎麼偷

場景一,直接使用票據來做驗證,get型csrf的token和此類似

http://t99y.com/a.php?ticket=XXXXXXXXXXXXXXXX

服務端使用此ticket去sso驗證此使用者身份,然後在本域種認證cookie

偷的思路:

讓我們構造的頁面獲取到憑證後請求我們控制的伺服器上的資源,這樣referrer裡就有ticket資訊了

偷的幾種方式

  • 找能發自定義src的圖片的頁面去sso取票,帶著ticket資訊的頁面會發起圖片請求,圖片服務是我們自己的,我們可以讀到請求中的referrer,referrer中會包含ticket資訊
  • 找能發自定義src的iframe的頁面,iframe請求中的referre有ticket
  • 找一個有js跳轉漏洞的頁面去取票,跳轉目的地址是我們的服務,js的跳轉是帶上referrer的,讀取此請求的referrer,裡面包含ticket
  • 如果img和iframe的src值只允許白名單域的url,那就再找一個白名單域的302跳轉漏洞來繞過白名單,302跳轉可以傳遞上個請求的referrer
  • Xss獲取位址列資訊

示意圖如下,如下是我畫的一個chrome瀏覽器,位址列裡ticket引數會被包含到下面的一些元素的請求的referrer中

enter image description here

參考案例: 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跳轉可以幫我們實現

偷的幾種方式

  • 找一個有302跳轉漏洞的頁面如b.php,發起單點登陸請求,然後帶著ticket資訊的b.php會跳轉到我們的服務上。因為js的跳轉會帶referrer,然後再透過302跳轉把referrer傳給我們能控制的頁面
  • Xss獲取當前頁面referrer

場景四,中間頁接收ticket完成認證,然後用302跳轉到我們的目標頁http://t99y.com/login.php?ticket=XXXXXXXXXXXXXXXX&url=http://t99y.com/a.php 此時會種上認證cookie

然後頁面會再302跳轉到 http://t99y.com/a.php

參考示例:好幾個大的網際網路網站……

偷的幾種方式

  • 前面的一些靠referrer偷的方式都沒法用了……
  • 只能靠xss了,不要小看xss,不要光知道偷cookie

這種情況是多個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超長的拒絕服務終於可以派上用場了

偷的方式

  • Xss建立iframe,種超長cookie,讓含ticket的302拒絕服務,然後使用iframe.contentWindow.location.href讀取最後的iframe的當前地址

拒絕服務還有個好處,可以繞過某些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端均可兩個漏洞一併提交)

偷的幾種方式

  • 可能存在jsonp劫持漏洞,可以透過jsonp劫持來偷取使用者的登陸憑證
  • Xss漏洞,去跨域請求此介面得到資料

0x0a 總結


綜上所述,get請求的濫用大家都沒重視過,但綜合一些小漏洞,可能會產生一些意想不到的大漏洞

修復方案其實很簡單,不要使用get方法進行非讀操作,不要使用get方法傳輸敏感資訊,因為你不可能控制你所有頁面不向第三方發起帶referrer的資源請求,而且get請求很難保護。它只是個天真爛漫的孩子,你不要讓它承載太多責任

在前幾天的阿里安全峰會上,我講了這個議題,最後的觀眾提問環節有人問使用https可不可以解決上面的問題。答案當然是不可以,https解決的只是客戶端到服務端的傳輸加密防篡改。但get請求的資料在兩個端,尤其是客戶端,https是保護不了的。

至於單點登入問題的修復方案,有很多層面都可以去解決,比如不使用get,不讓攻擊者發起偽造的單點登入請求等等, 這些細節需要具體問題具體對待,這裡就不細講了。有需求的女網友可以私下找我交流,共同為網際網路的安全學習進步

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章