
Script de detección de seguridad de autenticación de Milvus: CVE-2025-64513 (backdoor sourceid) / CVE-2026-26190 (token débil /expr) / puerto interno 53100
| Vulnerabilidad | CVE | Versiones afectadas | Método de detección |
|---|
| Bypass de autenticación mediante backdoor sourceid | CVE-2025-64513 | < 2.4.24 / < 2.5.21 / < 2.6.5 | gRPC ListDatabases + inyección de sourceid |
| Token débil de /expr en puerto de administración | CVE-2026-26190 | < 2.5.27 / < 2.6.10 | HTTP /expr?code=1%2B1&auth=by-dev (el parámetro code debe codificarse en URL) |
| Puerto interno rootcoord 53100 sin autenticación | — | < 2.6.10 (deja de escucharse desde 2.6.10) | Conexión gRPC directa a RootCoordService |
# proxy 层检测(sourceid 后门 + /expr 弱 token)
python3 milvus-auth-audit.py --host 127.0.0.1 --port 19530 --mgmt-port 9091
# 完整检测(含内部端口,需容器网络内可达)
python3 milvus-auth-audit.py --host <容器IP> --port 19530 --mgmt-port 9091 --internal-port 53100
Parámetros:
--host: dirección del proxy de Milvus--port: puerto gRPC del proxy (por defecto 19530)--mgmt-port: puerto de administración (por defecto 9091, aquí está /expr)--internal-port: puerto interno (rootcoord por defecto 53100, pasar 0 para omitirlo)--cve-check: muestra la información sobre las versiones afectadas por CVEpip install grpcio protobuf
Las llamadas gRPC requieren el código Python generado a partir de las definiciones proto (milvus_pb2_grpc.py, root_coord_pb2_grpc.py, etc.). Debe colocarse en el subdirectorio proto/ del mismo directorio que el script. Para generarlo:
# 1. 拉 milvus-proto 仓库
git clone https://github.com/milvus-io/milvus-proto.git
# 2. 拉 milvus 源码(内部 proto:root_coord.proto / internal.proto / proxy.proto 等)
git clone https://github.com/milvus-io/milvus.git
# 3. 生成(milvus 内部 proto 在 milvus/pkg/proto/ 下)
pip install grpcio-tools
python3 -m grpc_tools.protoc -I milvus-proto/proto -I milvus/pkg/proto \
--python_out=proto --grpc_python_out=proto \
milvus-proto/proto/milvus.proto milvus/pkg/proto/root_coord.proto \
milvus/pkg/proto/internal.proto milvus/pkg/proto/proxy.proto
=== 2.6.4 ===
[*] 目标: 172.22.0.4:19530 管理端口: 9091
[check] 认证状态: 已开启认证(authorizationEnabled=true)
[verify] sourceid 后门绕过认证, 数据库=['default'] -> HIT
[verify] /expr 任意表达式执行 (auth=by-dev) -> HIT
[exploit] 内部端口未认证, 数据库=['default'] -> HIT
[!] 发现 3 个可利用认证缺陷
=== 2.6.5 ===
[check] 认证状态: 已开启认证(authorizationEnabled=true)
[verify] sourceid 被拒绝 -> SAFE
[verify] /expr 任意表达式执行 (auth=by-dev) -> HIT
[exploit] 内部端口未认证, 数据库=['default'] -> HIT
[!] 发现 2 个可利用认证缺陷
=== 2.6.10 ===
[check] 认证状态: 已开启认证(authorizationEnabled=true)
[verify] sourceid 被拒绝 -> SAFE
[verify] /expr 已默认禁用 -> SAFE
[exploit] 端口不可达 -> SAFE
[+] 未发现认证缺陷
internal/proxy/authentication_interceptor.go, validSourceID() comprueba el header sourceId; si su valor decodificado en base64 es igual a @@milvus-member@@, se omite toda la rama de autenticación. Es un mecanismo de confianza mutua entre componentes internos (PerRPCCredentials en grpcclient/auth.go), pero sin validación de origen, por lo que un atacante externo puede falsificarlo. Cadena de explotación completa: sourceid + authorization=base64("root:假密码") = full admin (el proxy omite la validación y transmite la identidad falsa tal cual)./expr del puerto de administración 9091 obtiene el token de autenticación de etcd.rootPath (por defecto by-dev), que es completamente predecible, y permite ejecutar expresiones expr-lang arbitrarias. Desde 2.6.10 está controlado por common.security.exprEnabled y deshabilitado por defecto.AuthenticationInterceptor solo está registrado en el proxy (19530); el servidor gRPC interno de rootcoord (53100) no tiene autenticación. Una conexión directa sin autenticación dentro de la red del contenedor otorga full admin. Desde 2.6.10 este puerto ya no escucha.Úselo únicamente para pruebas de seguridad en entornos autorizados. No lo utilice en sistemas no autorizados.