作者:Y4er
原文鏈接:https://y4er.com/post/from-hop-by-hop-to-cve-2022-1388/

前言

最近爆出來的bigip的CVE-2022-1388漏洞,涉及到一個知識點就是hop by hop,對這個東西沒了解過,所以有了此文。

回顧CVE-2021-22986

CVE-2021-22986原理是因為apache和jetty之間的鑒權不當導致的權限繞過。

當不存在Authorization basic認證頭時,由apache做權限校驗,判斷basic認證頭是否存在,此時response中的server頭為apache

1.png

當給一個錯誤的basic認證頭時仍返回apache的401認證,注意這里給的是一個admin:空密碼的admin用戶。

2.png

當給一個空的X-F5-Auth-Token認證頭時,由jetty處理返回401,報錯信息為Authorization failed: no user authentication header or token detected.

3.png

當兩個請求頭都存在時,繞過了權限校驗,rce。

4.png

由此得出結論,當存在X-F5-Auth-Token頭時apache不檢查basic認證頭,而jetty只會判斷用戶名,而不判斷密碼是否正確。

思考為什么權限校驗不起作用?

查看apache的配置文件/config/httpd/conf/httpd.conf發現

5.png

/mgmt/請求被轉發到8100端口,并且啟用了AuthPAM_Enabled,啟用auth會調用/usr/lib/httpd/modules/mod_auth_pam.so判斷鑒權,在這個so中

6.png

判斷是否存在X-F5-Auth-Token頭

7.png

然后接著拿一些其他的請求頭

8.png

最終邏輯就是如果存在轉發給jetty處理。

而在jetty中 f5.rest.jar

com.f5.rest.workers.authz.AuthzHelper#decodeBasicAuth

9.png

從header中拿到basic認證的用戶名和密碼,在com.f5.rest.common.RestOperationIdentifier#setIdentityFromBasicAuth中設置用戶身份

10.png

因為basic不為空,所以進入com.f5.rest.common.RestOperation#setIdentityData

11.png

因為 userName!=null && userReference==null,所以處理完之后用戶的身份變為

identityData.userName = 'admin';
identityData.userReference = 'http://localhost/mgmt/shared/authz/users/admin'
identityData.groupReference = null;

接著在鑒權的地方 com.f5.rest.workers.EvaluatePermissions#completeEvaluatePermission

12.png

setBasicAuthFromIdentity之后拿到userRef,此時userRef即上文處理完之后的用戶身份。在判斷AuthzHelper.isDefaultAdminRef(userRef)

13.png

先拿到默認的AdminReference和當前用戶身份匹配,在getDefaultAdminReference()中拿到admin用戶的身份new一個RestReference

14.png

UrlHelper.buildPublicUri(UrlHelper.buildUriPath(new String[]{WellKnownPorts.AUTHZ_USERS_WORKER_URI_PATH, DEFAULT_ADMIN_NAME}))`最終構建出來的url還是`http://localhost/mgmt/shared/authz/users/admin

所以此時我們在basic中將用戶名設置為admin則可以滿足defaultReference != null && defaultReference.equals(userReference)至此繞過權限認證。

然后就是找一個命令執行的點

15.png

對應的就是util下的路由功能點

16.png

調用bash執行命令即可

17.png

另外此處文檔中也有提到

https://f5-sdk.readthedocs.io/en/latest/_modules/f5/bigip/tm/util/bash.html

CVE-2021-22986的修復

在上文中,我們傳遞了一個X-F5-Auth-Token為空的header頭,所以completeEvaluatePermission函數會賦給我們一個默認的用戶身份。而修復補丁在mod_auth_pam.so判斷當X-F5-Auth-Token為空直接返回401

18.png

所以我們無法傳遞給jetty一個空的X-F5-Auth-Token請求頭。

那么CVE-2022-1388就是對其的繞過,這里引申出本文的重點hop by hop。

hop by hop

先解釋下這是什么東西。根據RFC 2612,HTTP/1.1 規范默認將以下標頭視為逐跳:Keep-Alive、Transfer-Encoding、TE、Connection、Trailer、Upgrade、Proxy-Authorization和Proxy-Authenticate。當在請求中遇到這些標頭時,代理服務器會處理這些標頭,并且不會將其轉發到下一個節點。

以推特@jinonehk的一張圖來看

19.png

第一次嘗試導出用戶時返回403,因為不是環路ip,而當加上Connection: close, X-Real-IP時,導出用戶成功,說明此時后端服務獲取不到X-Real-IP請求頭,認為是本地請求所以可以導出用戶。

更具體一點,我在這里找到了一個ctf的題目 https://github.com/ritsec/RITSEC-CTF-2019/tree/master/Web/hop-by-hop

在verify函數中嘗試獲取xff頭,如果獲取不到則默認為direct。

20.png

而前置服務為apache,根據逐跳原則,當Connection中加了其他標頭X-Forwarded-For,那么在apache轉發給下一跳時,會移除X-Forwarded-For頭,導致在verify函數中request.headers['X-Forwarded-For']拋出異常,由此拿到flag。

21.png

可以自己本地搭一個反代試試,我這有一個springboot的項目,只有一個controller

22.png

apache 80端口反代springboot 9091端口

先開啟反代功能

LoadModule proxy_module modules/mod_proxy.so

配置virtualhost

<VirtualHost *:80>
    ProxyRequests Off
    ProxyPreserveHost On
    <Proxy>
        Order deny,allow
        Allow from all
    </Proxy>
    ProxyPass /  http://localhost:9091
    ProxyPassReverse /  http://localhost:9091
</VirtualHost>

正常傳token,springboot可以獲取到token頭

23.png

當connection加上Token時,springboot獲取的token為null

24.png

由此可見CVE-2022-1388

CVE-2022-1388

在CVE-2022-1388中使用Connection加上X-F5-Auth-Token讓jetty接收到的X-F5-Auth-Token為null以此來繞過權限認證。

25.png

另外需要注意的一個地方為host賦值為localhost,不然host為ip時報錯

26.png

因為CVE-2021-22986之后,在com.f5.rest.common.RestOperationIdentifier#setIdentityFromBasicAuth

27.png

當host為localhost或者127.0.0.1時,會賦予用戶身份。另外這里還可以賦值host為127.4.2.1然后basic用戶名為f5hubblelcdadmin,或者通過Connection加上X-Forwarded-Host也可以rce,就不截圖了。

hop by hop的適用面

我本地測試了apache、nginx、openresty、HAProxy,其中只有apache會消費掉Connection中的請求頭,其他的要單獨測試了。

參考鏈接

看了太多資料了,用到了但是沒貼上來的請原作者見諒。

  1. 漏洞百出
  2. https://twitter.com/jinonehk/status/1420413477521301507
  3. https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers
  4. RFC 2616
  5. https://y4y.space/2021/03/19/cve-2021-22986-f5-rest-unauthenticated-rce-analysis/
  6. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection
  7. https://nosec.org/home/detail/4722.html

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