文章总结: 文档分析了MLflow追踪服务器在basic-auth模式下的授权绕过漏洞CVE-2025-14297。漏洞源于授权校验器映射表未覆盖所有端点,导致认证用户可绕过权限检查读写数据,引发泄露或供应链投毒。文章提供了复现步骤,建议立即升级,并强调授权应默认拒绝及资源层统一授权。 综合评分: 100 文章分类: 漏洞分析,应用安全,漏洞预警,供应链安全,安全建设
CVE-2025-14297:MLflow 追踪服务器的授权绕过漏洞
幻泉之洲
2026年3月10日 17:57 北京
本文详细分析了在开源机器学习管理平台 MLflow的 basic-auth 模式下发现的一个授权绕过漏洞(CVE-2025-14297)。漏洞源于其授权机制设计缺陷:部分访问受保护资源的 API 端点未被纳入授权校验器映射,导致认证通过的用户可以在未授权情况下读取甚至写入实验数据与模型工件。文章剖析了漏洞成因、影响范围、具体复现步骤,并提供了修复建议与安全教训。
漏洞概述
CVE 编号: CVE-2025-14297
影响范围: 采用 basic-auth 模式的自托管 MLflow OSS 部署。该漏洞不影响 Databricks 托管的 MLflow 服务。
危害等级: 高危。经过身份验证的非管理员用户,可以利用此漏洞绕过基于对象的权限控制,访问未被授权的实验、运行记录(runs)和模型工件(artifacts),在受影响版本上甚至能够进行未授权的写入操作。这可能引发数据泄露、供应链投毒,甚至权限提升。
技术原理分析
漏洞成因:基于注册表的授权设计缺陷
MLflow 在 basic-auth 模式下,其授权机制依赖于一个内部的“校验器(validator)”映射表。当一个请求到达时,Flask 的 before_request 钩子会执行以下流程:
- 对请求进行身份验证,确认用户身份。
- 根据请求路径和方法,在
BEFORE_REQUEST_VALIDATORS映射表中查找对应的授权校验器。 - 如果找到校验器,则执行针对具体对象的权限检查。
关键在于,这个校验器映射表主要从经过 protobuf 注册的 REST 端点(/api/2.0/mlflow/...)中填充。
漏洞就出在这里:如果某个请求的路由和方法在映射表中找不到对应的校验器,那么该请求在通过身份验证后,会直接跳过授权检查,默认允许执行。
def _before_request(): # … authentication happens …
# Authorization: look up validator for this route validator = BEFORE_REQUEST_VALIDATORS.get((request.path, request.method)) if validator: validator() # runs authorization check # If no validator found: request proceeds without authorization
这个问题很隐蔽,因为 MLflow 确实有权限模型,并且在大多数端点上都能正确执行。漏洞并非“完全没有授权”,而是因为一些端点从授权层的视角看“不在登记册上”,导致策略从未运行。
攻击向量:未被覆盖的访问路径
有两类主要的访问面未被校验器映射覆盖,成为攻击入口:
- 自定义 Flask 路由/辅助端点:例如用于检索或上传工件的辅助接口,它们不是通过 protobuf 注册的 REST 端点。
- GraphQL 端点(
/graphql):通过解析器(resolvers)访问实验和运行数据,但未集成到同一个校验器机制中。
影响范围
该漏洞影响所有使用 basic-auth 模式的自托管 MLflow 开源部署。
- 受影响组件:MLflow 追踪服务器(Tracking Server)。
- 触发条件:攻击者需要具备一个有效的、经过身份验证的用户凭证(即使是低权限的
NO_PERMISSIONS用户)。 - 核心风险:破坏了 MLflow 在多用户环境下的关键安全不变性——对受保护资源(实验、运行、工件)的每一次读写都必须在对象级别进行授权。
漏洞复现(PoC 说明)
假设以下场景:管理员创建了一个运行任务并上传了工件,同时明确拒绝了一个非管理员用户(NON_ADMIN)对该实验的访问权限。
场景一:读取绕过
通过规范的 REST API 访问被正确阻止:
curl -H “Authorization: Basic $NON_ADMIN_TOKEN” \ “$API_URL/api/2.0/mlflow/artifacts/list?run_id=$RUN”
403 Forbidden
但通过未被校验器覆盖的备用路由,可以成功读取:
curl -H “Authorization: Basic $NON_ADMIN_TOKEN” \ “$API_URL/get-artifact?run_id=$RUN&path=secret.txt”
200 – returns full contents
场景二:写入绕过(受影响版本)
通过未经验证的上传路由,可以注入或覆盖工件:
curl -X PUT -H “Authorization: Basic $NON_ADMIN_TOKEN” \ –data-binary “MALICIOUS CONTENT” \ “$API_URL/ajax-api/2.0/mlflow/upload-artifact?run_uuid=$RUN&path=malicious.txt”
200 – uploads successfully
场景三:GraphQL 查询绕过
非管理员用户即使被明确拒绝访问,仍可通过 /graphql 端点查询运行元数据。
攻击链条推演
这个漏洞不仅仅导致数据泄露。结合写入能力,可以构造更复杂的攻击链:
- 获取立足点:攻击者是一个经过认证的低权限用户(或窃取了其凭证)。
- 权限绕过:利用未经验证的路由(如
/get-artifact,/ajax-api/.../upload-artifact,/graphql)跳过对象级授权,读取或写入受限的实验/运行/工件。 - 数据投毒:利用写入权限,在无权控制的运行任务中上传或替换模型工件(如
python_function模型)。 - 信任链权限提升:更高权限的进程(如管理员审查、CI/CD 作业、生产服务系统)随后拉取并加载这些被篡改的工件。如果工件格式是可执行的,这可能导致在特权上下文中执行任意代码。
- 横向移动:攻击者现在具备了将影响扩散到任何消费 MLflow 工件的下游系统的能力,将权限缺口转变为供应链风格的安全事件。
修复建议与缓解措施
官方修复
该漏洞已通过漏洞赏金平台 Huntr 负责任的披露。修复补丁已合并至 MLflow 主分支:
- 提交 87dc3fc:修复了 GraphQL 的授权问题。
- 提交 eddc240:修复了 AJAX 代理工件路由的授权问题。
建议所有受影响用户立即升级到已修复的 MLflow 版本。
安全设计教训
从这个漏洞中可以吸取两个普遍的安全设计教训:
1. 授权应“默认拒绝”
如果一个授权层由注册表或映射驱动,那么缺失的注册条目绝不能等同于“不执行授权”。否则,安全态势将完全依赖于端点注册的完整性,而这在软件的长期演进中很难保持稳定。授权检查失败时应明确拒绝,而不是静默放行。
2. 在多接口服务中,应在资源层统一授权
如果实验、运行和工件是被保护的对象,那么对它们的读写操作,无论通过哪种协议或路由抵达,都应强制执行权限检查。这可以降低因为新增接口(如辅助路由、新的UI端点、GraphQL 解析器)未接入原始的执行机制,而意外产生绕过漏洞的风险。
尽管 MLflow 社区已迅速修复此漏洞,但所有自部署复杂系统的团队都应审视自身的授权实现。不要假设所有路径都被覆盖。最危险的授权漏洞往往藏在代码随系统演进自然产生的“上下文与时间缝隙”里。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:幻泉之洲 《CVE-2025-14297:MLflow 追踪服务器的授权绕过漏洞》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论