CVE-2025-14279:MLflowDNSRebinding漏洞分析

admin 2026-03-05 19:45:54 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文深入分析CVE-2025-14279漏洞,指出MLflow因未校验Host头而易受DNSRebinding攻击,导致内网API被未授权访问。文章详细阐述了攻击原理与环境搭建过程,利用rbndr.us成功复现漏洞,并剖析了官方在3.5.0版本通过引入安全中间件进行Host验证与CORS防护的修复方案,建议用户升级以修复漏洞。 综合评分: 90 文章分类: 漏洞分析,AI安全,WEB安全,应用安全


cover_image

CVE-2025-14279: MLflow DNS Rebinding 漏洞分析

原创

whoami0002 whoami0002

SecurityPaper

2026年3月4日 20:52 江苏

一、漏洞概述

1.1 漏洞简介

MLflow 是一个开源的机器学习生命周期管理平台,由 Databricks 开发。该漏洞存在于 MLflow REST Server 中,由于缺乏 Origin/Host 头验证,导致服务器容易受到 DNS Rebinding 攻击。

攻击者可以通过恶意网站绕过浏览器的同源策略 (Same-Origin Policy) 保护,对 MLflow REST API 端点执行未授权调用,从而实现对实验数据的查询、更新和删除操作,可能导致数据泄露、数据破坏或数据篡改。


二、DNS Rebinding 攻击原理

2.1 什么是 DNS Rebinding?

