shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

这篇具有很好参考价值的文章主要介绍了shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 前置知识

1.1 shiro550利用条件

知道aes加密的key且目标服务器含有可利用的攻击链。

原理

在Shiro <= 1.2.4中,反序列化过程中所用到的AES加密的key是硬编码在源码中,当用户勾选RememberMe并登录成功,Shiro会将用户的cookie值序列化,AES加密,接着base64编码后存储在cookie的rememberMe字段中.

服务端收到登录请求后,会对cookie的rememberMe字段的值进行base64解码,接着进行AES解密,然后反序列化。由于AES加密是对称式加密(key既能加密数据也能解密数据),所以当攻击者知道了AES key后,就能够构造恶意的rememberMe cookie值从而触发反序列化漏洞。

影响版本:1.2.4以下

解决payload过长的方式:

  1. 使用urlclassloader加载远程字节码
  2. 将字节码放在post的body中,恶意类实现加载body中的字节码即可.

1.2 shiro721利用条件

知道已经登陆用户的合法cookie且目标服务器含有可利用的攻击链就可以进行漏洞利用。

原理

shiro721用到的加密方式是AES-CBC,而且其中的ase加密的key基本猜不到了,是系统随机生成的。而cookie解析过程跟cookie的解析过程一样,也就意味着如果能伪造恶意的rememberMe字段的值且目标含有可利用的攻击链的话,还是能够进行RCE的。

通过Padding Oracle Attack攻击可以实现破解AES-CBC加密过程进而实现rememberMe的内容伪造。下面会有单独的篇幅讲Padding Oracle Attack。

影响版本:

1.2.5,
1.2.6,
1.3.0,
1.3.1,
1.3.2,
1.4.0-RC2,
1.4.0,
1.4.1

shiro-721对cookie中rememberMe的值的解析过程

shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

1.3 基于返回包的shiro特征检测

1. 根据返回包中是否有rememberMe=DeleteMe

shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

构造恶意的rememberMe数据,看房回包中是不是rememberMe=DeleteMe。

2. 使用序列化的SimplePrincipalCollection类的对象

发送一个经过序列化的SimplePrincipalCollection类的对象来判断。如果key正确,则返回包中不会有rememberMe=DeleteMe

示例代码如下:

public class SimplePrincipalCollectionTest {
    @Test
    public void test01() throws IOException, NotFoundException, CannotCompileException {
        SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection();
        AesCipherService aes = new AesCipherService();
        byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(simplePrincipalCollection);
        oos.close();
        ByteSource ciphertext = aes.encrypt(barr.toByteArray(), key);
        System.out.println(ciphertext.toString());
    }
}

Java Shiro SimplePrincipalCollection 探测密钥正确性

2. 环境搭建

git clone https://github.com/inspiringz/Shiro-721.git
cd Shiro-721/Docker
docker build -t shiro-721 .
docker run -p 8080:8080 -d shiro-721

3. 漏洞复现

先使用合法账户登陆,记得勾选remember Me,然后使用burp抓包获取cookie:
shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

获取到cookie:
shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

将其中的remember Me字段复制下来输入到工具中进行利用:

java -jar ysoserial.jar CommonsBeanutils1 "touch /tmp/123" > payload.class
python shiro_exp.py http://192.168.171.137:8080/login.jsp LIO2vKStP5R4NN+TLY0Bgfrz+3sacQHB1BfrOheCVAHeFAGtRsX9JW24tCvcedluOxZwFPoOSs7/tA0fK+UJ9ylRjLIT87NIN1smV22TVqdQ4vSJXB42IQCTV1mDA2CwlDpoeem6M4qY2SeB4JwIpV+iUwNJoOj+NfWeX3/lLZHkoCnsR5TCm6GrHyhdaDZYK0BAJNXFQ9658sJGAF1fztcfR0pYD9RtX26iLW73+D0pd3x6DhPQB7euA4uhUZ3Ue8RoOK3jTqxHC3U5n0DIMpc1RWlHVzUyHjejFAPXCReV+7ds/dWr+b5XlgP9/7ajmi2+6dqr2apVaIhEMC5SP4X4Y+QZw3wS6w76pD1vT8JSlG6l+h4+tIRuS4/gbUzX8GhmPCtw2MBMS/xZ2FsjvTPexdPLEf+114qo4152aNNcXul4zN3czLlve+otlqd5E/WyhhbBA2+EFk+Pewnsq2g2sS53s57H9BcWhXHkcwf0cIrkOXAn9a9xfkkm1HH9 payload.class

shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理
shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

此 exp 爆破时间较长,建议使用 ysoserial 生成较短的 payload 验证(eg: ping 、 touch /tmp/success, etc),约 1 个多小时可生成正确的 rememberme cookie,生成成功后将自动停止运行。

shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

最终会生成恶意的rememberMe cookie,我们使用这个cookie替换原数据包中的cookie。然后登陆进服务器看,会发现/tmp目录下被创建了一个123文件。

4. Padding Oracle Attack原理

这种攻击方式可以达到破解AES-CBC加密的效果。我们先了解几个基础知识。

4.1 分组密码填充

首先我们知道密码都是字符,一个字符8bit也就是1个byte。

aes加密的时候会将字符进行分组并填充,有可能是每8字节一组,也可能是16字节一组。

但是密码不可能恰好填满每个组,可能第一组填满了,第二组只有一个字符,这时候就需要进行填充。

如果明文密码分组完后刚好不需要填充,那么会额外添加一个组,这个组的数据全部都是0xXY,这个数据是多少取决于aes加密是多少个字节分一组的。具体举例如下:

假设密码为一个1,且加密算法中分组的逻辑是8个字节也就是64bit为一组。因为1只占1个字节,所以第一组中还有7个字节是空的。这时候第一组中的数据为:

1 0x07 0x07 0x07 0x07 0x07 0x07 0x07

如果明文恰好不需要填充比如是8个1,且分组逻辑还是8个字节也就是64bit为一组,那么分完组的明文如下:

第一组:

1 1 1 1 1 1 1 1 

第二组:

0x08 0x08 0x08 0x08 0x08 0x08 0x08 0x08

综上,填充的逻辑是,一定会填充数据,区别是填充一个组还是填充几位,如果分组后的明文最后一组中有N字节没有数据就填充0x0N。

如果分组后刚好合适,那么额外添加一个组,且这个组的明文数据一定全是0xXY,0xXY是多少取决于aes加密的分组逻辑填充了多少个数据

如果解密出的明文的结尾不是符合规律的0xXY,那么系统会判断解密失败。

4.2 AES-CBC模式算法

CBC主要是引入一个初始化向量(IV)来加强密文的随机性,保证相同明文通过相同的密钥加密的结果不一样。Shiro的IV通过源码我们可知是16byte的。因此分组也是16byte一组。

加密:

shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

逻辑:

  1. 明文经过填充后,分为不同的组,以组的方式对数据进行处理
  2. 初始化向量(IV)首先和第一组明文进行XOR(异或)操作,得到得值称为middle。
  3. 采用密钥key,对middle进行加密生成第一组的密文。
  4. 第一组加密的密文作为第二组的初始向量(IV),参与第二组明文的异或操作。
  5. 依次执行块加密,最后将每一块的密文拼接成最终的密文。

由于初始化向量(IV)每次加密都是随机的,所以IV经常会被放在密文的前面,解密时先获取前面的IV,再对后面的密文进行解密。密文的第一组就是IV。

解密:
shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

逻辑:

  1. 将密文进行分组(按照加密采用的分组大小),前面的第一组是初始化向量IV,从第二组开始才是真正的密文。
  2. 使用加密密钥对密文的第一组进行解密,得到Middle,第一组中只要密文不变,那么Middle一定不会改变。
  3. 将Middle和初始化向量IV进行异或,得到该组的明文
  4. 前一块密文是后一块密文的IV,通过异或中间值,得到明文
  5. 块全部解密完成后,拼接得到明文,密码算法校验明文的格式(填充格式是否正确)
  6. 校验通过得到明文,校验失败得到密文

4.3 解密

假设密文跟IV的值如下:

初始化向量: 7B 21 6A 63 49 51 17 0F
第一组密文: F8 51 D6 CC 68 FC 95 37
第二组密文: 85 87 95 A2 8E D4 AA C6


我们首先要知道,系统判断解密是否成功的点是解密后明文点最后一位或者几位的值跟aes算法中的分组逻辑是否匹配,匹配才能解密成功。

例如,解密后最后一组明文的最后一位值为0xFF,而aes算法的分组逻辑是8byte一组。那么这次解密一定是失败的。原因如下:

  1. 如果进行了明文填充,那么最后一位的值一定是小于0x08且大于0x01的。
  2. 如果没有进行明文填充而直接额外加了一个组,那么最后一位的值一定是0x08。

只有这两种可能性,而0xFF没在这两种可能性中,所以解密失败。


我们这时候选择只将IV跟第一段密文传入服务及进行解密,且将IV改成全0,就会有下面这张图:

shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

我们只用第一组密文是因为第一组密文一定没有填充,也就是说解密出的明文不可能有0x01-0x08中的值(假设这个例子中是8字节一组)。

