作者:知道创宇404实验室 kuipla、Billion
2022/5/4日F5官方发布一个关于BIG-IP的未授权RCE(CVE-2022-1388)安全公告,官方对该漏洞的描述是Undisclosed requests may bypass iControl REST authentication.
,修复方式中提到了低版本可以将非Connection:keep-alive
和Connection: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把这两个函数反编译出来进行对比,主要修改位置有以下两处
此处是将非Connection:keep-alive
和Connection:close
的请求头清除。
此处是对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
请求最后会被送到/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
那么这个X-Forwarded-Host是怎么赋值的呢,很明显已公开的poc中并没有直接在header中添加X-Forwarded-Host,其实这个字段是由apache整出来的,后面提到的变形poc中会讲解怎么利用,这里由于逆向能力不强就不献丑了。
在最新版测试发现这个问题依旧存在,猜测可能是环境内部的一些其他认证需求导致的这个问题。
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设置为YWRtaW46
,Connection: Keep-Alive, X-F5-Auth-Token
就可以绕过apache的检查,同时apache还会贴心的帮我们删去X-F5-Auth-Token
,把请求直接送到Authorization
的验证,从而实现bypass。
0x02 一些poc的变种
经过我们的测试发现两种poc变种
- 写两个
X-F5-Auth-Token:
也能绕过apache的检测 - 同时由于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