untrust
一款针对 attestation 忽略的信任边界的 TEE 部署审计工具。
云端 TEE(AWS Nitro Enclaves、AMD SEV-SNP、Intel TDX)承诺,即使宿主机被完全攻破,也无法触及硬件隔离的 enclave。其密码学 attestation 的机制是可靠的。但部署层面并非如此。
每个 TEE 工作负载都必须从外部接收*某些内容*:来自云端对象存储的 bootstrap 状态、来自宿主机的环境变量、以及其策略本应(但通常并未)强制执行 attestation 的 KMS 密钥。这些输入均不受 attestation 保证的保护。而所有这些都曾在真实的漏洞利用中被使用过。
`untrust` 会审计 TEE attestation 未覆盖的信任边界,并生成包含具体修复指导的通过/失败报告。
## 为什么会有这个项目
`untrust` 诞生于一次真实的对抗模拟之后,在这次模拟中,仅仅拥有云存储的单次写入权限,就足以在硬件隔离的 enclave 内部以 root 身份执行完整的远程代码执行 (RCE)。这个漏洞存在于 bootstrap 状态下载过程中的路径遍历问题——这是一种自 1998 年就存在的漏洞类别,却击垮了价值万亿美元的信任边界。
展示此项研究的演讲在 **DEF CON 34**(2026 年 8 月)上进行:*"Enclave 在对你撒谎:通过启动时状态打破 TEE 信任边界。"*
## 安装
```
pip install untrust
```
需要 Python 3.10+ 及已配置的 AWS 凭证(用于实时扫描)。
## 快速入门
### 针对真实部署的实时扫描
```
untrust scan \
--target-bucket my-enclave-state \
--kms-key-id arn:aws:kms:us-west-2:111111111111:key/abc... \
--instance-id i-0abc123 \
--region us-west-2 \
--output report.json
```
### Demo 模式(无需 AWS 凭证)
```
untrust scan --demo
```
### 示例输出
对内置模拟部署运行 `untrust scan --demo`:
使用 `untrust list-checks` 列出每项检查及其严重程度:
## 审计内容
涵盖八大类别的 33 项检查,每一项都映射到真实的漏洞利用路径。
### Bootstrap 与供应链
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **BOOTSTRAP-01** | S3 bucket 是否接受状态前缀中的路径遍历键名 (`../`)? | 通过上传单个对象实现 enclave RCE |
| **BOOTSTRAP-02** | bucket 策略是否将 `s3:PutObject` 限制为特定主体? | 任何 IAM 主体都可以在 enclave 的状态中植入文件 |
### 对象存储(状态 bucket)
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **S3-01** | 是否启用了全部四项 S3 公共访问阻断设置? | bootstrap 状态被公开暴露 |
| **S3-02** | 是否开启了默认的 SSE-KMS 加密,并配置了仅限 TLS (`aws:SecureTransport`) 的拒绝策略? | 状态在静态和传输过程中面临明文及 MITM 攻击 |
| **ROLLBACK-01** | 是否有 S3 Object Lock (WORM) 保护状态以防止回滚? | 攻击者将状态回滚到 enclave 重新加载的旧有效版本 |
| **AUDIT-01** | 状态 bucket 是否启用了版本控制和服务器访问日志记录? | 静默覆盖且不留下任何取证痕迹 |
### 替代状态后端
bootstrap 状态的信任边界与后端无关——attestation 完全不覆盖这些。如果 enclave 从 S3 以外的平台加载状态,请使用相应的标志进行定向扫描(`--dynamodb-table`、`--secret-arn`、`--parameter-path`、`--efs-id`、`--db-instance`)。除非指定了后端名称,否则每项检查都将跳过。
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **DDB-01** | DynamoDB 状态表:客户管理的 CMK、PITR、删除保护、resource-policy 写入范围、数据事件审计 | 项目篡改/回滚、未经 attestation 门控的解密、未经审计的写入 |
| **SECRETS-01** | Secrets Manager:客户管理的 CMK、轮换、非通配符 resource policy、数据事件审计 | 未经 attestation 门控的密钥检索、跨账户/通配符读取 |
| **SSM-01** | Parameter Store:位于客户管理的 CMK(而非 `alias/aws/ssm`)下的 `SecureString` | 明文配置/机密读取;未经 attestation 门控的解密 |
| **EFS-01** | EFS/EBS 状态文件系统:CMK 加密、强制 TLS 的 FS 策略、备份 | 开放挂载、静态明文、篡改后无法恢复 |
| **RDS-01** | RDS/Aurora:CMK 存储加密、非公开、无 `0.0.0.0/0` 入口、IAM 认证、删除保护、无公开快照 | 直接连接数据库、静态密码认证、公开快照数据泄露 |
### KMS 与 Attestation
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **KMS-01** | 每条 Allow+Decrypt 语句是否针对**真实的代码度量值**强制执行了 attestation(不是全零,也不是仅限身份的 PCR3/PCR4)? | 绕过 KMS 且无需 enclave,或 debug enclave 解密了生产密钥 |
### IAM 与访问控制
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **IMDS-01** | 是否强制启用了 IMDSv2 (`HttpTokens: required`)? | 通过 HTTP GET 窃取未认证凭证 |
| **IAM-01** | 实例角色是否对 S3/KMS 资源拥有通配符 `*` 权限? | enclave 或攻击者可访问账户中的任何 bucket/密钥 |
| **SSH-01** | 是否禁用了 SSH 并移除了 EC2 Instance Connect? | 通过 `SendSSHPublicKey` 权限进行横向移动 |
### 网络与宿主机
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **NAT-01** | 宿主机的网桥是否从 enclave 流量中过滤了 IMDS? | 在 enclave 内部窃取宿主机 IAM 凭证 |
| **PORT-01** | 宿主机上是否存在未预期的监听 TCP 端口? | 额外的远程攻击面 |
| **HOST-01** | 敏感文件(EIF、密钥、机密、环境变量)是否配置了受限权限? | 非特权用户窃取凭证/镜像 |
| **HOST-02** | 与 enclave 相关的 systemd 服务是否以非 root 用户运行? | 一旦服务被攻破即刻获得 root 权限 |
| **EXEC-01** | 状态目录下的文件是否不存在执行权限? | 通过替换状态文件在宿主机上执行代码 |
| **VSOCK-01** | 是否存在需要人工认证审查的 vsock 监听器? | 未经认证的宿主机→enclave RPC 攻击面 |
| **DNS-01** | 宿主机是否对来自 enclave 的 DNS 进行了 DNAT 重定向? | 若缺少 TLS pinning,则面临基于 DNS 的 MITM |
| **VPC-01** | 宿主机是否不存在公网 IP、VPC peering 和 transit-gateway 连接? | 扩大对 enclave 宿主机的网络可访问范围 |
### 宿主机内存与持久化清理
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **CORE-01** | 是否禁用了核心转储 (core dumps)? | 崩溃时会将 enclave 附近的机密以明文形式写入宿主机磁盘 |
| **SWAP-01** | 是否禁用了 swap? | 进程内存被分页到未加密的磁盘上 |
| **LOG-01** | enclave 的 journal 日志是否仅限 root 访问? | 非特权日志访问泄露了密钥/token 上下文 |
| **RESTART-01** | enclave 服务是否避免了自动重启 + 重新下载不受信任的状态? | 每次重启时都会因一个中毒对象导致被持续重复利用 |
### Enclave 运行时
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **ENCLAVE-01** | enclave 是否运行在 debug 模式之外? | debug enclave 会将所有 PCR 置零,从而破坏 attestation |
| **ENCLAVE-02** | enclave 的 PCR 度量值是否存在且非零? | attestation 实际上并未激活 |
| **ENCLAVE-03** | 每台宿主机是否只运行一个 enclave? | 共享大页/CPU 争用以及合租侧信道攻击 |
| **ENCLAVE-04** | enclave 是否从**已签名**的 EIF (PCR8) 启动并验证了签名? | 没有签名身份来绑定 KMS;也没有与构建 pipeline 的关联 |
### 配置
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **ENV-01** | 宿主机提供的环境变量文件是否不含危险变量且在语义上有效? | 流量重定向 (HTTPS_PROXY)、状态注入 (BUCKET_NAME) |
### 检测与取证
| 检查项 | 验证内容 | 失败导致的后果 |
|-------|-----------------|-----------------|
| **CLOUDTRAIL-01** | 是否存在记录管理事件(KMS `Decrypt`)及状态 bucket 的 S3 数据事件的追踪? | 实时的 KMS 拦截和状态篡改不会留下任何审计痕迹 |
## `untrust` 刻意*不*检查的内容(及原因)
一款诚实的扫描器应当指出自身的盲区。这些威胁是真实存在的,但部署配置扫描器无法对它们进行有效测试——它们需要代码审查、在 enclave *内部*进行运行时自省,或者属于硬件供应商的责任。以上内容已与机密计算联盟威胁模型、MITRE/COIN enclave 接口研究、Trail of Bits 的 Nitro 攻击面说明以及近期的学术研究(SGX.Fail、TEE.Fail)进行了交叉对比。
| 威胁 | 排除原因 | 归属领域 |
|--------|----------------------|------------------|
| **熵源** (`rng_current` = `nsm-hwrng`) 和 **时钟源** (`kvm-clock`) | 只能在 enclave *内部*观察;没有宿主机/SSM 访问路径 | Enclave 运行时自检 |
| **Attestation nonce / 时间戳新鲜度** | 这是 enclave 消耗 attestation 的代码属性,而非部署配置 | 应用程序代码审查 |
| **常数时间加密 / 时序侧信道** | 需要代码和微架构分析 | 应用程序代码审查 |
| **vsock 接口输入验证** (MITRE COIN: 并发、顺序、输入、嵌套) | 双向的宿主机↔enclave 协议由应用程序定义;`VSOCK-01` 仅标记是否存在监听器 | 应用程序代码审查 / 模糊测试 |
| **物理与微架构攻击** (TEE.Fail DDR 介入、Battering RAM、Wiretap、L3 缓存) | 硬件/供应商层面;Nitro 不向客户提供内存加密密钥路径,也无物理操作员访问权限 | AWS 管理 / 可接受的风险 |
| **可重复构建与独立 PCR 验证** | 属于 CI/CD 过程控制(例如仲裁构建),而非运行时状态 | 构建 pipeline / 供应链策略 |
## CLI 参考
```
# 运行所有检查
untrust scan --target-bucket BUCKET --kms-key-id KEY --instance-id INSTANCE
# 审计非 S3 状态后端(任意组合)
untrust scan --dynamodb-table TABLE --kms-key-id KEY
untrust scan --secret-arn ARN
untrust scan --parameter-path /enclave/
untrust scan --efs-id fs-0123 --db-instance prod-db
# 仅被动扫描 — 跳过侵入性检查(S3 写入探测和所有
# host/nitro-cli SSM 命令),以避免触发 SOC/EDR 检测
untrust scan --target-bucket BUCKET --kms-key-id KEY --instance-id INSTANCE --read-only
# 以演示模式运行(模拟易受攻击的部署)
untrust scan --demo
# 输出 JSON 报告
untrust scan --demo --output report.json
untrust scan --demo --json
# 列出可用检查
untrust list-checks
# 版本
untrust --version
```
## JSON 输出
`--output` 和 `--json` 标志会生成结构化输出,适合与 CI/CD pipeline、SIEM 系统或安全仪表板集成:
```
{
"version": "1.0.0",
"timestamp": "2026-08-24T14:30:22.000000+00:00",
"target": {
"bucket": "enclave-state-XXXXXXXXXXXX",
"kms_key_id": "arn:aws:kms:us-west-2:XXXXXXXXXXXX:key/demo-key-id",
"instance_id": "i-0abc123def456789a",
"region": "us-west-2"
},
"summary": {
"total": 28,
"pass": 0,
"fail": 28,
"skip": 0,
"error": 0
},
"findings": [...]
}
```
## 路线图
- **v1.0 (DEF CON 34, 2026年8月):** AWS Nitro Enclaves,33 项检查(S3 + DynamoDB/Secrets Manager/SSM/EFS/RDS 状态后端),JSON 输出
- **v1.1:** 用于集成 GitHub Advanced Security 的 SARIF 输出格式
- **v2.0:** AMD SEV-SNP attestation 策略审计
- **v2.1:** Intel TDX bootstrap 完整性检查
- **v3.0:** Azure Confidential Containers,GCP Confidential VMs
- **未来 针对特定供应商 TEE 平台的 Plugin API
## 工作原理
`untrust` 使用 AWS SDK (boto3) 和 SSM 来检查目标部署。它结合了多类检查(运行 `untrust list-checks` 查看全部 33 项检查):
- **Cloud-API 检查** 直接读取 S3、KMS、EC2、IAM 和 CloudTrail 配置 —— 例如 `KMS-01` 执行语义密钥策略评估(拒绝全零和仅限身份的 PCR 条件),`ROLLBACK-01` 读取 S3 Object Lock,`S3-02` 读取 bucket 加密和仅限 TLS 的策略,`CLOUDTRAIL-01` 确认 KMS/S3 活动已被真实记录。
- **替代后端检查** 在定向时对非 S3 状态存储应用相同的存储平面控制:DynamoDB (`DDB-01`)、Secrets Manager (`SECRETS-01`)、SSM Parameter Store (`SSM-01`)、EFS/EBS (`EFS-01`) 以及 RDS/Aurora (`RDS-01`)。每一项都检查客户管理的 CMK(以便 `KMS-01` attestation 能够进行门控)、最小特权/非公开访问、防回滚以及审计覆盖范围。CMK 状态通过 `kms:DescribeKey` (`KeyMetadata.KeyManager`) 权威解析 —— 字符串检查无法区分 AWS 管理的服务密钥和客户 CMK,因为两者都显示为已解析的密钥 ARN。
- **宿主机检查(通过 SSM `AWS-RunShellScript`)** 在父实例上运行只读命令 —— SSH/端口/服务状态、文件和执行权限、IMDS 过滤、DNS DNAT、核心转储/swap/journal 清理以及重启持久化。
- **Enclave 运行时检查(通过 SSM + `nitro-cli`)** 确认 enclave 退出 debug 模式、具有非零 PCR、非合租属性,并且是从已签名的 EFI 启动(`describe-eif` → PCR8 + 签名验证)。
- **BOOTSTRAP-01** 额外上传带有路径遍历键名的金丝雀 (canary) 对象,并删除任何上传成功的对象。被*拒绝*的写入 —— 收到 `403 AccessDenied` **或**任何其他客户端(`4xx`)响应(例如 bucket 策略/加密条件返回的 `400`)—— 将被视为**已阻断(PASS)**,因为对象从未落地。只有临时/服务器端故障(节流、`5xx`)才会被报告为 `ERROR`。
### 只读模式
`untrust scan --read-only` 仅运行被动的 Cloud-API 检查并跳过侵入性检查 —— 即 `BOOTSTRAP-01` 写入探测以及所有通过 SSM `AWS-RunShellScript` 在实例上执行 shell 的宿主机/enclave 检查。适用于需要安全态势快照,但不想产生写入事件或宿主机命令执行(以免触发 SOC/EDR pipeline 告警)的场景。
### 所需 IAM 权限
执行扫描的身份需要以下权限:
```
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "UntrustS3Checks",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:DeleteObject",
"s3:GetBucketVersioning",
"s3:GetBucketLogging",
"s3:GetBucketPolicy",
"s3:GetBucketPublicAccessBlock",
"s3:GetEncryptionConfiguration",
"s3:GetBucketObjectLockConfiguration"
],
"Resource": [
"arn:aws:s3:::YOUR-STATE-BUCKET",
"arn:aws:s3:::YOUR-STATE-BUCKET/*"
]
},
{
"Sid": "UntrustKms",
"Effect": "Allow",
"Action": "kms:GetKeyPolicy",
"Resource": "arn:aws:kms:REGION:ACCOUNT:key/KEY-ID"
},
{
"Sid": "UntrustEc2",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DescribeVpcPeeringConnections",
"ec2:DescribeTransitGatewayVpcAttachments"
],
"Resource": "*"
},
{
"Sid": "UntrustCloudTrail",
"Effect": "Allow",
"Action": [
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"cloudtrail:GetEventSelectors"
],
"Resource": "*"
},
{
"Sid": "UntrustIam",
"Effect": "Allow",
"Action": [
"iam:GetInstanceProfile",
"iam:ListRolePolicies",
"iam:GetRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:GetPolicy",
"iam:GetPolicyVersion"
],
"Resource": "*"
},
{
"Sid": "UntrustStateBackends",
"Effect": "Allow",
"Action": [
"kms:DescribeKey",
"dynamodb:DescribeTable",
"dynamodb:DescribeContinuousBackups",
"dynamodb:GetResourcePolicy",
"secretsmanager:DescribeSecret",
"secretsmanager:GetResourcePolicy",
"ssm:DescribeParameters",
"elasticfilesystem:DescribeFileSystems",
"elasticfilesystem:DescribeFileSystemPolicy",
"elasticfilesystem:DescribeBackupPolicy",
"rds:DescribeDBInstances",
"rds:DescribeDBSnapshots",
"rds:DescribeDBSnapshotAttributes",
"ec2:DescribeSecurityGroups"
],
"Resource": "*"
},
{
"Sid": "UntrustSsm",
"Effect": "Allow",
"Action": [
"ssm:SendCommand",
"ssm:GetCommandInvocation"
],
"Resource": [
"arn:aws:ssm:REGION:ACCOUNT:document/AWS-RunShellScript",
"arn:aws:ec2:REGION:ACCOUNT:instance/INSTANCE-ID"
]
}
]
}
```
**BOOTSTRAP-01** 会向目标 bucket 写入金丝雀对象并在完成后将其删除 —— 请将 `s3:PutObject`/`s3:DeleteObject` 操作范围限制为专用的审计角色。**宿主机和 enclave 运行时检查**(SSH-01、PORT-01、NAT-01、HOST-01、HOST-02、EXEC-01、ENV-01、VSOCK-01、DNS-01、CORE-01、SWAP-01、LOG-01、RESTART-01、ENCLAVE-01/02/03/04)通过 SSM 在宿主机上执行只读 shell/`nitro-cli` 命令 —— 请确保 SSM 代理正在运行,且实例配置文件允许 SSM 会话。其余检查使用 S3、KMS、EC2、IAM 和 CloudTrail 读取 API。
## 背景阅读
- [AWS Nitro Enclaves 用户指南](https://docs.aws.amazon.com/enclaves/latest/user/nitro-enclave.html)
- [使用 AWS KMS 进行 Nitro Enclaves 的密码学 Attestation](https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html)
- [NCC Group, "公开报告 — AWS Nitro 系统安全审查" (2023)](https://research.nccgroup.com/2023/04/)
- [Trail of Bits, "AWS Nitro Enclaves 安全评估" (2022)](https://github.com/trailofbits/publications)
- [OWASP, "路径遍历"](https://owasp.org/www-community/attacks/Path_Traversal)
## 披露
促成本工具开发的漏洞是在针对生产环境 TEE 部署的授权对抗模拟中发现的。它们已被报告给受影响的供应商,修复程序已在后续版本中发布。协调披露流程已完成。`untrust` 不包含任何特定于供应商的漏洞利用代码或专有信息 —— 它基于公开的云 API 通用化地实现了这些审计检查。
## 许可证
MIT。详见 [LICENSE](LICENSE)。
## 作者
[Sandeep Jayashankar](https://github.com/pyro-0x) (pyro) — 进攻性云安全研究员。
DEF CON 34 演讲者。研究方向:针对机密计算部署的对抗模拟。