图中最后一行解密我们是看不到的,只会看到页面反馈是解密失败。这时候我们只需更改传进去的IV的最后一位,从0x00改到0xFF,在这个例子中直到当IV最后一位等于0x3C的时候,程序显示解密成功。

因为明文的最后一组一定会有填充物,而我们只传进去了IV跟一组密文,因此推断出这组密文被系统认为是最后一组密文,那么只有当这组密文的明文有合法填充位的时候解密才会成功,程序才不会报错。

因为我们知道这一组其实是密文中的第一组,也就一定不会有填充位,也就意味着所有的数据都不可能有0x01-0x08中的值(假设这个例子中是8字节一组)。

综上,这时候有8种可能性。因为明文填充位有可能是0x01到0x08八种,于是middle中的最后一位也就有八种可能性。这时候我们可以对这8种可能的middle进行分别实验,举例如下:


假设当明文填充位的数据为0x01-0x08时分别对应的middle最后一位的值为ABCDEFGH。

我们假设middle的最后一位是A,且填充位是0x01
这时候将IV最后一位的值进行更改,使得A异或IV的最后一位的值得到0x02。
然后对IV的倒数第二位进行爆破,从0x00到0xFF。

如果爆破成功,网页返回200,就能确定最后一位填充位是0x01,且前面的数据都不是0x01-0x08中的。进而能确定middle的最后一位。

如果爆破失败,那将middle最后一位换成另一个,以此类推。

只要第二个数据能爆破成功,就能确定第一个数据一定正确。


最终我们测试出填充位是0x01,反推出middle中的最后一位是0x3D,IV最后一位 xor 0x01 = middle最后一位。

接下来就更改IV的最后两位,使得解密可以成功,此时如果解密成功,那么解密出的明文最后两位一定是0x02,由此可推算出middle的倒数第二位。快速的做法是根据刚得到的middle中最后一位的值来更改IV中最后一位的值,先使得得到明文的最后一位是0x02,然后其实只需要更改IV倒数第二位的值就可以了,极大的减少了运算次数,节省破解时间。

以此类推可以推断出middle的值,进而可以解密真正的明文。

第一组的密文会变成第二组密文的IV,根据上面的逻辑可以继续进行解密,然后推断出所有的铭文数据。

4.4 加密

shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理

具体加密过程如下:

  1. 将要加密的数据分成N个块并进行数据填充,假设要加密的数据为hello,aes加密分组为8字节每组,那么明文填充后应该为hello\x03\x03\x03
  2. 创建两个明文组,内容为\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA,第二个为全0,将全0的分组跟全A分组链接,0分组在前A分组在后。
  3. 将第二步形成的联合分组加到shiro合法cookie的最后面,对全0分组的最后一位进行修改,直到页面不报错,或者说没有rememberMe=deleteme。此时明文的最后一位是0x01,因此能推断出middle最后一位的数据。
  4. 接着修改倒数第二位直到页面不报错,推断出middle倒数第二位的数据,以此类推。此时可以得到全A组那一部分中middle的所有数据,只要全A组数据不变,那么全A组的middle永远不会变,因为middle是A组数据与key运算得到的。
  5. A组前一组的密文是由A组的middle与明文得到的,middle是不会变的,明文是我们要加密的铭文组的最后一个组,这两个属性我们都知道,因此我们可以用hello\x03\x03\x03这个明文去跟middle去异或,得到A组上一组的密文,假设运算得到的密文全部为B。那么如果我们想将hello\x03\x03\x03加密传送给服务端,则需要传输的数据为\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA。
  6. 如果有多个分组,比如说在hello前面还有八个A字符,而我们已经得到这个明文字符串的结尾密文为\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA,此时需要给\xBB\xBB\xBB\xBB\xBB\xBB\xBB\xB前面再添加八位的全0字符,接着就从后往前依次修改全0组的数据,像第3、4步一样,得到全B组的middle,可以用这个middle加密倒数第二组的明文形成密文,以此类推可以得到所有明文的密文。

5. 防御方式

  1. 由于这种方法需要爆破得到key,因此可以对短时间内多次访问的ip进行禁止访问操作,达到防御目的。
  2. 升级至安全版本。
  3. 关闭rememberMe持久化登录功能。

6. 参考文章

Shiro RCE again(Padding Oracle Attack)
Padding Oracle Attack(填充提示攻击)详解及验证
Apache Shiro 反序列化漏洞(Shiro-721 CVE-2016-4437)
利用Oracle Padding加密任意数据
Apache Shiro反序列化漏洞-Shiro-550复现总结
Shiro-721 RCE Via Padding Oracle Attack文章来源地址https://www.toymoban.com/news/detail-446461.html

