shiro反序列化漏洞分析、模拟攻击及修复(一)

shiro反序列化漏洞分析、模拟攻击及修复(二)

shiro反序列化漏洞分析、模拟攻击及修复(三)

Apache Shiro Java 的权限及安全验证框架中占用重要的一席之地,在它编号为550issue 中爆出严重的 Java 反序列化漏洞。下面,我们将首先搭建漏洞环境,模拟还原此漏洞的场景及分析,最后根据不同的场景提出了三种办法来修补此漏洞。详见shiro反序列化漏洞分析、模拟攻击及修复(三)

实验内容

  • windows环境中搭建shiro漏洞环境
  • 分析漏洞原因
  • 使用反弹shell利用漏洞模拟攻击
  • 漏洞修复分析及方案

实验采用工具与环境

  • Windows 10
  • IDEA
  • python3
  • Power shell
  • Httpie
  • java
  • Maven
  • tomcat

shiro环境搭建

1.git上获取 Apache Shiro 存在漏洞的源代码。地址:https://github.com/apache/shiro/releases/tag/shiro-root-1.2.4

2.修改shiro/samples/web下的pom.xml文件,添加如下内容:
 



     

        1.6

        1.6

    

...

    

        

            javax.servlet

            jstl

            

            1.2

            runtime

        

.....

        

            org.apache.commons

            commons-collections4

            4.0

        

3.使用maven进行存在漏洞环境的 war 包进行编译。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第1张图片

ps:在编译过程中出现了以下错误

 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-toolchains-plugin:  
1.1:toolchain (default) on project shiro-samples: Cannot find matching toolchain  
 definitions for the following toolchain types:  
[ERROR] jdk [ vendor='sun' version='1.6' ] 

  • mavenconf目录下的toolchains.xml文件中添加

shiro反序列化漏洞分析、模拟攻击及修复(一)_第2张图片l

  • 重新编译打包,成功。

4.target 目录下生成的 samples-web-1.2.4.war 文件拷贝至 tomcat 目录下的 webapps 目录将其重命名为了 shiro.war 文件,启动 tomcat, 在浏览器当中输入 http://localhost:8080/shiro ,可以看到如下登录界面

shiro反序列化漏洞分析、模拟攻击及修复(一)_第3张图片

shiro反序列化漏洞分析

1.登录root账号,勾选Remember Me,观察其cookie中的rememberMe内容

shiro反序列化漏洞分析、模拟攻击及修复(一)_第4张图片

2.查看官方漏洞描述,其处理cookie的流程是:得到rememberMecookie-->Base64解码-->AES解密-->反序列化。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第5张图片

3.rememberMe内容使用base64解码后为

00 01 02 03 04 05 06 07  08 09 0A 0B 0C 0D 0E 0F
--------------------------------------------------------------------
58 1D 21 BE 14 35 E0 1D  2A AD 0E 4C 74 9C DF 3A  | X.!..5..*..Lt..:
A8 99 65 F5 25 38 25 D2  6A C5 83 7E 4D 5A F4 1A  | ..e.%8%.j..~MZ..
0E 54 38 F2 C3 EE 6D B2  BF 4C 3E 14 AA A3 F0 44  | .T8...m..L>....D
45 5F 5A 9B 5A E8 CB 4A  62 EC 25 90 DA A2 27 1D  | E_Z.Z..Jb.%...'.
A7 C4 85 36 94 CD 24 69  76 BB 6F 97 EA B1 4C 9C  | ...6..$iv.o...L.
1A ED 33 70 CC E4 EE 64  64 8B 37 DB 9E 58 63 36  | ..3p...dd.7..Xc6
6A 42 60 C3 04 A6 E4 BE  A7 10 87 F5 FC 54 FA 32  | jB`..........T.2
DC 5B 5F E7 D0 35 35 49  0A 53 A9 7B C0 A7 82 A6  | .[_..55I.S.{....
BC 90 70 60 0C 30 E3 13  4E 46 B2 88 21 52 26 D1  | ..p`.0..NF..!R&.
FC 37 55 8A 45 2F 9E 7B  A8 84 C8 EF 19 15 AE 1E  | .7U.E/.{........
72 28 FB 18 BE 8A 67 00  9B 9A 65 FA 0B 4E 35 BE  | r(....g...e..N5.
DE 9C 00 C2 88 E9 45 71  D9 B7 98 59 6D DD 83 E6  | ......Eq...Ym...
A2 6A B9 33 89 2C FC F0  CD 7A 2E D3 BA 14 A9 4C  | .j.3.,...z.....L
25 12 10 E8 FB 3F 86 B4  4A 7D 68 AF 0E 43 C3 B3  | %....?..J}h..C..
49 EC AC 0C 94 8C C5 9D  1E 70 00 24 20 C8 7A 17  | I........p.$ .z.
E3 3D DF C7 F7 35 71 8B  F5 12 65 2C F8 23 A7 E6  | .=...5q...e,.#..
33 57 CE C4 1B 00 0C A5  6C 06 AE 5D 03 D8 AE 06  | 3W......l..]....
1A 7C C7 3E 23 0F 00 FE  FD 29 32 58 E5 2C D7 63  | .|.>#....)2X.,.c
FD E4 A7 A4 69 17 4C 24  67 5A 1A 42 A4 14 F1 B2  | ....i.L$gZ.B....
BB 9B A2 A6 58 F0 B0 CF  1A 6F 5D B8 0C DD E9 A4  | ....X....o].....
A9 E9 DD CE 4D CD 1B A2  0F C8 3A EE 6E 38 B3 B0  | ....M.....:.n8..
B8 B6 E5 E3 5C B8 22 0B  DF 0E 09 6B AA 42 DC 8F  | ....\."....k.B..
FC C2 53 9E C2 8F 3D D5  DC 32 E2 1A 97 36 E6 AB  | ..S...=..2...6..
68 47 83 3A 98 D4 8A 5F  FF 1A 77 D5 98 B6 B5 94  | hG.:..._..w.....

