Java代码审计:反序列化

admin 2022年1月16日20:52:18评论169 views字数 2356阅读7分51秒阅读模式
1 反序列化漏洞
    反序列漏洞,当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码(多见于第三方组件产生的漏洞)

Java代码审计:反序列化

    常见审计点:
ObjectInputStream.readObjectObjectInputStream.readUnsharedXMLDecoder.readObjectYaml.loadXStream.fromXMLObjectMapper.readValueJSON.parseObject
    JAVA 常见的序列化和反序列化的方法有JAVA 原生序列化和 JSON 类(fastjson、jackson)序列化

2 简单的序列化
@GetMapping("/test")public String test() {    String obj = "hello world!";    try {        // 创建一个包含对象进行反序列化信息的”object”数据文件        FileOutputStream fos = new FileOutputStream("object");        ObjectOutputStream os = new ObjectOutputStream(fos);
// writeObject()方法将obj对象写入object文件 os.writeObject(obj); os.close();
// 从文件中反序列化obj对象 FileInputStream fis = new FileInputStream("object"); ObjectInputStream ois = new ObjectInputStream(fis);
// 恢复对象 String obj2 = (String) ois.readObject(); ois.close(); return obj2;
} catch (Exception e) { return e.toString(); }}

Java代码审计:反序列化


3 漏洞代码
    readObject,读取输入流,并转换对象。
    ObjectInputStream.readObject() 方法的作用正是从一个源输入流中读取字节序列,再把它们反序列化为一个对象。
    如果此时ObjectInputStream对象的初始化参数来自外部请求输入参数则基本可以确定存在反序列化漏洞
@RequestMapping("/readObject")public String readObject(String base64) {    try {        System.out.println("[vul] 执行反序列化");        BASE64Decoder decoder = new BASE64Decoder();
// 坑:读取的base64内容,加号会被转空格 base64 = base64.replace(" ", "+");
byte[] bytes = decoder.decodeBuffer(base64);
// 将字节转为输入流 ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
// 反序列化流,将序列化的原始数据恢复为对象 ObjectInputStream in = new ObjectInputStream(stream); in.readObject(); in.close(); return "反序列化漏洞"; } catch (Exception e) { return "需生成Payload:java -jar ysoserial-0.0.6-SNAPSHOT-BETA-all.jar CommonsCollections5 "open -a Calculator" | base64"; }}


Java代码审计:反序列化


4 安全代码
    使用Apache Commons IO的ValidatingObjectInputStream,accept方法来实现反序列化类白/黑名单控制
@RequestMapping("/safe")public String safe(String base64) {    try {        System.out.println("[safe] 执行反序列化");        BASE64Decoder decoder = new BASE64Decoder();
// 坑:读取的base64内容,加号会被转空格 base64 = base64.replace(" ", "+");
byte[] bytes = decoder.decodeBuffer(base64);
// 将字节转为输入流 ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
// 使用 ValidatingObjectInputStream ValidatingObjectInputStream ois = new ValidatingObjectInputStream(stream);
// 只允许反序列化Student class ois.accept(Student.class); Object obj = ois.readObject();
return "ValidatingObjectInputStream"; } catch (Exception e) { return e.toString(); }}

5 编码建议
    1.更新commons-collections、commons-io等第三方库版本
    2.业务需要使用反序列化时,尽量避免反序列化数据可被用户控制,如无法避免建议尽量使用白名单校验的修复方式

6 代码链接
https://github.com/j3ers3/Hello-Java-Sec

7 历史文章
Java代码审计:SQL注入
Java代码审计:XSS与SSRF
Java代码审计:远程代码执行

原文始发于微信公众号(Reset安全):Java代码审计:反序列化

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月16日20:52:18
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Java代码审计:反序列化http://cn-sec.com/archives/739151.html

发表评论

匿名网友 填写信息