从`__class__`到RCE:深入拆解Python SSTI漏洞中的那些‘魔术方法’

SSTIPython安全漏洞分析
于 2026-05-29 11:35:21 修改
·本内容遵循CC 4.0 BY-SA版权协议

__class__到RCE:Python SSTI漏洞中的魔术方法深度解析

在Python的世界里,魔术方法(Magic Methods)就像隐藏在对象背后的秘密通道,它们以双下划线开头和结尾,赋予了对象特殊的行为能力。当这些"魔法"被恶意利用时,一条从普通字符串到远程代码执行(RCE)的危险路径就此展开。本文将带您深入探索SSTI(服务器端模板注入)漏洞中那些关键魔术方法的工作原理和利用技巧。

1. Python对象模型的底层机制

Python中一切皆对象,而每个对象都携带着一组特殊的属性和方法,这就是魔术方法的用武之地。理解这些方法如何工作,是破解SSTI漏洞的关键。

1.1 对象继承链的导航工具

__class__属性是每个Python对象都具备的基本属性,它指向对象所属的类。例如:

PYTHON
>>> "hello".__class__
<class 'str'>

这个简单的属性却是SSTI攻击链的起点。通过它,攻击者可以从一个字符串对象回溯到其类定义,进而探索整个继承体系。

__base____mro__则提供了在继承链中导航的能力:

  • __base__:返回类的直接父类
  • __mro__(Method Resolution Order):返回一个元组,包含类及其所有祖先类
PYTHON
class A: pass
class B(A): pass
class C(B): pass
 
print(C.__base__) # <class '__main__.B'>
print(C.__mro__) # (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)

1.2 危险的类探索能力

__subclasses__()方法可能是Python中最危险的魔术方法之一。它返回一个类的所有直接子类:

PYTHON
>>> object.__subclasses__()
[<class 'type'>, <class 'weakref'>, <class 'weakcallableproxy'>, ...]

