反序列化脏数据

    渗透测试 lz520520 2年前 (2022-03-19) 597次浏览

    脏数据1.0

    Java反序列化数据绕WAF之加大量脏数据 https://mp.weixin.qq.com/s/wvKfe4xxNXWEgtQE4PdTaQ

    其实就是再最外层封装一层,只要该类有对象属性,一般来说在反序列化的时候都会试着调用该属性的readObject去还原他。所以我们要找的class,第一需要实现java.io.Serializable接口,第二可以存储任意对象。这么看来集合类型就非常符合我们的需求。

    1. ArrayList

    2. LinkedList

    3. HashMap

    4. LinkedHashMap

    5. TreeMap

    脏数据2.0

    这个思路是基于@Y4tacker师傅做的扩展,源头总体来说还是这篇文章https://mp.weixin.qq.com/s/KncxkSIZ7HVXZ0iNAX8xPA

    如上方法还是正常封装,而java反序列化,在ObjectInputStream#readSerialData中,有一个逻辑,即使某块数据反序列化失败,仍然可以继续下一块数据的反序列化,比如LinkedList.add添加多个,每个对象不影响下个对象反序列化。如下图是个大的for循环。

    反序列化脏数据

    而skipCustomData应该是用于处理一些自定义数据,120(0x78)是块数据结束符。下图是jdk1.6的

    反序列化脏数据

    这是jdk1.8,对比多个版本主要是确认119和121是否都是无操作,目前看来只有119(0x77)即TC_BLOCKDATA是空操作,那么就可以在块中插入脏数据0x77。

    反序列化脏数据

    调试发现this.readObject0(false)会调用下一个序列化数据,而该bin.peekByte读取的是0x73,

    反序列化脏数据

    尝试插入一字节测试

    反序列化脏数据

    发现在readBlockHeader里报错了

    反序列化脏数据

    原来这里也会读取到119,那么这个字节就不能用了。

    反序列化脏数据

    其实根据这个思路,可以找一些其他位置或其他字符来测试。

    简单看了下,发现0x70表示Null,而

    反序列化脏数据

    并且原来这里0x78后面也是112(0x70 TC_NULL)

    反序列化脏数据

    所以尝试插入,发现可以了,可以继续反序列化hashmap了(这里测试的是URLDNS),后续就是正常过程了。

    反序列化脏数据

    仔细跟踪了下,readBlockHeader里如果是112(0x70 TC_NULL),那么就和不插入一样,正常进行后续解析。

    反序列化脏数据

    readBlockHeader是在this.bin.skipBlockData()里,一般只会执行一次。然后this.readObject0(false)里的switch判断类型,如果是112(0x70 TC_NULL)也就跳过不处理,继续后续处理。

    反序列化脏数据

    反序列化脏数据

    绕过119(0x77 TC_BLOCKDATA)的报错了,那么我突然想在这后面再插入119(0x77 TC_BLOCKDATA)是不是也行。- -傻逼了,go写多了,case 119没有break,会步入122,那么就会继续解析之前的blockheader。到这突然又想到,那么我在0x77后面再插入0x70是不是就又绕回来了。

    这里出现了一个误解,peekByte是不会移动数据流的pos的,只有read、readFull等等才会,所以这里没有用的。

    反序列化脏数据

    目前看来只能插入0x70了

    反序列化脏数据

    其他字节能否有同样效果,可以找下skipCustomData() 里的解析方法,skipBlockData()->readBlockHeader()readObject0()

    总结下有两个新的方案

    1. 填充大量null代表的\x70

    2. 填充大量不存在的class,这个其实想填充啥填充啥

    或者把上面两种结合一下

    测试效果如下,填充100个class和1W个\x70,反序列化脏数据


    Security , 版权所有丨如未注明 , 均为原创丨
    转载请注明原文链接:反序列化脏数据
    喜欢 (0)