python原型链污染
字数 1899 2025-08-29 22:41:24

Python原型链污染与Flask安全漏洞分析

1. Python原型链污染基础

1.1 Python中的魔术方法

Python中所有以双下划线__包围的方法称为魔术方法(Magic Method),它们会在特定条件下自动执行:

  • __class__: 查看变量所属的类
  • __init__(): 类的构造函数,创建实例时自动调用
  • __globals__: 保存函数全局变量的字典引用,可以修改无继承关系的类属性甚至全局变量
  • __file__: 全局变量,返回当前文件路径

1.2 原型链污染原理

在Node.js中,对象的__proto__属性指向该对象所在类的prototype属性。修改son.__proto__中的值可以影响父类。

在Python中,通过修改魔术方法或特殊属性,可以达到类似原型链污染的效果,影响类的行为或全局配置。

2. Flask框架中的安全漏洞

2.1 文件路径污染

通过污染__file__全局变量,可以改变文件路径解析行为。常见的Linux环境变量路径包括:

  • /proc/[pid]/environ: 当前进程环境变量
  • /etc/environment: 系统全局环境变量

2.2 Flask全局变量

Flask框架中两个重要的全局变量:

  1. app: Flask应用实例,核心对象,负责处理请求和配置

    • 包含路由定义(app.route)
    • 应用启动(app.run())
    • 其他配置方法
  2. _static_folder: 指定静态文件目录路径

    • 默认在应用根目录下的static文件夹
    • 可通过app.static_folder访问和修改

2.3 静态目录利用

如果_static_folder被设置为根目录/,可以通过/static/proc/1/environ访问系统环境变量文件。

3. Flask调试模式PIN码攻击

当Flask开启debug模式时,访问/console路由需要PIN码进行调试。PIN码生成依赖六个要素:

  1. username: 通过getpass.getuser()/etc/passwd获取
  2. modname: 默认flask.app,通过getattr(mod, "file", None)获取
  3. appname: 默认Flask,通过getattr(app, "name", type(app).name)获取
  4. moddir: Flask库app.py的绝对路径
  5. uuidnode: MAC地址十进制表示
    • 通过uuid.getnode()获取
    • 或从/sys/class/net/eth0/address读取16进制后转换
  6. machine_id: 机器唯一标识
    • Linux: /etc/machine-id/proc/sys/kernel/random/boot_id
    • Docker: /proc/self/cgroup/docker/后的内容

PIN码生成算法:

  • Python 3.6: MD5加密
  • Python 3.8: SHA1加密

4. 实际攻击案例分析

4.1 污染app.secret_key

通过原型链污染修改Flask的app.secret_key,可以控制会话签名密钥,可能导致会话伪造。

4.2 merge函数漏洞分析

merge函数实现对象合并功能时,如果没有正确处理属性访问,可能导致原型链污染:

def merge(target, source):
    for key in source:
        if key in target and isinstance(target[key], dict) and isinstance(source[key], dict):
            merge(target[key], source[key])
        else:
            target[key] = source[key]

攻击者可以通过精心构造的输入修改对象的特殊属性。

4.3 WAF绕过技术

  • Unicode编码绕过: 使用Unicode编码特殊字符绕过字符串过滤,json.loads可以解析Unicode
  • UTF-16BE编码: 将payload编码为UTF-16BE绕过某些过滤机制

4.4 XXE漏洞组合攻击

通过原型链污染设置app.config['xml_data']为恶意XML代码,再访问触发XML解析的路由,实现XXE文件读取。

5. 防御措施

  1. 严格输入验证: 对所有用户输入进行严格验证和过滤
  2. 禁用调试模式: 生产环境务必关闭Flask调试模式
  3. 最小权限原则: 应用运行使用最小必要权限
  4. 安全配置:
    • 限制静态目录访问范围
    • 使用随机强密钥
  5. 代码审计: 检查所有对象合并、属性复制操作的安全性
  6. 依赖更新: 保持框架和依赖库的最新版本