DNS Rebinding 是一种利用 DNS 解析机制绕过浏览器同源策略的攻击技术。攻击的核心思想是:

  1. 攻击者控制一个域名(如 evil.com)及其 DNS 服务器
  2. 第一次 DNS 查询返回攻击者服务器的 IP(如 1.2.3.4
  3. 受害者浏览器加载攻击者的恶意页面
  4. 攻击者将 DNS 记录更改为目标内网 IP(如 127.0.0.1 或 192.168.1.100
  5. 当恶意 JavaScript 发起请求时,浏览器认为仍在访问 evil.com(同源),但实际请求发送到了内网服务

2.2 攻击流程图

┌─────────────────────────────────────────────────────────────────────┐
│                     DNS Rebinding 攻击流程                           │
└─────────────────────────────────────────────────────────────────────┘

  ┌──────────┐                ┌──────────┐              ┌──────────────┐
  │  受害者   │                │ 攻击者   │              │  MLflow      │
  │  浏览器   │                │ DNS/Web  │              │  Server      │
  └────┬─────┘                └────┬─────┘              │ (127.0.0.1)  │
       │                           │                    └──────┬───────┘
       │  1. 访问 evil.com         │                           │
       │ ─────────────────────────>│                           │
       │                           │                           │
       │  2. DNS 返回 1.2.3.4      │                           │
&nbsp; &nbsp; &nbsp; &nbsp;│ <─────────────────────────│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;3. 加载恶意页面 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ <─────────────────────────│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;[恶意 JS 等待 DNS TTL 过期] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;4. 再次查询 evil.com DNS &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ ─────────────────────────>│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;5. DNS 返回 127.0.0.1 ⚠️ &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ <─────────────────────────│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;6. JS 发送请求到 evil.com │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; (浏览器认为是同源) &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ ─────────────────────────────────────────────────────>│
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;7. MLflow 返回敏感数据 &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ <─────────────────────────────────────────────────────│
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp;8. JS 将数据发送给攻击者 &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ ─────────────────────────>│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │
&nbsp; &nbsp; &nbsp; &nbsp;│ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; │

2.3 为什么 MLflow 受影响?

在 MLflow 3.4.0 及之前的版本中:

  1. 缺乏 Host 头验证:服务器不验证请求的 Host 头是否合法
  2. 缺乏 Origin 验证:不检查请求的来源是否在允许列表中
  3. 无 CORS 保护:允许任意来源的跨域请求访问 API

这使得攻击者可以通过 DNS Rebinding 绕过浏览器的同源策略,对运行在 localhost 或内网的 MLflow 服务发起攻击。


三、漏洞原理详解

3.1 漏洞根因分析

漏洞版本代码 (MLflow ≤ 3.4.0)

在漏洞版本中,MLflow 的 FastAPI 应用直接暴露 REST API,没有任何安全中间件保护:


四、漏洞环境搭建

4.1 环境要求

  • Python 3.8+

  • MLflow 3.4.0 (漏洞版本)

  • 现代浏览器 (Chrome/Firefox)

  • 可选:自建 DNS 服务器用于 DNS Rebinding

4.2 安装漏洞版本的 MLflow

# 创建虚拟环境
python&nbsp;-m&nbsp;venv mlflow_vuln_env
cd&nbsp;mlflow_vuln_env

# Windows
.\Scripts\activate

# Linux/Mac
source&nbsp;bin/activate

# 安装漏洞版本
pip install&nbsp;mlflow==3.4.0

4.3 启动 MLflow Server

# 使用 0.0.0.0 以便 DNS Rebinding 攻击可以访问
mlflow server&nbsp;--host127.0.0.1&nbsp;--port5000

4.4 DNS Rebinding 测试域名 (rbndr.us)

本文使用 rbndr.us 服务进行 DNS Rebinding 测试,无需自建 DNS 服务器。

域名格式:<IP1_HEX>.<IP2_HEX>.rbndr.us

测试域名:72727272.7f000001.rbndr.us

| 组成部分 | 十六进制 | IP 地址 | 说明 | | — | — | — | — | | 第一段 | 72727272 | 114.114.114.114 | 公网 DNS 服务器 IP | | 第二段 | 7f000001 | 127.0.0.1 | 本地回环地址 |

工作原理:

  • DNS 服务器会在两个 IP 之间随机切换

  • 首次解析可能返回 114.114.114.114

  • 再次解析可能返回 127.0.0.1

  • 浏览器认为是”同源”请求,实际访问了本地服务

验证 DNS Rebinding:

# 多次执行,观察 IP 变化
nslookup&nbsp;72727272.7f000001.rbndr.us


五、漏洞复现

5.1 使用 rbndr.us 进行DNS Rebinding 攻击

使用 72727272.7f000001.rbndr.us 域名进行真实的 DNS Rebinding 攻击复现。

这里使用get请求进行测试

六、漏洞修复分析

6.1 官方修复 Commit

修复 Commit: b0ffd289e9b0d0cc32c9e3a9b9f3843ae83dbec3

6.2 修复方案概述

MLflow 3.5.0 添加了一个完整的安全中间件层,包括:

  1. Host 头验证 (DNS Rebinding 防护)
  2. *CORS 保护
  3. X-Frame-Options 头 (防止点击劫持)
  4. 安全响应头**

6.3 新增安全配置选项

| 配置项 | CLI 选项 | 环境变量 | 默认值 | | — | — | — | — | | 允许的 Host | --allowed-hosts | MLFLOW_SERVER_ALLOWED_HOSTS | localhost, 私有 IP | | CORS 来源 | --cors-allowed-origins | MLFLOW_SERVER_CORS_ALLOWED_ORIGINS | localhost:* | | X-Frame-Options | --x-frame-options | MLFLOW_SERVER_X_FRAME_OPTIONS | SAMEORIGIN | | 禁用安全中间件 | --disable-security-middleware | MLFLOW_SERVER_DISABLE_SECURITY_MIDDLEWARE | false |

6.5 核心补丁代码分析

6.5.1 mlflow/server/fastapi_security.py – 安全中间件核心

这是补丁的核心文件

# mlflow/server/fastapi_security.py (MLflow 3.5.0+)
# 来源: https://github.com/mlflow/mlflow/commit/b0ffd289e9b0d0cc32c9e3a9b9f3843ae83dbec3

fromstarlette.middleware.corsimportCORSMiddleware

classHostValidationMiddleware:
&nbsp; &nbsp;&nbsp;"""
&nbsp; &nbsp; Host 头验证中间件 - 防止 DNS Rebinding 攻击

&nbsp; &nbsp; 通过验证 HTTP 请求的 Host 头是否在允许列表中,
&nbsp; &nbsp; 阻止来自恶意域名的请求访问内部服务。
&nbsp; &nbsp; """

&nbsp; &nbsp;&nbsp;def__init__(self,&nbsp;app,&nbsp;allowed_hosts:&nbsp;list[str]):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.app=app
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.allowed_hosts=allowed_hosts
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 编译通配符模式为正则表达式
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.allowed_host_patterns=&nbsp;[
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self._compile_pattern(host)&nbsp;forhostinallowed_hosts
&nbsp; &nbsp; &nbsp; &nbsp; ]

&nbsp; &nbsp;&nbsp;def_compile_pattern(self,&nbsp;pattern:&nbsp;str):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"""将通配符模式编译为正则表达式"""
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;importre
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 支持 *.example.com 和 localhost:* 格式
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;regex=pattern.replace(".",&nbsp;r"\.").replace("*",&nbsp;r".*")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;returnre.compile(f"^{regex}$",&nbsp;re.IGNORECASE)

&nbsp; &nbsp;&nbsp;asyncdef__call__(self,&nbsp;scope,&nbsp;receive,&nbsp;send):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ifscope["type"]&nbsp;!="http":
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;awaitself.app(scope,&nbsp;receive,&nbsp;send)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 提取 Host 头
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;headers=dict(scope["headers"])
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;host=headers.get(b"host",&nbsp;b"").decode("utf-8")

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# ✅ 关键修复:验证 Host 头是否在允许列表中
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ifnotself._is_valid_host(host):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 返回 400 Bad Request,拒绝可疑请求
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;response=Response(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;content="Invalid Host header",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;status_code=400
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;awaitresponse(scope,&nbsp;receive,&nbsp;send)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;awaitself.app(scope,&nbsp;receive,&nbsp;send)

&nbsp; &nbsp;&nbsp;def_is_valid_host(self,&nbsp;host:&nbsp;str)&nbsp;->bool:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"""检查 Host 是否匹配允许的模式"""
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# 移除端口号进行匹配
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;host_without_port=host.split(":")[0]&nbsp;if":"inhostelsehost

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;forpatterninself.allowed_host_patterns:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ifpattern.match(host)&nbsp;orpattern.match(host_without_port):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;returnTrue

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;returnFalse

classCORSBlockingMiddleware:
&nbsp; &nbsp;&nbsp;"""
&nbsp; &nbsp; CORS 阻止中间件 - 防止跨域攻击

&nbsp; &nbsp; 验证 Origin 头是否在允许列表中,
&nbsp; &nbsp; 阻止恶意网站的跨域请求。
&nbsp; &nbsp; """

&nbsp; &nbsp;&nbsp;STATE_CHANGING_METHODS=&nbsp;{"POST",&nbsp;"PUT",&nbsp;"DELETE",&nbsp;"PATCH"}

&nbsp; &nbsp;&nbsp;def__init__(self,&nbsp;app,&nbsp;allowed_origins:&nbsp;list[str]):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.app=app
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.allowed_origins=allowed_origins
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.allow_all="*"inallowed_origins

&nbsp; &nbsp;&nbsp;asyncdef__call__(self,&nbsp;scope,&nbsp;receive,&nbsp;send):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ifscope["type"]&nbsp;!="http":
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;awaitself.app(scope,&nbsp;receive,&nbsp;send)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;headers=dict(scope["headers"])
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;origin=headers.get(b"origin",&nbsp;b"").decode("utf-8")
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;method=scope.get("method",&nbsp;"GET")

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# ✅ 关键修复:对状态变更请求验证 Origin
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;iforiginandmethodinself.STATE_CHANGING_METHODS:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ifnotself._is_allowed_origin(origin):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;response=Response(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;content="CORS request blocked",
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;status_code=403
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;awaitresponse(scope,&nbsp;receive,&nbsp;send)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;awaitself.app(scope,&nbsp;receive,&nbsp;send)

&nbsp; &nbsp;&nbsp;def_is_allowed_origin(self,&nbsp;origin:&nbsp;str)&nbsp;->bool:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"""检查 Origin 是否被允许"""
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ifself.allow_all:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;returnTrue

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;returnany(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self._match_origin(origin,&nbsp;allowed)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;forallowedinself.allowed_origins
&nbsp; &nbsp; &nbsp; &nbsp; )

classSecurityHeadersMiddleware:
&nbsp; &nbsp;&nbsp;"""
&nbsp; &nbsp; 安全响应头中间件 - 防止点击劫持和 XSS

&nbsp; &nbsp; 自动添加安全相关的 HTTP 响应头。
&nbsp; &nbsp; """

&nbsp; &nbsp;&nbsp;def__init__(self,&nbsp;app,&nbsp;x_frame_options:&nbsp;str="SAMEORIGIN"):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.app=app
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;self.x_frame_options=x_frame_options

&nbsp; &nbsp;&nbsp;asyncdef__call__(self,&nbsp;scope,&nbsp;receive,&nbsp;send):
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ifscope["type"]&nbsp;!="http":
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;awaitself.app(scope,&nbsp;receive,&nbsp;send)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;asyncdefsend_wrapper(message):
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;ifmessage["type"]&nbsp;=="http.response.start":
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;headers=dict(message.get("headers", []))

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;# ✅ 添加安全响应头
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;headers[b"x-content-type-options"]&nbsp;=b"nosniff"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;headers[b"x-frame-options"]&nbsp;=self.x_frame_options.encode()
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;headers[b"x-xss-protection"]&nbsp;=b"1; mode=block"

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;message["headers"]&nbsp;=list(headers.items())

&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;awaitsend(message)

&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;awaitself.app(scope,&nbsp;receive,&nbsp;send_wrapper)

defconfigure_security_middleware(app,&nbsp;config):
&nbsp; &nbsp;&nbsp;"""
&nbsp; &nbsp; 配置安全中间件层 - MLflow 3.5.0+ 的核心修复

&nbsp; &nbsp; 按正确顺序添加所有安全中间件。
&nbsp; &nbsp; 中间件执行顺序(后添加的先执行):
&nbsp; &nbsp; 1. SecurityHeadersMiddleware - 添加安全响应头
&nbsp; &nbsp; 2. CORSMiddleware - 处理 CORS 预检请求
&nbsp; &nbsp; 3. CORSBlockingMiddleware - 阻止非法跨域请求
&nbsp; &nbsp; 4. HostValidationMiddleware - 验证 Host 头
&nbsp; &nbsp; """

&nbsp; &nbsp;&nbsp;ifconfig.disable_security_middleware:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;_logger.warning(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"Security middleware is disabled. "
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"Only use this when security is handled by a reverse proxy."
&nbsp; &nbsp; &nbsp; &nbsp; )
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return

&nbsp; &nbsp;&nbsp;allowed_hosts=config.get_allowed_hosts()
&nbsp; &nbsp;&nbsp;allowed_origins=config.get_allowed_origins()

&nbsp; &nbsp;&nbsp;# ✅ 添加安全响应头中间件
&nbsp; &nbsp;&nbsp;app.add_middleware(
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;SecurityHeadersMiddleware,
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;x_frame_options=config.x_frame_options
&nbsp; &nbsp; )

&nbsp; &nbsp;&nbsp;# ✅ 添加 CORS 中间件 (Starlette 标准中间件)
&nbsp; &nbsp;&nbsp;app.add_middleware(
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;CORSMiddleware,
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;allow_origins=allowed_origins,
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;allow_credentials=True,
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;allow_methods=["*"],
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;allow_headers=["*"],
&nbsp; &nbsp; )

&nbsp; &nbsp;&nbsp;# ✅ 添加 CORS 阻止中间件 (自定义,处理状态变更请求)
&nbsp; &nbsp;&nbsp;app.add_middleware(
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;CORSBlockingMiddleware,
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;allowed_origins=allowed_origins
&nbsp; &nbsp; )

&nbsp; &nbsp;&nbsp;# ✅ 添加 Host 头验证中间件
&nbsp; &nbsp;&nbsp;app.add_middleware(
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;HostValidationMiddleware,
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;allowed_hosts=allowed_hosts
&nbsp; &nbsp; )

&nbsp; &nbsp;&nbsp;_logger.info(f"Security middleware configured:")
&nbsp; &nbsp;&nbsp;_logger.info(f" &nbsp;Allowed hosts:&nbsp;{allowed_hosts}")
&nbsp; &nbsp;&nbsp;_logger.info(f" &nbsp;Allowed CORS origins:&nbsp;{allowed_origins}")
&nbsp; &nbsp;&nbsp;_logger.info(f" &nbsp;X-Frame-Options:&nbsp;{config.x_frame_options}")

6.5.2 mlflow/server/fastapi_app.py – FastAPI 应用集成

补丁修改了 FastAPI 应用创建逻辑,集成安全中间件:

# mlflow/server/fastapi_app.py (补丁修改部分)

frommlflow.server.fastapi_securityimportconfigure_security_middleware

defcreate_app(config):
&nbsp; &nbsp;&nbsp;"""Create FastAPI application with security middleware."""
&nbsp; &nbsp;&nbsp;app=FastAPI(
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;title="MLflow Tracking Server",
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;...
&nbsp; &nbsp; )

&nbsp; &nbsp;&nbsp;# ✅ 补丁新增:配置安全中间件
&nbsp; &nbsp;&nbsp;ifnotconfig.disable_security_middleware:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;configure_security_middleware(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;app,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;allowed_hosts=config.allowed_hosts,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;cors_allowed_origins=config.cors_allowed_origins,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;x_frame_options=config.x_frame_options,
&nbsp; &nbsp; &nbsp; &nbsp; )
&nbsp; &nbsp;&nbsp;else:
&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;_logger.warning(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"Security middleware is disabled. "
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;"Ensure security is handled by your reverse proxy."
&nbsp; &nbsp; &nbsp; &nbsp; )

&nbsp; &nbsp;&nbsp;# Mount Flask app for backward compatibility
&nbsp; &nbsp;&nbsp;app.mount("/",&nbsp;WSGIMiddleware(flask_app))

&nbsp; &nbsp;&nbsp;returnapp

七、总结

CVE-2025-14279 是一个典型的 DNS Rebinding 漏洞,其根本原因在于:

  1. 缺乏 Host 头验证:服务器接受任意 Host 头,无法防御 DNS Rebinding
  2. CORS 配置不当:允许任意来源的跨域请求
  3. 无安全响应头:缺少必要的安全 HTTP 响应头

该漏洞影响 MLflow 3.4.0 及之前的所有版本,攻击者可以通过恶意网站对运行在本地或内网的 MLflow 服务发起未授权访问,窃取或篡改机器学习实验数据。


八、参考链接

  • CVE-2025-14279 – NVD

  • huntr.com 漏洞报告

  • MLflow 修复 Commit

  • MLflow 安全配置文档

  • DNS Rebinding 攻击原理


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:SecurityPaper whoami0002 whoami0002《CVE-2025-14279: MLflow DNS Rebinding 漏洞分析》

wasm逆向初探 网络安全文章

wasm逆向初探

文章总结: 文档基于吾爱破解红包题介绍了WebAssembly逆向分析方法。内容涵盖开发环境搭建及静态分析技巧,如利用Ghidra插件或通过wabt转C代码配合
评论:0   参与:  0