文章总结: 本文深入分析CVE-2025-14279漏洞,指出MLflow因未校验Host头而易受DNSRebinding攻击,导致内网API被未授权访问。文章详细阐述了攻击原理与环境搭建过程,利用rbndr.us成功复现漏洞,并剖析了官方在3.5.0版本通过引入安全中间件进行Host验证与CORS防护的修复方案,建议用户升级以修复漏洞。 综合评分: 90 文章分类: 漏洞分析,AI安全,WEB安全,应用安全
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 解析机制绕过浏览器同源策略的攻击技术。攻击的核心思想是:
- 攻击者控制一个域名(如
evil.com)及其 DNS 服务器 - 第一次 DNS 查询返回攻击者服务器的 IP(如
1.2.3.4) - 受害者浏览器加载攻击者的恶意页面
- 攻击者将 DNS 记录更改为目标内网 IP(如
127.0.0.1或192.168.1.100) - 当恶意 JavaScript 发起请求时,浏览器认为仍在访问
evil.com(同源),但实际请求发送到了内网服务
2.2 攻击流程图
┌─────────────────────────────────────────────────────────────────────┐
│ DNS Rebinding 攻击流程 │
└─────────────────────────────────────────────────────────────────────┘
┌──────────┐ ┌──────────┐ ┌──────────────┐
│ 受害者 │ │ 攻击者 │ │ MLflow │
│ 浏览器 │ │ DNS/Web │ │ Server │
└────┬─────┘ └────┬─────┘ │ (127.0.0.1) │
│ │ └──────┬───────┘
│ 1. 访问 evil.com │ │
│ ─────────────────────────>│ │
│ │ │
│ 2. DNS 返回 1.2.3.4 │ │
│ <─────────────────────────│ │
│ │ │
│ 3. 加载恶意页面 │ │
│ <─────────────────────────│ │
│ │ │
│ [恶意 JS 等待 DNS TTL 过期] │
│ │ │
│ 4. 再次查询 evil.com DNS │ │
│ ─────────────────────────>│ │
│ │ │
│ 5. DNS 返回 127.0.0.1 ⚠️ │ │
│ <─────────────────────────│ │
│ │ │
│ 6. JS 发送请求到 evil.com │ │
│ (浏览器认为是同源) │ │
│ ─────────────────────────────────────────────────────>│
│ │ │
│ 7. MLflow 返回敏感数据 │ │
│ <─────────────────────────────────────────────────────│
│ │ │
│ 8. JS 将数据发送给攻击者 │ │
│ ─────────────────────────>│ │
│ │ │
2.3 为什么 MLflow 受影响?
在 MLflow 3.4.0 及之前的版本中:
- 缺乏 Host 头验证:服务器不验证请求的 Host 头是否合法
- 缺乏 Origin 验证:不检查请求的来源是否在允许列表中
- 无 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 -m venv mlflow_vuln_env
cd mlflow_vuln_env
# Windows
.\Scripts\activate
# Linux/Mac
source bin/activate
# 安装漏洞版本
pip install mlflow==3.4.0
4.3 启动 MLflow Server
# 使用 0.0.0.0 以便 DNS Rebinding 攻击可以访问
mlflow server --host127.0.0.1 --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 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 添加了一个完整的安全中间件层,包括:
- Host 头验证 (DNS Rebinding 防护)
- *CORS 保护
- X-Frame-Options 头 (防止点击劫持)
- 安全响应头**
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:
"""
Host 头验证中间件 - 防止 DNS Rebinding 攻击
通过验证 HTTP 请求的 Host 头是否在允许列表中,
阻止来自恶意域名的请求访问内部服务。
"""
def__init__(self, app, allowed_hosts: list[str]):
self.app=app
self.allowed_hosts=allowed_hosts
# 编译通配符模式为正则表达式
self.allowed_host_patterns= [
self._compile_pattern(host) forhostinallowed_hosts
]
def_compile_pattern(self, pattern: str):
"""将通配符模式编译为正则表达式"""
importre
# 支持 *.example.com 和 localhost:* 格式
regex=pattern.replace(".", r"\.").replace("*", r".*")
returnre.compile(f"^{regex}$", re.IGNORECASE)
asyncdef__call__(self, scope, receive, send):
ifscope["type"] !="http":
awaitself.app(scope, receive, send)
return
# 提取 Host 头
headers=dict(scope["headers"])
host=headers.get(b"host", b"").decode("utf-8")
# ✅ 关键修复:验证 Host 头是否在允许列表中
ifnotself._is_valid_host(host):
# 返回 400 Bad Request,拒绝可疑请求
response=Response(
content="Invalid Host header",
status_code=400
)
awaitresponse(scope, receive, send)
return
awaitself.app(scope, receive, send)
def_is_valid_host(self, host: str) ->bool:
"""检查 Host 是否匹配允许的模式"""
# 移除端口号进行匹配
host_without_port=host.split(":")[0] if":"inhostelsehost
forpatterninself.allowed_host_patterns:
ifpattern.match(host) orpattern.match(host_without_port):
returnTrue
returnFalse
classCORSBlockingMiddleware:
"""
CORS 阻止中间件 - 防止跨域攻击
验证 Origin 头是否在允许列表中,
阻止恶意网站的跨域请求。
"""
STATE_CHANGING_METHODS= {"POST", "PUT", "DELETE", "PATCH"}
def__init__(self, app, allowed_origins: list[str]):
self.app=app
self.allowed_origins=allowed_origins
self.allow_all="*"inallowed_origins
asyncdef__call__(self, scope, receive, send):
ifscope["type"] !="http":
awaitself.app(scope, receive, send)
return
headers=dict(scope["headers"])
origin=headers.get(b"origin", b"").decode("utf-8")
method=scope.get("method", "GET")
# ✅ 关键修复:对状态变更请求验证 Origin
iforiginandmethodinself.STATE_CHANGING_METHODS:
ifnotself._is_allowed_origin(origin):
response=Response(
content="CORS request blocked",
status_code=403
)
awaitresponse(scope, receive, send)
return
awaitself.app(scope, receive, send)
def_is_allowed_origin(self, origin: str) ->bool:
"""检查 Origin 是否被允许"""
ifself.allow_all:
returnTrue
returnany(
self._match_origin(origin, allowed)
forallowedinself.allowed_origins
)
classSecurityHeadersMiddleware:
"""
安全响应头中间件 - 防止点击劫持和 XSS
自动添加安全相关的 HTTP 响应头。
"""
def__init__(self, app, x_frame_options: str="SAMEORIGIN"):
self.app=app
self.x_frame_options=x_frame_options
asyncdef__call__(self, scope, receive, send):
ifscope["type"] !="http":
awaitself.app(scope, receive, send)
return
asyncdefsend_wrapper(message):
ifmessage["type"] =="http.response.start":
headers=dict(message.get("headers", []))
# ✅ 添加安全响应头
headers[b"x-content-type-options"] =b"nosniff"
headers[b"x-frame-options"] =self.x_frame_options.encode()
headers[b"x-xss-protection"] =b"1; mode=block"
message["headers"] =list(headers.items())
awaitsend(message)
awaitself.app(scope, receive, send_wrapper)
defconfigure_security_middleware(app, config):
"""
配置安全中间件层 - MLflow 3.5.0+ 的核心修复
按正确顺序添加所有安全中间件。
中间件执行顺序(后添加的先执行):
1. SecurityHeadersMiddleware - 添加安全响应头
2. CORSMiddleware - 处理 CORS 预检请求
3. CORSBlockingMiddleware - 阻止非法跨域请求
4. HostValidationMiddleware - 验证 Host 头
"""
ifconfig.disable_security_middleware:
_logger.warning(
"Security middleware is disabled. "
"Only use this when security is handled by a reverse proxy."
)
return
allowed_hosts=config.get_allowed_hosts()
allowed_origins=config.get_allowed_origins()
# ✅ 添加安全响应头中间件
app.add_middleware(
SecurityHeadersMiddleware,
x_frame_options=config.x_frame_options
)
# ✅ 添加 CORS 中间件 (Starlette 标准中间件)
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ✅ 添加 CORS 阻止中间件 (自定义,处理状态变更请求)
app.add_middleware(
CORSBlockingMiddleware,
allowed_origins=allowed_origins
)
# ✅ 添加 Host 头验证中间件
app.add_middleware(
HostValidationMiddleware,
allowed_hosts=allowed_hosts
)
_logger.info(f"Security middleware configured:")
_logger.info(f" Allowed hosts: {allowed_hosts}")
_logger.info(f" Allowed CORS origins: {allowed_origins}")
_logger.info(f" X-Frame-Options: {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):
"""Create FastAPI application with security middleware."""
app=FastAPI(
title="MLflow Tracking Server",
...
)
# ✅ 补丁新增:配置安全中间件
ifnotconfig.disable_security_middleware:
configure_security_middleware(
app,
allowed_hosts=config.allowed_hosts,
cors_allowed_origins=config.cors_allowed_origins,
x_frame_options=config.x_frame_options,
)
else:
_logger.warning(
"Security middleware is disabled. "
"Ensure security is handled by your reverse proxy."
)
# Mount Flask app for backward compatibility
app.mount("/", WSGIMiddleware(flask_app))
returnapp
七、总结
CVE-2025-14279 是一个典型的 DNS Rebinding 漏洞,其根本原因在于:
- 缺乏 Host 头验证:服务器接受任意 Host 头,无法防御 DNS Rebinding
- CORS 配置不当:允许任意来源的跨域请求
- 无安全响应头:缺少必要的安全 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 漏洞分析》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论