6. 参考资源

  1. Flask官方安全指南
  2. Python魔术方法文档
  3. CTF中Flask PIN码计算总结
  4. 原型链污染原理与防御
Python原型链污染与Flask安全漏洞分析 1. Python原型链污染基础 1.1 Python中的魔术方法 Python中所有以双下划线 __ 包围的方法称为魔术方法(Magic Method),它们会在特定条件下自动执行: __class__ : 查看变量所属的类 __init__() : 类的构造函数,创建实例时自动调用 __globals__ : 保存函数全局变量的字典引用,可以修改无继承关系的类属性甚至全局变量 __file__ : 全局变量,返回当前文件路径 1.2 原型链污染原理 在Node.js中,对象的 __proto__ 属性指向该对象所在类的 prototype 属性。修改 son.__proto__ 中的值可以影响父类。 在Python中,通过修改魔术方法或特殊属性,可以达到类似原型链污染的效果,影响类的行为或全局配置。 2. Flask框架中的安全漏洞 2.1 文件路径污染 通过污染 __file__ 全局变量,可以改变文件路径解析行为。常见的Linux环境变量路径包括: /proc/[pid]/environ : 当前进程环境变量 /etc/environment : 系统全局环境变量 2.2 Flask全局变量 Flask框架中两个重要的全局变量: app : Flask应用实例,核心对象,负责处理请求和配置 包含路由定义( app.route ) 应用启动( app.run() ) 其他配置方法 _static_folder : 指定静态文件目录路径 默认在应用根目录下的 static 文件夹 可通过 app.static_folder 访问和修改 2.3 静态目录利用 如果 _static_folder 被设置为根目录 / ,可以通过 /static/proc/1/environ 访问系统环境变量文件。 3. Flask调试模式PIN码攻击 当Flask开启debug模式时,访问 /console 路由需要PIN码进行调试。PIN码生成依赖六个要素: username : 通过 getpass.getuser() 或 /etc/passwd 获取 modname : 默认 flask.app ,通过 getattr(mod, "file", None) 获取 appname : 默认 Flask ,通过 getattr(app, "name", type(app).name) 获取 moddir : Flask库 app.py 的绝对路径 uuidnode : MAC地址十进制表示 通过 uuid.getnode() 获取 或从 /sys/class/net/eth0/address 读取16进制后转换 machine_ id : 机器唯一标识 Linux: /etc/machine-id 或 /proc/sys/kernel/random/boot_id Docker: /proc/self/cgroup 中 /docker/ 后的内容 PIN码生成算法 : Python 3.6: MD5加密 Python 3.8: SHA1加密 4. 实际攻击案例分析 4.1 污染 app.secret_key 通过原型链污染修改Flask的 app.secret_key ,可以控制会话签名密钥,可能导致会话伪造。 4.2 merge 函数漏洞分析 merge 函数实现对象合并功能时,如果没有正确处理属性访问,可能导致原型链污染: 攻击者可以通过精心构造的输入修改对象的特殊属性。 4.3 WAF绕过技术 Unicode编码绕过 : 使用Unicode编码特殊字符绕过字符串过滤, json.loads 可以解析Unicode UTF-16BE编码 : 将payload编码为UTF-16BE绕过某些过滤机制 4.4 XXE漏洞组合攻击 通过原型链污染设置 app.config['xml_data'] 为恶意XML代码,再访问触发XML解析的路由,实现XXE文件读取。 5. 防御措施 严格输入验证 : 对所有用户输入进行严格验证和过滤 禁用调试模式 : 生产环境务必关闭Flask调试模式 最小权限原则 : 应用运行使用最小必要权限 安全配置 : 限制静态目录访问范围 使用随机强密钥 代码审计 : 检查所有对象合并、属性复制操作的安全性 依赖更新 : 保持框架和依赖库的最新版本 6. 参考资源 Flask官方安全指南 Python魔术方法文档 CTF中Flask PIN码计算总结 原型链污染原理与防御