到了这里,关于shiro 721 反序列化漏洞复现与原理以及Padding Oracle Attack攻击加解密原理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Fastjson反序列化漏洞原理与复现

    Fastjson是java的一个库,可以将Java对象转化为json格式的字符串,也可以将json格式的字符串转化为Java对象。 Fastjson提供了 toJSONString() 和 parseObject() 方法来将Java对象与JSON相互转换。调用 toJSONString() 方法即可将对象转换成 JSON 字符串, parseObject() 方法则反过来将JSON字符串转换成

    2024年02月12日
    浏览(62)
  • Apache Shiro RememberMe 1.2.4 反序列化过程命令执行漏洞【原理扫描】

    文章目录 一、分析定位 1. 漏洞描述 2. 项目引发漏洞简述 二、 若依系统 2.1. 版本升级 2.2. 配置文件 2.3. 推荐做法 2.4. 栗子 2.5. 项目场景 三、Gus系统 3.1. shiro版本升级 3.2. 调用重新生成 3.3. 生成工具类 shiro漏洞补充: 一、分析定位 1. 漏洞描述 2. 项目引发漏洞简述 若依/Guns管

    2024年02月15日
    浏览(47)
  • Shiro1.2.4反序列化漏洞

    目录 Shiro1.2.4反序列化漏洞 一、JRMP协议 二、漏洞原理 三、复现步骤 四、修复和防御 ​JRMP全称为Java Remote Method Protocol,也就是Java远程方法协议。是RMI(Remote Method Invocation)工作的底层协议。 ​Apache Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在名为remember-me的Co

    2024年02月01日
    浏览(37)
  • Shiro反序列化漏洞综合利用工具Shiro Attack使用教程

    目录 漏洞扫描 利用链检测 执行命令 注入蚁剑内存马 将目标网站输入在目标地址栏中吗,点击爆破密钥,如果发现key,则可以利用

    2024年02月13日
    浏览(36)
  • RuoYi v4.2 Shiro反序列化漏洞

    反序列化漏洞 漏洞原理 反序列化漏洞是基于序列化和反序列化的操作,在反序列化——unserialize()时存在用户可控参数,而反序列化会自动调用一些魔术方法,如果魔术方法内存在一些敏感操作例如eval()函数,而且参数是通过反序列化产生的,那么用户就可以通过改变参数来

    2024年02月01日
    浏览(46)
  • Apache Shiro反序列化漏洞研究及解决方法

    前言 一个阳光明媚的午休,我正惬意的喝着茶听着音乐,享受美好生活的时候,客户的QQ头像闪动了,原以为是出了什么新需求临时需要调整,没想到客户反馈的是平台出现了严重漏洞,不敢小视,抄起电脑开弄 我根据客户给出的安全厂商反馈的问题,总结如下: 1,Shiro反

    2024年02月11日
    浏览(51)
  • 【shiro】shiro反序列化漏洞综合利用工具v2.2(下载、安装、使用)

    shiro反序列化漏洞综合利用工具v2.2下载: 链接:https://pan.baidu.com/s/1kvQEMrMP-PZ4K1eGwAP0_Q?pwd=zbgp 提取码:zbgp 其他工具下载: 除了该工具之外,github上还有其他大佬贡献的各种工具,有许多python编写的工具,功能简单,可以作为理解shiro漏洞原理并编写自己工具的教材。 说明 :

    2023年04月08日
    浏览(48)
  • 反序列化漏洞及漏洞复现

    问题 :为什么要序列化? 序列化,“将对象的状态信息转换为可以存储或传输的形式的过程”,这种形式大多为字节流、字符串、Json 串。在序列化期间内,将对象当前状态写⼊到临时或永久性的存储区。以后,就可以通过从存储区中读取或还原(反序列化)对象的状态,重

    2024年02月09日
    浏览(46)
  • Shiro反序列化漏洞(CVE-2016-4437)+docker靶场+工具利用

    将java对象转换为字节序列(json/xml)的过程叫序列化,将字节序列(json/xml)恢复为java对象的过程称为反序列化。 Shiro框架提供了“记住我”的功能,用户登陆成功后会生成经过加密并编码的cookie,cookie的key为RememberMe,cookie的值是经过序列化的,使用AES加密,再使用base64编码

    2024年02月16日
    浏览(46)
  • Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437)

    目录 前言: (一)基本介绍 0x01 影响版本 0x02 漏洞分析 根据加密的顺序,不难知道解密的顺序为: 登入  验证  (二)环境搭建 1、本地复现 0x01 源代码 0x02  pom.xml修改: 0x03 tomcat服务器 0x04  ysoserial-jar依赖 0x05  访问端口  2、vulhub  访问端口:  (三)利用工具和方式 1、

    2024年02月05日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包