作者:知道創宇404實驗室 kuipla、Billion
時間:2022年05月10日

2022/5/4日F5官方發布一個關于BIG-IP的未授權RCE(CVE-2022-1388)安全公告,官方對該漏洞的描述是Undisclosed requests may bypass iControl REST authentication.,修復方式中提到了低版本可以將非Connection:keep-aliveConnection:close的請求全部關閉。

0x00 補丁分析

由于BIG-IP的框架依舊有大佬分析過了,因此我們直接根據去尋找apache的認證服務mod_pam_auth.so以及mgmt轉發的8100端口對應的認證/usr/share/java/rest/目錄下發生改變的jar包上。

mod_pam_auth.so

在ida中使用bindiff插件對比新舊兩個so文件,能夠發現只有sub_5EF0和5AF0改動比較大

接下來用ida把這兩個函數反編譯出來進行對比,主要修改位置有以下兩處

1652163870393

此處是將非Connection:keep-aliveConnection:close的請求頭清除。

1652163906623

此處是對X-F5-Auth-Token進行了驗證,而不是之前簡單判斷了下是否賦值。

測試發現確實可以bypass apache認證

添加xf5頭

icrd.jar&f5.rest.jar

通過對icrd/com/f5/mgmt/tm/common/WellKnownPorts.class的路由分析以及鑒權的com/f5/rest/app/RestServerServlet.class進行前后對比,我們發現一個很奇怪的事情,鑒權部分的代碼并未進行大的更改,也就是說apache的請求走私可以bypass掉jetty的認證。

總結

猜測Connection頭請求走私可以bypass jetty的認證。

根據官方的描述和推特上的討論,我們一開始是認為這個洞是由CVE-2021-22986的SSRF帶出cookie的bypass。因為一般的請求走私是CL-CL,CL-TE,TE-CL,TE-TE,但因為BIG-IP使用的apache不支持 Transfer-Encoding,因此我們猜測走私的原因放到了Content-Length上走私請求到一個未授權的接口獲取SSRF。

后面卡了很久也沒找到這個"不存在的接口",最后才發現是hop-by-hop導致的問題。

關于hop-by-hop是在這里導致的權限bypass我們放到下面細講。

0x01 漏洞分析

首先我們先來看如果要Bypass掉Apache的認證怎么做,根據官方的補丁,只要符合X-F5-Auth-Token不為空即可,并且mod_pam_auth.so是先判斷X-F5-Auth-Token后再判斷Authorization的值,這給了hop-by-hop一個很大的操作空間。

那么剩下的就是jetty的認證,jetty的認證只要由組成X-F5-Auth-Token和Authorization組成。由于鑒權部分并未做太大改動,因此我們簡單描述下兩者是如何進行檢驗的。

X-F5-Auth-Token

com/f5/rest/workers/EvaluatePermissions.class#evaluatePermission

1652165675577

請求最后會被送到/shared/authz/tokens/進行驗證,由于跟CVE-2022-1388關系不大就不繼續跟下去了。

Authorization

Authorization的鑒權非常奇怪,Authorization是由authn進行的驗證,之前了解過CVE-2021-22986肯定知道這里之前只鑒權了用戶名是否存在,因為admin一定存在,只要將Auth設置為YWRtaW46就行。

補丁的是檢測了X-Forwarded-Host不為本地的Basic Auth header的賬號密碼,但X-Forwarded-Host為本地IP依舊只檢測了賬戶名是否正確。

com/f5/rest/common/RestOperationIdentifier.class#setIdentityFromBasicAuth

1652167398489

那么這個X-Forwarded-Host是怎么賦值的呢,很明顯已公開的poc中并沒有直接在header中添加X-Forwarded-Host,其實這個字段是由apache整出來的,后面提到的變形poc中會講解怎么利用,這里由于逆向能力不強就不獻丑了。

在最新版測試發現這個問題依舊存在,猜測可能是環境內部的一些其他認證需求導致的這個問題。

1652162299142

hop-by-hop

hop-by-hop簡單的說就是將可以在Connection: Keep-Alive后面再加一個字段,這個字段在經過代理服務器轉發后會被刪除。理論上東西的危害非常有限,甚至于說不能算漏洞。

但是在BIG-IP的環境下,有一個非常罕見的系統流程路徑可以經過hop-by-hop產生RCE。

讓我們回顧一下整個系統的認證流程,apache是檢查Authorization的正確性,但只檢測X-F5-Auth-Token是否為空,并且優先檢查X-F5-Auth-Token。Jetty同樣優先檢查X-F5-Auth-Token的正確性,但只檢查Authorization是否是合法用戶名。

那么只要我們設置Host為localhost,X-F5-Auth-Token不為空,Authorization設置為YWRtaW46Connection: Keep-Alive, X-F5-Auth-Token就可以繞過apache的檢查,同時apache還會貼心的幫我們刪去X-F5-Auth-Token,把請求直接送到Authorization的驗證,從而實現bypass。

0x02 一些poc的變種

經過我們的測試發現兩種poc變種

  1. 寫兩個X-F5-Auth-Token:也能繞過apache的檢測

  2. 同時由于hop-by-hop的原因,即使apache刪除了header中的X-Forwarded-Host,但如果我們用Connection: Keep-Alive, X-F5-Auth-Token, X-Forwarded-Host,那么我們設置的X-Forwarded-Host依舊生效,這樣Host就不必必須為localhost了

參考鏈接

https://book.hacktricks.xyz/pentesting-web/abusing-hop-by-hop-headers

https://blog.riskivy.com/f5%E4%BB%8E%E8%AE%A4%E8%AF%81%E7%BB%95%E8%BF%87%E5%88%B0%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90

https://support.f5.com/csp/article/K23605346


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1893/