2020年07月08日, 360CERT监测发现 F5
官方更新了 F5 BIG-IP 远程代码执行
的风险通告,该漏洞编号为 CVE-2020-5902
,漏洞等级: 严重
。
未授权的远程攻击者通过向漏洞页面发送特制的请求包,可以造成任意 Java 代码执行。进而控制 F5 BIG-IP
的全部功能,包括但不限于: 执行任意系统命令、开启/禁用服务、创建/删除服务器端文件等,使用官方的httpd配置缓解修复方案仍可造成反序列化代码执行漏洞。该漏洞影响控制面板受影响,不影响数据面板。
对此,360CERT建议广大用户及时将 BIG-IP
按照修复建议升级到指定版本。与此同时,请做好资产自查以及预防工作,以免遭受黑客攻击。
首先,这里 F5
选择了 Apache
和 tomcat
服务器使用 ajp_proxy
模块进行通信, apache
处理完请求之后,通过 ajp
协议转发给 Tomcat
,默认是 8009
端口,来看一下关于漏洞的配置文件,
proxy_ajp.conf
ProxyPassMatch ^/tmui/(.*/.jsp.*)$ ajp://localhost:8009/tmui/$1 retry=5 ... ProxyPassMatch ^/hsqldb(.*)$ ajp://localhost:8009/tmui/hsqldb$1 retry=5
apache
的 httpd.conf
# # HSQLDB # <Location /hsqldb> <RequireAll> AuthType Basic AuthName "BIG/-IP" AuthPAM_Enabled on AuthPAM_IdleTimeout 1200 require valid-user Require all granted </RequireAll> </Location> <Location /tmui> # Enable content compression by type, disable for browsers with known issues <IfModule mod_deflate.c> AddOutputFilterByType DEFLATE text/html text/plain application/x-javascript text/css BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4/.0[678] no-gzip BrowserMatch /bMSIE !no-gzip !gzip-only-text/html </IfModule> <RequireAll> AuthType Basic AuthName "Restricted area" AuthPAM_Enabled on AuthPAM_ExpiredPasswordsSupport on AuthPam_ValidateIP On AuthPAM_IdleTimeout 1200 AuthPAM_DashboardTimeout Off require valid-user Require all granted </RequireAll> </Location>
Apache 处理 url
Apache httpd
将 URL
中的 ;
解释为用于路径解析的普通字符,而 Tomcat
将其解释为查询分隔符,也就如下面所说,相当于 ?
。
我们看一下 Tomcat
是如何解析 url
的,我们的测试 url
为 index.jsp/..;xxx/urltest/aaaa
, web.xml
为:
在 CoyoteAdapter.service
下断点,因为 Tomcat
里在 CoyoteAdapter
去处理封装请求。
Adapter连接了Tomcat连接器Connector和容器Container.它的实现类是CoyoteAdapter主要负责的是对请求进行封装,构造Request和Response对象.并将请求转发给Container也就是Servlet容器.
此时,会调用 postParseRequest
方法对req进行处理,继续跟到 parsePathParameters
方法,截取了关键部分的代码,主要目的是把 ;
和 /
之间的部分,包括 ;
给去除。
接着检测 ;
和 /
中间的部分是否存在 =
,如果存在,比如为 age=1
,就会取出 age
和 1
,调用 addPathParameter
,加到请求的 param
里,所以在这里 ;
就相当于 ?
的作用了。
接着调用 normalize
处理 url
,这里的 url
是 parsePathParameters
方法处理过后的。
这里面最终会把 /../
给删除,并且路径会到上层,处理后是这样的。
于是,url的处理经历了两步
parsePathParameters
:
index.jsp/..;xxx/urltest/aaaa -> index.jsp/../urltest/aaaa
normalize
index.jsp/../urltest/aaaa -> /urltest/aaaa
F5
实现了自己的 pam
进行认证,模块路径为 /usr/lib/httpd/modules/
,其中,涉及到 login.jsp
授权的是 mod_f5_auth_cookie.so
文件。
反汇编之后,大概是这样的。我们能够请求 /tmui/login.jsp
而不需要进行身份验证。
如果直接访问其他 jsp
文件, 在 没有通过身份验证的情况下,是会被重定向到 /tmui/login.jsp
的
在 apache
的处理中, ;
是被当作普通字符的,不会解析。
/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd
此时,由于请求的是 /tmui/login.jsp
,根据 pam
认证模块里, /tmui/login.jsp
不需要认证,接着,该请求会被转发到 tomcat
上,最终 tomcat
请求:
/tmui/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd
在web.xml 是有该配置的
<servlet-mapping> <servlet-name>org.apache.jsp.tmui.locallb.workspace.fileRead_jsp</servlet-name> <url-pattern>/tmui/locallb/workspace/fileRead.jsp</url-pattern> </servlet-mapping>
请求 /hsqldb;
, apache
本身会对 /hsqldb
进行认证,根据 httpd.conf
的配置,是匹配不到 /hsqldb;
的
<Location /hsqldb> <RequireAll> AuthType Basic AuthName "BIG/-IP" AuthPAM_Enabled on AuthPAM_IdleTimeout 1200 require valid-user Require all granted </RequireAll> </Location>
但正是因为 tomcat
对于 ;
处理上的差异,导致了身份的绕过, %0a
也是一个道理。
由于 fileRead.jsp
本身没有身份验证,通过权限绕过之后,就能够直接访问 fileRead.jsp
,于是,直接从 url
里获取 fileName
参数,带入 WorkspaceUtils.readFile
最终造成一个文件读取
由于 tmshCmd.jsp
本身没有身份验证,通过权限绕过之后,就能够直接访问 tmshCmd.jsp
,于是,直接从 url
里获取 command
参数,带入 WorkspaceUtils.runTmshCommand
2020年07月08日, 360CERT监测发现 F5
官方更新了 F5 BIG-IP
远程代码执行 的风险通告,更新了 httpd
的补丁,从
include ' <LocationMatch ".*/./.;.*"> Redirect 404 / </LocationMatch> '
改为
include ' <LocationMatch ";"> Redirect 404 / </LocationMatch> '
然而这样依然可以被绕过,使用 %0a
,也是因为tomcat的处理和apache的差异所导致的。
通过 ;
或者 %0a
直接访问 hsqldb
来绕过身份验证,从而通过 org.hsqldb.util.ScriptTool.main
反序列化了以 ASCII
十六进制字符串造成反序列化漏洞,不过该反序列化攻击需要 hsqldb
没有设置密码。我们直接访问 hsqldb
,会被重定向
curl -k "https://10.70.249.116:443/hsqldb" <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>302 Found</title> </head><body> <h1>Found</h1> <p>The document has moved <a href="/tmui/login.jsp">here</a>.</p> </body></html>
而利用 ;
或者 %0a
,可以造成权限绕过,具体在上面已经说过了。
curl -k "https://10.70.249.116:443/hsqldb;" <html><head><title>HSQL Database Engine Servlet</title> </head><body><h1>HSQL Database Engine Servlet</h1> The servlet is running.<p> The database is also running.<p> Database name: mem:.<p> Queries processed: 0<p> </body></html>
反序列化的调用栈
deserialize:-1, InOutUtil (org.hsqldb.lib) getObject:-1, JavaObject (org.hsqldb.types) getArguments:-1, Function (org.hsqldb) getValue:-1, Function (org.hsqldb) getValue:-1, Expression (org.hsqldb) executeCallStatement:-1, CompiledStatementExecutor (org.hsqldb) executeImpl:-1, CompiledStatementExecutor (org.hsqldb) execute:-1, CompiledStatementExecutor (org.hsqldb) sqlExecuteCompiledNoPreChecks:-1, Session (org.hsqldb) executePart:-1, DatabaseCommandInterpreter (org.hsqldb) execute:-1, DatabaseCommandInterpreter (org.hsqldb) sqlExecuteDirectNoPreChecks:-1, Session (org.hsqldb) execute:-1, Session (org.hsqldb) fetchResult:-1, jdbcStatement (org.hsqldb.jdbc) execute:-1, jdbcStatement (org.hsqldb.jdbc) execute:98, ScriptTool (org.hsqldb.util)
实例化 Function 对象
首先,根据我们的sql语句,解析器会识别我们调用的是一个方法,于是会实例化一个 org.hsqldb.Function
,这部分逻辑在 readColumnExpression
里,
在 Function
方法中,会判断我们调用的方法是否是静态方法,只能调用静态方法,将要调用的方法进行封装到 Function
对象中。
接着对方法的返回值进行判断,这里是 org.hsqldb.util.ScriptTool.main
,返回值是 void
。 于是调用 Types.getParameterTypeNr
,是 void
,暂时将 iReturnType
值设置为 0
。 接着往下走,对参数类型进行判断,不为 java.sql.Connection
,调用 Types.getParameterTypeNr
方法。 由于main方法的参数类型是 String
,同时 String
类型继承 Serializable
接口。 于是最终将 iReturnType
赋值为 1111
。
反序列化16进制数据
之后在 readColumnExpression
调用 Parser.read
方法,取出 '
单引号包裹的值,也就是我们要反序列化的 hex
值。
然后,取出 hex
的值,调用 convertObject
,这里对根据 iReturnType
是 1111
,于是调用 StringConverter.hexToByte
,将 hex
还原为 byte
数组并传入 JavaObject
的构造方法中。 将 byte
数组赋值给 data
。 由于返回值是 JavaObject
,于是最后调用 JavaObject.getObject
方法。 调用 InOutUtil.deserialize
处理 data
值。 最终造成反序列化。
2020-07-01F5官方发布通告
2020-07-03360CERT发布通告
2020-07-06360CERT更新通告
2020-07-10F5官方更新漏洞的缓解措施
2020-07-11360CERT二次更新通告
2020-07-14360CERT发布分析
【补丁二次更新】CVE-2020-5902: F5 BIG-IP 远程代码执行漏洞通告更新 [https://cert.360.cn/warning/detail?id=636804bf8fec3049e0a49383db8eb80d]
[https://cert.360.cn/warning/detail?id=a9bd3b42b2a9cfe1eef921d5bdfb0243]
[https://cert.360.cn/warning/detail?id=a1768348bde7807647cbc7232edce7df/]
[https://support.f5.com/csp/article/K52145254]
Understanding the root cause of F5 Networks K52145254: TMUI RCE vulnerability CVE-2020-5902
[https://research.nccgroup .com/2020/07/12/understanding-the-root-cause-of-f5-networks-k52145254-tmui-rce-vulnerability-cve-2020-5902/]
[https://github.com/Critical-Start/Team-Ares/tree/master/CVE-2020-5902]
[https://github.com/jas502n/CVE-2020-5902 ]
推荐阅读:
1、【补丁二次更新】CVE-2020-5902: F5 BIG-IP 远程代码执行漏洞通告更新
2、Citrix 多个高危漏洞通告
3、CVE-2020-8558: Kubernetes 本地主机边界绕过漏洞通告
长按下方二维码关注360CERT!谢谢你的关注!
注:360CERT官方网站提供《CVE-2020-5902: F5 BIG-IP 远程代码执行漏洞分析》完整详情,点击阅读原文