ApereoCAS PaddingOracle漏洞分析 && XXE漏洞利用

PaddingOracle这个漏洞开始实际上是我和@Passer6y挖的一个0day,后来SCTF给撞了…吐了
XXE是之后和@threedream挖的一个0day,目前还经常在用

Padding Oracle

Padding Oracle复习

  1. padding

分组密码Block Cipher需要在加载前确保每个每组的长度都是分组长度的整数倍。一般情况下,明文的最后一个分组很有可能会出现长度不足分组的长度。这个时候,普遍的做法是在最后一个分组后填充一个固定的值,这个值的大小为填充的字节总数。即假如最后还差3个字符,则填充0×03。这种Padding原则遵循的是常见的PKCS5标准

  1. AES CBC模式加解密逻辑

-w878

很清晰,初始化向量IV和cipher用户可控,因此这两个就是我们的攻击点。

  1. Padding Oracle的攻击原理
    每个分组8个字节,首先从padding 0x01开始。
    如下图,当我们可控的IV的最后一个字节输入0x66时,经过和Intermediary Value异或一次后,最后的padding就变成了0x01。因此,每爆破一位需要最多256次请求。

padding 0x02时具体过程下边说

  1. java中的padding oracle如何利用
    首先是个小知识点,java中的反序列化,是从stream中按照固定length或者格式取值的,比如readInt就会从obj stream中取能反序列化为int的那部分。
    因此如果我们在已有的 aes加密后的 序列化字符串后边padding上我们的分组,是不会影响之前的这个对象反序列化的。因此,如果我们padding正确,则会解密正确+反序列化成功,返回200;如果padding错误,则会解密失败,返回302。

下图是失败的流程:
-w695

-w1050

  1. 如何伪造明文
    我们的最终目的实际上是伪造明文,因此整个过程应该是padding oracle拿到Intermediary Value,然后cbc字节翻转伪造任意序列化对象从而rce。

这里就不得不膜dalao们的思路,通过padding两个块直接一个块一个块的伪造明文。
参考 https://p0sec.net/index.php/archives/126/

step1
首先padding如下Ciphertext,aes中16字节为一个块,一共两个块,Plaintext为这一堆0经过aes解密后得到的明文。

Ciphertext
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

Plaintext
0x7c 0x42 0xda 0x7b 0x84 0xa2 0x77 0xb1 0x31 0x37 0x1f 0xcd 0xbe 0x3e 0x23 0x1c 0x4a 0xec 0xf6 0xed 0x58 0xfc 0xdc 0xa4 0xa3 0x4a 0x39 0x25 0x39 0x5b 0xeb 0x42

首先爆破第一个块的最后一个字节,当为0x43时,经过和最后一个分组的Intermediary Value异或后,结果为0x1,然后在0x43 ^ 0x1 = 0x42即可确定Intermediary Value的最后一个字节为0x42。这里需要记住这个0x42,我们下一步要用到。
-w3892

step2
接下来需要爆破倒数第二个字节,让最后一个块解密出的明文的最后两个字节为0x2。但是要注意,因为最后的0x1变成了0x2,所以我们第一步爆破出的0x43就不能用了,需要0x2 ^ 0x42 = 0x40重新计算出最后一个字节。

然后爆破就能得到倒数第二位Intermediary Value为0xe9 ^ 0x02 = 0xeb,第二步结束

step3
接下来慢慢的爆破这16个字节,我们就能拿到最后一组密文对应的Intermediary Value:
0x4a 0xec 0xf6 0xed 0x58 0xfc 0xdc 0xa4 0xa3 0x4a 0x39 0x25 0x39 0x5b 0xeb 0x42
假设我们要伪造的最后一堆密文对应的明文为0123456789abcdef,一共16字节,那么我们只需要hex(0x4a^0x30) = 0x7a,然后让前一组的密文为0x7即可。伪造过后的前一组密文:
0x7a 0xdd 0xc4 0xde 0x6c 0xc9 0xea 0x93 0x9b 0x73 0x58 0x47 0x5a 0x3f 0x8e 0x24 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00

step4
这时候倒数第二个block已经伪造完成,效果就是可以让最后一组的密文0000…经过解密后变成0123…f这段明文。接下来需要控制倒数第二个block的解密结果。
再倒数第二个block之前再插入两个block,现在考虑加的这四个block中的倒数第二、第三两个block的密文(倒数第二个block的密文就是上边伪造出来的):
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x7a 0xdd 0xc4 0xde 0x6c 0xc9 0xea 0x93 0x9b 0x73 0x58 0x47 0x5a 0x3f 0x8e 0x24

然后直接爆破第一个分组的最后一个字节,直到padding正确,第二个分组的最后一个字节为0x01,就构造好的倒数第二个block。

cas中的padding oracle

0-33 header
34-770 cipher

高版本

5和6中使用了jwt,进行了签名,算法是HS512,每次运行签名的key都不一样,暂时没找到能绕过的思路。

XXE

就不告诉你

Proudly powered by Hexo and Theme by Hacker
© 2023 LFY