在SSTI攻击中,攻击者通常会沿着以下路径前进:

  1. 从字符串对象获取其类(__class__
  2. 回溯到基类object(通过__base____mro__
  3. 获取所有子类(__subclasses__()
  4. 寻找可利用的危险类

2. SSTI漏洞中的魔术方法利用链

2.1 从模板注入到代码执行

SSTI漏洞发生在应用程序将用户输入直接拼接到模板中时。考虑以下Flask示例:

PYTHON
from flask import Flask, request, render_template_string
 
app = Flask(__name__)
 
@app.route('/')
def index():
name = request.args.get('name', 'Guest')
template = f"<h1>Hello, {name}!</h1>"
return render_template_string(template)

当攻击者输入{{7*7}}时,服务器返回49,这就确认了SSTI漏洞的存在。

2.2 完整的利用链条

一个典型的SSTI攻击payload会串联多个魔术方法:

TEXT
{{ ''.__class__.__mro__[1].__subclasses__()[X].__init__.__globals__['popen']('whoami').read() }}

让我们分解这个payload:

  1. ''.__class__:获取空字符串的类(str)
  2. .__mro__[1]:获取str类的第二个祖先(object)
  3. .__subclasses__()[X]:获取object的第X个子类(通常是os._wrap_close)
  4. .__init__.__globals__:访问该类的全局变量字典
  5. ['popen']:获取os模块的popen函数
  6. ('whoami').read():执行系统命令并读取输出

2.3 关键魔术方法详解

魔术方法 作用 安全风险
__class__ 返回对象所属类 暴露类继承链入口
__base__ 返回直接父类 允许向上遍历继承链
__mro__ 返回方法解析顺序 快速访问所有祖先类
__subclasses__ 返回所有子类 暴露危险系统类
__init__ 类初始化方法 提供访问__globals__的入口
__globals__ 返回函数全局变量 暴露模块级函数和变量

3. 防御策略与最佳实践

3.1 输入过滤与沙箱环境

最根本的防御是避免将用户输入直接作为模板渲染。如果必须使用动态模板,应采取以下措施:

  • 严格过滤所有输入,禁止{{}}等模板语法
  • 使用安全的模板引擎配置
  • 在沙箱环境中执行模板渲染

3.2 魔术方法的安全管理

对于高风险应用,可以考虑限制魔术方法的访问:

PYTHON
class SafeStr(str):
def __getattribute__(self, name):
if name.startswith('__') and name.endswith('__'):
raise AttributeError(f"Access to {name} is restricted")
return super().__getattribute__(name)

3.3 安全开发检查清单

  1. 模板使用规范

    • 优先使用render_template而非render_template_string
    • 明确区分静态模板和动态内容
  2. 依赖管理

    • 及时更新框架和模板引擎
    • 移除不必要的内置模块导入
  3. 运行时防护

    • 限制Python解释器能力
    • 监控异常的类方法调用

4. 深入理解魔术方法的本质

4.1 Python对象模型探秘

Python的灵活性很大程度上源于其动态对象模型。每个对象都维护着一个__dict__属性,存储着它的属性和方法。魔术方法正是通过这个机制实现各种特殊行为。

PYTHON
class Demo:
def __init__(self):
self.value = 42
def __str__(self):
return f"Demo with {self.value}"
 
d = Demo()
print(d.__dict__) # {'value': 42}

4.2 方法解析顺序(MRO)的算法

Python使用C3线性化算法确定方法解析顺序。理解MRO有助于预测__mro__属性的输出:

PYTHON
class A: pass
class B(A): pass
class C(A): pass
class D(B, C): pass
 
print(D.__mro__)
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

4.3 __globals__的底层原理

函数的__globals__属性指向定义该函数的模块的全局命名空间。这是SSTI攻击能够访问系统模块的关键:

PYTHON
import os
 
def demo():
pass
 
print(demo.__globals__['os'] is os) # True

在实际开发中,我曾遇到一个案例:一个简单的字符串格式化功能,因为使用了format()方法的动态调用,意外暴露了__globals__,导致信息泄露风险。这提醒我们,即使是最基础的功能,也可能因为Python的动态特性而变得危险。

Python 魔术方法 详解
本文详细介绍了Python魔术方法,包括特殊属性的查看、实例化、可视化、运算符重载等,特别强调了运算符重载在实际应用中的场景,并探讨了容器相关魔术方法和可调用对象的概念,以斐波那契数列为示例进行说明。
Lee木木
5873
SSTI模板注入及绕过姿势(基于Python-Jinja2)
本文深入探讨SSTI(服务端模板注入)的原理与利用流程,总结了常见Payload及如何绕过过滤机制,包括文件读取、命令执行及请求方式绕过等实战案例。
Y4tacker
16714
Python常见的魔术方法魔术属性
本文围绕Python魔术方法魔术属性展开。魔术方法以双下划线开头和结尾,能让对象响应内置运算符或函数,如__len__等,还介绍了单态模式节省内存。魔术属性可获取对象或类的内部成员结构、文档、类名等信息,对Python开发有重要指导意义。
景天科技苑
1607
`链式`调用如何使用`Python`的`魔术方法`实现`流利``接口`
本文介绍如何利用Python魔术方法实现链式调用,提升代码可读性和表达力。通过返回对象自身并结合__getattr__等动态方法,可构建流畅的API接口,适用于查询构造、HTML生成等场景,同时提醒注意副作用与异常处理。
海派程序猿
1144
ctfshow-ssti
文章介绍了服务端模板注入(SSTI)的概念,特别是针对Python的Flask框架,强调了由于代码不规范导致的安全问题。通过Python类继承的示例展示了如何查找并利用魔术方法执行命令。文章还列举了多种利用SSTI漏洞方法,包括`__builtins__`、`os.popen`等,并提供了CTF挑战中的解题例子。
zhou965
548
SSTI模块注入】SSTI+Flask+Python(上)基础知识
本文深入探讨了服务端模板注入(SSTI)的概念、成因和原理,重点讲解了在Flask框架中如何利用jinja2模板引擎进行SSTI攻击。通过示例展示了如何通过`render_template`和`render_template_string`函数进行模板注入,并介绍了可能的漏洞点和利用技巧,包括通过内置方法`__class__``__bases__`等获取敏感信息。同时,文章还讨论了模块化在Web开发中的应用及其安全利用原理。
黑色地带(崛起)
754
SSTI 服务器端模板注入
本文深入解析服务器端模板注入(SSTI)概念,探讨模板引擎基础,介绍常见注入手法及绕过技巧,涵盖SSTIPython、PHP、Java等语言中的应用,并通过多个CTF实战案例展示SSTI的利用流程。
zhang三
3056
SSTI Bypass 学习 (Python3&jinja2
本文详细介绍了SSTI(服务端模板注入)的概念,特别是针对Python3和Jinja2框架的Bypass方法。通过分析SSTI的利用流程和常见Payload,讲解了如何绕过过滤限制,包括利用`{%%}`执行if语句、编码绕过、以及利用`request`对象。此外,还分享了一种利用Python字符串格式化特性的Bypass思路,并强调了Bypass技巧的关键在于创新思维和不断学习。
「已注销」
1814
SSTI模板注入(flask) 学习总结
本文围绕Flask-jinja2 SSTI展开,介绍了SSTI中常用魔术方法和内建函数,阐述利用SSTI读取文件(区分Python 2和3)及执行命令的多种方式,还详细讲解了关键字、其他字符过滤的绕过姿势,如字符串拼接、编码、利用函数等,最后提及使用Jinja过滤器绕过及获取flag的方法
Jay 17
1763
Python】面向对象 ④ ( 魔术方法 - 类内置方法 | `__str__` 字符串魔术方法 | 小于符号比较魔术方法 | 实现 `__lt__` 小于符号比较方法后也可以进行大于比较 )
文章介绍了Python类的魔术方法,包括构造方法__init__,用于字符串表示的__str__方法,以及实现对象间比较的__lt__方法。通过示例展示了如何使用这些魔术方法,使得实例对象可以直接进行字符串输出和比较操作。,
韩曙亮
1035
Python:魔术方法
本文介绍了Python中的魔术方法,包括__init__、__str__、__del__等。__init__用于初始化对象属性,__str__定义对象的字符串表示,__del__处理对象销毁时的操作。还汇总了常见魔术方法,这些方法能自定义和重载内置操作,使用时需理解其语义和场景。
00&00
999
python 魔术方法详解
本文系统讲解Python魔术方法(双下划线方法)的核心机制与应用,涵盖构造销毁、字符串表示、比较与算术运算符重载、类型转换、容器模拟、可调用对象、上下文管理器、属性访问控制及哈希等关键类别,强调其在自定义类行为扩展中的作用及其自动调用特性。
小灰灰搞电子
1287
Python魔术方法
本文详细介绍了Python中的常用魔术方法,包括`__init__``__new__``__del__``__call__``__len__``__str__``__repr__``__bool__``__format__`,并解释了它们的触发时机、作用及使用注意事项。此外,还讨论了属性相关的魔术方法,如`__getattr__``__setattr__``__delattr__``__getattribute__``__dir__`,以及属性访问的顺序和优先级。这些魔术方法在类的设计和对象操作中起着关键作用,帮助开发者实现更灵活和定制化的功能。
Alan and fish
787
Python魔术方法
本文介绍了Python中的魔术方法,包括创建与销毁、类型转换、比较等关键操作。魔术方法允许开发者重载Python的内置操作符和方法,如`__init__``__del__``__str__``__repr__``__hash__`等。通过定义这些特殊方法,可以自定义类的行为,比如实现自定义类型的比较、迭代和上下文管理。
Vincent__Lai
285
Python中类的魔术方法之--反射
本文详细介绍了Python中的反射,包括运行时类型信息获取、相关内建函数如`type()`、`isinstance()`的使用,以及反射相关的魔术方法,如`__getattr__``__setattr__``__delattr__`等。文章通过示例展示了动态添加属性的方法,并探讨了这些方法在属性查找顺序中的作用,强调了反射带来的灵活性。
带着梦想飞翔
462
python flask 魔术方法
本文介绍了Python魔术方法的应用,如`__init__`用于初始化对象,`__class__`获取类信息,`__base__`查找父类,`__subclasses__`遍历子类,以及`__globals__`访问全局变量。以BUGKU题目为例,展示了如何通过这些方法进行类的操作和调试。,
默默提升实验室
1730
python魔术方法
本文详细介绍了Python魔术方法,包括常规魔术方法`__init__``__del__`,比较方法`__eq__``__ne__`,运算符重载方法`__add__``__sub__`,属性访问控制的`__getattr__``__setattr__`,以及序列和可调用对象的魔术方法。通过这些魔术方法,可以自定义对象的行为,实现类的特殊功能,如序列化和文件打开器。
江洗河
358
python魔术方法大全
本文详细介绍了Python中的魔术方法,包括初始化方法`__init__`、析构方法`__del__`、长度计算`__len__`、字符串表示`__str__`等,并涵盖了属性访问、比较操作符、算术运算、类型转换、上下文管理以及容器类型的魔术方法。这些魔术方法在定义类行为和自定义类型时起着关键作用。
程序员老华
1079
python魔术方法大全(五)——运算篇
本文介绍了Python中的魔术方法,包括加法、减法、乘法等多个运算操作的魔术方法,如`__iadd__``__sub__``__mul__`等。通过实现这些魔术方法,可以自定义对象的行为,让类能够模拟数字类型的运算。文章以代码示例的形式详细解释了每种魔术方法的作用和用法,帮助读者深入理解Python中的鸭子类型和对象行为的模拟。
Python_魔力猿
793
Python中的魔术方法(1)—构建
本文详细解读了Python中的`__init__``__new__`魔术方法,介绍了它们在类实例化过程中的调用顺序,并展示了如何利用`__new__`实现单例模式。此外,还涉及元编程和注意事项,帮助读者理解类的创建与销毁机制。
凌空摘星
458
ssti代码
本文详细介绍了服务器端模板注入(SSTI)的概念、漏洞代码示例、利用过程以及防御措施。SSTI是一种攻击形式,攻击者通过恶意输入操控服务器上的模板引擎。文章通过Jinja2和Python Flask的示例代码,展示了SSTI漏洞的形成和利用方法,包括如何通过构造特定的Payload来获取系统信息或执行远程代码。最后,提出了避免SSTI漏洞的防御策略,包括避免直接传递用户数据至模板引擎、启用沙盒机制和严格校验与过滤输入。
m0_74115715
ssti漏洞详解
牛油果~
ssti漏洞下划线怎么绕过
淋着雨...
Tornado框架SSTI漏洞实战从原理到高级利用技巧
好荐的鱼爸
实战指南如何用Jinja2 SSTI漏洞从零到getshell(附CTF常用payload大全)
男友范儿
Web安全实战XCTF攻防世界Confusion1的SSTI漏洞利用与绕过技巧
Matthew_牛
从BUUCTF到实战手把手教你用tplmap自动化检测Flask SSTI漏洞(附完整复现步骤)
龚伟(William)
现代Web CTF题型演变JWT伪造、SSTIRCE组合攻击面分析(含3条高危链路)
SW_孙维
ssti工具
淋着雨...
Flask SSTI漏洞的花式利用用lipsum和request绕过层层过滤的5种姿势
魏文华