4. 解码后没有看到有明确的 Java 序列化特征字,因为处理流程中提到了 AES和加密密钥硬编码,所以去跟一下源码。在AbstractRememberMeManager 看到了加密密钥。Base64.decode("kPH+bIxk5D2deZiIxcaaaA==") 就是我们要找的硬编码密钥,因为 AES 是对称加密,即加密密钥也同样是解密密钥。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第6张图片

5.除了密钥,我们还需知道两个属性,一个是 AES 中的 mode(加解密算法),另外一个是 IV(初始化向量),继续查看 AbstractRememberMeManager 的代码,发现了encrypt方法

shiro反序列化漏洞分析、模拟攻击及修复(一)_第7张图片

6.在实现CipherService这个接口的抽象类 JcaCipherService中,在它的成员函数 initNewCipher 中下断点,可以看到:AES mode CBCIV是随机生成的。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第8张图片

7.利用上述获取到的信息,对 Base64 解码后的文件进行解密操作。

import base64
from Crypto.Cipher import AES


def decode_rememberme_file(filename):
    with open(filename, 'rb') as fpr:
        key = "kPH+bIxk5D2deZiIxcaaaA=="
        mode = AES.MODE_CBC
        IV = b' ' * 16
        encryptor = AES.new(base64.b64decode(key), mode, IV=IV)
        remember_bin = encryptor.decrypt(fpr.read())
    return remember_bin


if __name__ == '__main__':
    with open("decrypt.bin", 'wb+') as fpw:
        fpw.write(decode_rememberme_file("remember.bin"))

8.如下为解密后的文件内容,可以看到第二行打头的 ac ed 00 05,这是Java序列化的标志。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第9张图片

9.解密后文件的第一行内容,在JcaCipherService 这个类中的一个加密函数 encrypt 发现是先将 IV 写入,然后再加密具体的序列化对象的字节码,这样 IV 值我们可以直接通过读取第一行(16个字节,128位)获得了。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第10张图片

10.最后还剩加密的序列化对象,在SimplePrincipalCollection 中我们发现了关键的两个方法: writeObject readObject。到此,cookie的加密构造过程我们就都清楚了。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第11张图片

shiro反序列化漏洞调试

1.明白了shirorememberMe字段的解析过程,使用idea进行调试,进一步了解解析过程,调试时会出现错误,需要在sample-web下的pom文件中做以下修改。

  • jstl的版本改为1.2
  • 删掉servlet-apiscope字段。
  • jstl-1.2.jar放置在WEB-INF/lib下面
  • 增加jstl实现包

shiro反序列化漏洞分析、模拟攻击及修复(一)_第12张图片

2.使用刚刚登录所拿到的rememberMe值在getRememberedIdentity方法中打断点进行调试。可以看到拿到了cookie值。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第13张图片

3.继续跟踪,得到将cookie进行base64解码后的数据。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第14张图片

4.继续跟踪,得到将base64解码后的数据AES解密后的bytes

shiro反序列化漏洞分析、模拟攻击及修复(一)_第15张图片

5.继续跟踪,得到将AES解密后的bytes反序列化,通过readObject方法获得的cookie原值。至此,cookie解析结束。

shiro反序列化漏洞分析、模拟攻击及修复(一)_第16张图片

 

你可能感兴趣的:(shiro反序列化漏洞分析、模拟攻击及修复(一))