CVE-2024-10252 Dify 沙盒代码注入沙盒逃逸漏洞分析
dify-sandbox是dify工作流中用于执行代码节点的服务,通过web api方式提供服务。
dify-sandbox Code 执行服务
dify-sandbox使用了Gin web 框架 通过X-Api-Key请求头鉴权
在dify项目中 X-Api-Key 默认值为 dify-sandbox
代码执行的API 接受4个参数
- Language 代码语言 支持Python3 与 Nodejs
- Code 需要执行的代码
- Preload 预计载代码
- EnableNetwork 是否开启网络权限
漏洞详情
根据报告中POC 可以看到问题出在 preload
参数中
根据报告中POC 可以看到问题出在 preload
参数中
在拿到通过api 传入的内容后会将 enable_network
preload
参数填充到 沙盒Python代码解释模版中
python 代码解释执行模版如下
import ctypes
import os
import sys
import traceback
# setup sys.excepthook 定义系统异常回调
def excepthook(type, value, tb):
sys.stderr.write("".join(traceback.format_exception(type, value, tb)))
sys.stderr.flush()
sys.exit(-1)
sys.excepthook = excepthook
# 加载GO实现的Seccomp沙盒
lib = ctypes.CDLL("./python.so")
lib.DifySeccomp.argtypes = [ctypes.c_uint32, ctypes.c_uint32, ctypes.c_bool]
lib.DifySeccomp.restype = None
# get running path 获取执行路径
running_path = sys.argv[1]
if not running_path:
exit(-1)
# get decrypt key 获取解密key
key = sys.argv[2]
if not key:
exit(-1)
from base64 import b64decode
key = b64decode(key)
# 改变工作目录到 running_path
os.chdir(running_path)
{{preload}}
# 初始化沙盒
lib.DifySeccomp({{uid}}, {{gid}}, {{enable_network}})
code = b64decode("{{code}}")
def decrypt(code, key):
key_len = len(key)
code_len = len(code)
code = bytearray(code)
for i in range(code_len):
code[i] = code[i] ^ key[i % key_len]
return bytes(code)
code = decrypt(code, key)
exec(code)
在这个模版中可通过api控的参数有两个
- code
- preload
code 在沙盒初始化后执行受到沙盒的系统调用限制
而preload在沙盒初始化之前执行不受沙盒系统调用限制由此产生了沙盒逃逸 远程 Code 执行
修复Pr 分析
通过配置文件 选择是否启用 preload
功能 默认不启用
规避建议
- 确保dify项目使用的dify-sandbox服务版本 ≥ 0.2.10
- 仅允许dify 后端api服务访问 dify-sandbox
- 修改dify-sandbox 默认鉴权为强口令 dify-sandbox/conf/config.yaml dify/api/.env 文件中的口令
附录
参考
漏洞报告:https://huntr.com/bounties/62c6c958-96cb-426c-aebc-c41f06b9d7b0
fix PR:
版权信息
本文原载于 not only security,复制请保留原文出处。