漏洞描述
F5官网发布安全公告,披露F5 BIG-IP存在一处远程代码执行漏洞(CVE-2022-1388)。漏洞存在于iControl REST组件中,该漏洞允许定义身份验证的攻击者通过 BIG-IP 管理界面和自身IP地址对 iControl REST API 接口进行网络访问,进而导致可以在目标主机上执行任意系统命令、创建或删除文件或禁用BIG-IP上的服务。
利用范围
BIG-IP 16.x: 16.1.0 - 16.1.2
BIG-IP 15.x: 15.1.0 - 15.1.5
BIG-IP 14.x: 14.1.0 - 14.1.4
BIG-IP 13.x: 13.1.0 - 13.1.4
BIG-IP 12.x: 12.1.0 - 12.1.6
BIG-IP 11.x: 11.6.1 - 11.6.5
环境搭建
登录F5 BUG-IP官网下载对应版本的F5 BUG-IP,这里选择的是15.x系列。
选择下载对应版本虚拟机ova包。
导入虚拟机。
在导入虚拟机时,需选择部署,这里根据电脑配置选择越大越好。导入之后,打开虚拟机,输入默认账号密码root/default登录,默认情况需强制修改密码,修改之后即可登录。
输入ifconfig mgmt查看IP,或者输入config配置IP。
在浏览器中访问即可访问登录界面。
环境搭建成功。
漏洞分析
在CVE-2021-22986中,F5是允许未经身份验证的攻击者,通过BIG-IP管理界面和自身IP地址对iControl REST接口进行网络访问,从而导致了命令执行。
那么此次,我们先在浏览器中访问漏洞接口/mgmt/tm/util/bash,使用用户名为admin,密码为空进行登录。
抓取登陆数据包,重新发包。
可以看到,此时的请求中是不存在X-F5-Auth-Token。
在添加上X-F5-Auth-Token并且使其为空时,从响应结果可以看到server为Apache,状态为401。
添加上X-F5-Auth-Token并且使其不为空时,server变为了Jetty,返回状态为401,返回结果为X-F5-Auth-Token does not exist。
由此可以得出结论,在CVE-2021-22986修复之后,会使用Apache去检查X-F5-Auth-Token是否存在,同时检查是否为空。当X-F5-Auth-Token存在且不为空时,后端才会进行Jetty认证,而在Jetty认证中,还存在一个对X-F5-Auth-Token是否合法的检查,如上图显示的X-F5-Auth-Token does not exist就是在Jetty认证中,我们的X-F5-Auth-Token不为空,但是随便输入的一个值,导致检测不通过,返回401。
回顾一下,在CVE-2021-22986中, Apache(模块为mod_pam_auth.so)进行第一次检查,这里是检查请求中是否存在X-F5-Auth-Token(不检查是否为空)。
那么在检测到X-F5-Auth-Token不为空时,在jetty中 f5.rest.jar中,将获取到basic认证的username和password。
com.f5.rest.workers.authz.AuthzHelper#decodeBasicAuth
此外在com.f5.rest.common.RestOperationIdentifier#setIdentityFromBasicAuth中,我们的basic认证的值不为空时。
进入到com.f5.rest.common.RestOperation#setIdentityData。
由于userName和userReference都不为空时,我们传入的是admin,那username就为admin,userReference的url为/mgmt/shared/authz/users/admin。
随后在com.f5.rest.workers.EvaluatePermissions#completeEvaluatePermission中。
setBasicAuthFromIdentity获取到用户身份。
在com.f5.rest.workers.authz.AuthzHelper#isLocalOrDefaultAdminRequest
当前用户身份匹配默认的匹配,在getDefaultAdminReference中拿到admin用户的身份new一个RestReference,而这个RestReference和之前我们获取的userReference是一样的,此时就完成了身份认证。
那么在进入com.f5.rest.workers.EvaluatePermissions#completeEvaluatePermission之前这里还存在了对X-F5-Auth-Token的值进行了检查。
com.f5.rest.workers.EvaluatePermissions#evaluatePermission
也就是当Apache检查X-F5-Auth-Token存在时,会转发给后端的 Jetty进行的第二次检查(检查X-F5-Auth-Token的值是否合法)。
从如上代码可以判断,Jetty 检查到X-F5-Auth-Token为空时,将直接忽略其提供的信息是否合法从而进入到com.f5.rest.workers.EvaluatePermissions#completeEvaluatePermission完成后面的身份验证,从而绕过权限认证。
那么分析到这里,CVE-2022-1388和CVE-2021-22986不同之处就是,在CVE-2021-22986之后官方进行了修复,让apache对X-F5-Auth-Token是否为空做了一次检查,如果存在且为空,就不会进入到Jetty认证;如果存在且不为空,则进入Jetty认证,并且Jetty会对X-F5-Auth-Token的值做出合法检查。
那么如何使得apache检测时X-F5-Auth-Toke存在不为空,传给Jetty检查时X-F5-Auth-Toke为空呢,这里就利用到了HTTP 的 hop-by-hop滥用漏洞。
参考:
参考文章后我们可以发现,如果请求中带有 HTTP 头Connection: close, X-Foo, X-Bar,Apache 会在请求转发到代理前,将X-Foo和X-Bar逐一删除。
所以CVE-2022-1388的利用,即是构造特殊请求(加上Connection:Keep-Alive,X-F5-Auth-Toke)去通过 Apache 的第一次检查,由于 hop-by-hop 滥用漏洞导致在进入 Jetty 前X-F5-Auth-Token头被删除。
漏洞复现
通过实战,在Connection头加上X-F5-Auth-Token,只有当host为localhost时,才会绕过认证,命令执行。
这是因为在com.f5.rest.common.RestOperationIdentifier#setIdentityFromBasicAuth中。
当host为localhost或者127.0.0.1时,会赋予用户身份。
解决方法就是在Connection再后加上X-Forwarded-Host,绕过认证,从而命令执行。
参考资料
1.
2. https://downloads.f5.com/esd/productlines.jsp
3. ?__biz=Mzg3MTU0MjkwNw==&mid=&idx=1&sn=52811f2a353bf61a756ddf0feb
4.