预备知识
1 | ClassFile { |
1 | cp_info { |
constant_pool_count是2字节大小,所以如果其值大于0xffff时,多余的“常量”就会覆盖后续内容,从而控制类文件(XSLT 样式表中的 字符串(String)
以及 > 32767
的数值将存入到字节码的 常量池表(constant_pool)
中)
1 | // org.apache.bcel.classfile.ConstantPool#dump |
例如,如果写入65536个常量,那么常量池表就为空(0x10000 & 0xFFFF = 0);如果写入65537个常量,此时常量表为1…以此类推,后面溢出的常量就覆盖了class文件
access_flags&this_class
其实就是后续的内容还是要满足“常量”的格式
access_flags
的值决定了类的访问标识,如是否为 public
,是否为 抽象类
等等,如下为各个标识对应的 mask
值,当 与操作值 != 0
时则会增加相应的修饰符
编译后的字节码最终将得到 TemplatesImpl
对象,因此 由于需要实例化类对象,所以类不能为接口、抽象类,并且需要被 public 修饰,所以 access_flags
需满足如下条件:
- access_flags.x1 & 任意修饰符 == 0
- access_flags.x2 & ACC_PUBLIC(0x01) != 0
access_flags.x1=0x08:从1到16中选,但不选1的原因是utf8_info中有一项length,其值会影响bytes数量,进而后面就不太好控制
this_class.x2=0x06:因为后面构造的都是Double_info的常量,所以tag为0x06
this_class.x1=0x01:this_class
是一个指向常量池的 常量池索引
,所以为了使得 截断后的常量池最小
,所以这个值需要尽可能的小,由于 0x0006
已经占用了,
并不能选择常量池已有的这些
Class常量
,原因在于这些Class常量
是 XSLT 解析的过程中会使用到的类,而字节码最终会被defineClass()
加载为 Class,将会导致类冲突问题
所以最终确定值为 this_class = 0x0106(262)
加载一些 XSLT 解析过程不会引用的类:因为类是懒加载的,只有在被使用到的时候才会被加载进 JVM,所以
defineClass()
调用时并不会存在com.sun.org.apache.xalan.internal.lib.ExsltStrings
,从而解决了类冲突的问题,之后通过在其之前填充一些常量
access_flags.x2=0x07:因为其值和this_class.x1共同组成了String_info的index,所以会间接控制常量池大小
后续发现需要大于0x0600,有一个0x06位域index的高位
又有前面的约束,所以暂且选0x07
supper_class
super_class
同样也需要指向 CONSTANT_Class_info
类型索引,并且因为 TemplatesImpl
的原因依旧需要继承 org.apache.xalan.xsltc.runtime.AbstractTranslet
抽象类,所以直接指向 #0006
即可
interfaces_count&fields_count
method_count
methods[0]
1 | method_info { |
methods[0].attributes_count
表示当前方法体中 attribute
的数量,每个 attribute
都有着如下通用格式,根据 attribute_name_index
来决定使用的是哪种属性格式(如下表)
1 | attribute_info { |
主要关注 Code
属性,其中存储着方法块中的字节码指令
1 | Code_attribute { |
eg:
methods[1]
attributes[0]
attributes[1]
Double 8 bytes
Code
方法:
- JVM 会检查构造函数中
return
操作之前是否有调用super()
方法,所以可以通过return
前嵌入一个死循环即可解决这个问题
attributes[2]
payload
https://gist.github.com/thanatoskira/07dd6124f7d8197b48bc9e2ce900937f
https://ho1aas.blog.csdn.net/article/details/126986529
原文
http://noahblog.360.cn/xalan-j-integer-truncation-reproduce-cve-2022-34169/