CVE-2026-103956 - Loom for AWS - 严重 - 认证绕过 - 未配置 IdP 时可未授权获得超级管理员权限
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cve-2026-103956-loom-unauth
Loom for AWS < 1.6.1 - AWS Labs
当 Cognito 未设置且没有外部 IdP 处于活动状态时,get_current_user 会给每个请求赋予 t-admin / g-admins-super。这包括没有 Authorization 头的请求。在 IdP 设置之前的新部署就是一个开放的管理面板。
| ID | CVE-2026-103956 |
| CWE | CWE-306 / CWE-1188 |
| CVSS | 严重:10.0 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| 产品 | Loom for AWS |
| 受影响版本 | < 1.6.1。实验环境固定为 v1.6.0(8c658d61)。已在 v1.6.1(ccad5665)中修复。 |
| 认证 | 未认证 |
| 类别 | 认证绕过 / 未认证超级管理员(ATO) |
| 可达性 | 远程(未认证) |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1 |
攻击者无需任何凭据即可掌控代理控制平面。
GET /api/auth/me 会返回 username=local-dev、sub=local、组 t-admin 和 g-admins-super。GROUP_SCOPES 中的每个作用域都随该身份一并获得。POST /api/mcp/servers 返回 201。MCP、A2A、代理、记忆、安全、设置、凭据和管理审计都位于同一依赖之后。GET /api/mcp/servers/{id}/export 需要 admin:write。在此固定版本上,它会从 SQLite 返回 oauth2_client_secret。CVE 文本还提到对托管代理角色的 IAM 角色策略重写;该路径需要 AWS,不在本回环实验范围内。v1.6.1 需要 LOOM_ALLOW_UNAUTHENTICATED_LOCAL_DEV 以及回环客户端。同一请求返回 401(No identity provider configured)。
AWS 发布了 CVE-2026-103956,附带 GHSA-vgmj-998f-r8mp 和安全公告 2026-124-AWS。我将 awslabs/loom v1.6.0(8c658d61)与 v1.6.1(ccad5665)并排固定,并在未设置 LOOM_COGNITO_USER_POOL_ID 的情况下用 SQLite 运行后端。
backend/app/dependencies/auth.py 中的 get_current_user 会检查 Cognito 环境变量和活动的 IdP 记录。两者均为空时:它返回 UserInfo(sub="local", username="local-dev", groups=["t-admin", "g-admins-super"], scopes=ALL_SCOPES)。令牌从未被读取。
我在回环地址 127.0.0.1:18180(v1.6.0)和 18181(v1.6.1)上启动了原版 FastAPI。没有前端。没有 AWS。在 1.6.0 上,未认证的 GET /api/auth/me 返回 200,并带有那些组。未认证的 POST /api/mcp/servers 携带 oauth2_client_secret=CVE-2026-103956-WITNESS 返回 201。GET /api/mcp/servers/1/export 将密钥原样返回。在 1.6.1 上,同样的 /api/auth/me 返回 401。
SUCCESS CVE-2026-103956 me-http=200 me-user=local-dev me-sub=local me-groups=t-admin,g-admins-super mcp-create=201 export-has-secret=yes list-has-witness=yes patched-me-http=401 CVE-2026-103956-WITNESS
已记录的误判:public.ecr.aws/docker/library/python:3.13-slim 因 Docker Hub 的 python:3.13-slim 而被跳过;v1.6.0 上首次 /health 在 uvicorn 已绑定时返回 curl 52,随后返回 200;MCP 创建 schema 在第一次 POST 时即匹配,没有 422 重试。一个反向 shell。一场戏。判定依据是 /api/auth/me 加上导出的密钥。
cd lab
./run.sh
仅针对 http://127.0.0.1:18180(v1.6.0)和 http://127.0.0.1:18181(v1.6.1)。run.sh 会浅克隆这些标签,构建两个后端,然后拆除整个栈。使用 SQLite。不设置 Cognito 环境变量。在已修补的服务上不设置 LOOM_ALLOW_UNAUTHENTICATED_LOCAL_DEV。
升级到 1.6.1 或更高版本。针对相关的 SSRF/令牌问题,AWS 建议使用 1.7.0。1.6.1 的绕过是可选启用的,且仅限回环地址。在此之前,请在后端可被回环之外的地址访问之前完成 Cognito 或外部 IdP 的配置,并在任何已部署的环境中保持 LOOM_ALLOW_UNAUTHENTICATED_LOCAL_DEV 未设置。
backend/app/dependencies/auth.py(get_current_user)