本文目录导读:

- 基础限制:
exec+ 受限命名空间(不安全) - 中级保护:
eval+ AST限制(适用于简单表达式) - 严格限制:
RestrictedPython(推荐用于简单场景) - 进程级隔离:
subprocess+ 资源限制(推荐) - 容器级隔离:Docker(最安全)
- 专业方案:PyPy的沙箱(已停止维护,但理念值得参考)
- 安全建议
- 实际工程选择
在Python中安全运行沙箱代码是一个复杂的课题,因为Python本身的设计目标是灵活和动态,而不是安全隔离,没有任何方案能做到100%安全,但可以根据需求选择不同级别的防护措施。
以下是几种常见的Python沙箱方案,按安全等级从低到高排列:
基础限制:exec + 受限命名空间(不安全)
def exec_in_sandbox(code, allowed_builtins=None):
# 创建一个受限的全局命名空间
restricted_globals = {
"__builtins__": allowed_builtins or {},
"__name__": "__sandbox__"
}
try:
exec(code, restricted_globals)
return restricted_globals
except Exception as e:
return {"error": str(e)}
问题:exec本身不是安全边界,很容易通过各种方式逃逸:
# 可以轻松绕过 code = """ ().__class__.__bases__[0].__subclasses__() """
中级保护:eval + AST限制(适用于简单表达式)
import ast
def safe_eval(expr, allowed_names={}):
# 只允许安全的AST节点
SAFE_NODES = {
ast.Expression, ast.Str, ast.Num, ast.Name, ast.Attribute,
ast.Load, ast.BinOp, ast.UnaryOp, ast.Add, ast.Sub,
ast.Mult, ast.Div, ast.Mod, ast.Pow, ast.Constant
}
try:
tree = ast.parse(expr, mode='eval')
for node in ast.walk(tree):
if type(node) in SAFE_NODES:
continue
raise ValueError(f"Unsafe expression: {type(node)}")
return eval(compile(tree, '<string>', 'eval'),
{"__builtins__": {}}, allowed_names)
except Exception as e:
raise ValueError(f"Evaluation error: {e}")
适用范围:只能用于非常简单的数学表达式或属性访问。
严格限制:RestrictedPython(推荐用于简单场景)
from RestrictedPython import compile_restricted, safe_globals
from RestrictedPython.Guards import guarded_iter_unpack_sequence
def restricted_exec(code, local_vars=None):
try:
compiled_code = compile_restricted(code, '<string>', 'exec')
restricted_globals = {
'__builtins__': {
'True': True,
'False': False,
'None': None,
'int': int,
'float': float,
'str': str,
'bool': bool,
'list': list,
'dict': dict,
'tuple': tuple,
'len': len,
'range': range,
'min': min,
'max': max,
'abs': abs,
'print': print, # 可选的输出函数
},
'_getattr_': safe_getattr,
'_write_': guarded_write,
'_print_': guarded_print,
}
restricted_locals = local_vars or {}
exec(compiled_code, restricted_globals, restricted_locals)
return restricted_locals
except Exception as e:
return {"error": str(e)}
限制:不能使用import、文件操作、网络访问等。
进程级隔离:subprocess + 资源限制(推荐)
import subprocess
import resource
import os
import signal
def run_sandboxed_code(code, timeout=5, memory_limit=100*1024*1024):
# 将代码写入临时文件或通过管道传递
script = f"""
import sys
import resource
# 设置资源限制
def set_limits():
# CPU时间限制
resource.setrlimit(resource.RLIMIT_CPU, (1, 1))
# 内存限制
resource.setrlimit(resource.RLIMIT_AS, ({memory_limit}, {memory_limit}))
# 文件大小限制
resource.setrlimit(resource.RLIMIT_FSIZE, (1024, 1024))
# 进程数限制
resource.setrlimit(resource.RLIMIT_NPROC, (10, 10))
set_limits()
# 执行用户代码
try:
exec({repr(code)})
except Exception as e:
print(f"Error: {{e}}", file=sys.stderr)
sys.exit(1)
"""
try:
# 在新进程中运行
result = subprocess.run(
['python3', '-c', script],
capture_output=True,
timeout=timeout,
text=True
)
return {
"stdout": result.stdout,
"stderr": result.stderr,
"returncode": result.returncode
}
except subprocess.TimeoutExpired:
return {"error": "Timeout"}
except Exception as e:
return {"error": str(e)}
优点:
- 进程级别的隔离
- 可以通过资源限制防止DoS攻击
- 用户代码无法影响主程序
容器级隔离:Docker(最安全)
import docker
import tempfile
import os
def run_in_docker(code, image="python:3.9-slim", timeout=30):
client = docker.from_env()
# 创建临时文件存放代码
with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
f.write(code)
temp_path = f.name
try:
# 运行容器
container = client.containers.run(
image=image,
command=f"python /code/script.py",
volumes={temp_path: {'bind': '/code/script.py', 'mode': 'ro'}},
mem_limit="100m",
cpu_quota=50000, # 限制CPU使用
network_mode="none", # 禁用网络
read_only=True, # 只读文件系统
remove=True,
detach=True
)
# 等待完成
result = container.wait(timeout=timeout)
logs = container.logs(stdout=True, stderr=True, tail=50)
return {
"exit_code": result['StatusCode'],
"output": logs.decode('utf-8')
}
except docker.errors.ContainerError as e:
return {"error": str(e)}
finally:
os.unlink(temp_path)
专业方案:PyPy的沙箱(已停止维护,但理念值得参考)
PyPy曾有一个沙箱实现,使用独立的子解释器运行代码:
# 概念代码(需要PyPy沙箱支持)
from pypy_sandbox import Sandbox
sandbox = Sandbox()
sandbox.run("print('Hello from sandbox')")
安全建议
- 明确需求:确定需要开放哪些功能(算术运算、字符串处理、文件访问等)
- 最小权限原则:只开放必需的功能
- 多层防御:组合使用多种限制方法
- 输入验证:预处理用户输入,过滤危险字符
- 超时机制:设置代码执行时间限制
- 资源限制:内存、CPU、文件大小等
实际工程选择
- 简单表达式求值:
ast.literal_eval或RestrictedPython - 运行用户代码:
subprocess+ 资源限制(推荐) - 需要网络/文件访问:Docker容器(最安全)
- 大规模生产环境:云厂商提供的Serverless服务(AWS Lambda, Cloud Functions等)
记住:没有任何纯Python的沙箱方案是绝对安全的,对于高安全性需求,始终使用操作系统级别的隔离(容器、虚拟机)或专业的沙箱服务。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播