名称: cosmos-vulnerability-scanner 描述: 扫描Cosmos SDK区块链,检测9种共识关键漏洞,包括非确定性、不正确签名者、ABCI崩溃和舍入错误。适用于审计Cosmos链或CosmWasm合约。
Cosmos 漏洞扫描器
1. 目的
系统性地扫描Cosmos SDK区块链模块和CosmWasm智能合约,检测可能导致链停止、共识失败或资金损失的平台特定安全漏洞。本技能编码了9种基于Cosmos链的独特关键漏洞模式。
2. 何时使用此技能
- 审计Cosmos SDK模块(自定义x/模块)
- 审查CosmWasm智能合约(Rust)
- Cosmos链预启动安全评估
- 调查链停止事件
- 验证共识关键代码变更
- 审查ABCI方法实现
3. 平台检测
文件扩展名和指标
- Go文件:
.go,.proto - CosmWasm:
.rs(Rust文件,包含cosmwasm导入)
语言/框架标记
// Cosmos SDK指标
import (
"github.com/cosmos/cosmos-sdk/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/..."
)
// 常见模式
keeper.Keeper
sdk.Msg, GetSigners()
BeginBlocker, EndBlocker
CheckTx, DeliverTx
protobuf服务定义
// CosmWasm指标
use cosmwasm_std::*;
#[entry_point]
pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg)
项目结构
x/modulename/- 自定义模块keeper/keeper.go- 状态管理types/msgs.go- 消息定义abci.go- BeginBlocker/EndBlockerhandler.go- 消息处理器(传统)
工具支持
- CodeQL: 用于非确定性和崩溃的自定义规则
- go vet, golangci-lint: 基本的Go静态分析
- 手动审查: 对于共识问题至关重要
4. 本技能的工作方式
调用时,我将:
- 搜索您的代码库以查找Cosmos SDK模块
- 分析每个模块以检测9种漏洞模式
- 报告发现,包括文件引用和严重性
- 提供修复每个已识别的问题
- 检查消息处理器以发现验证问题
5. 示例输出
当发现漏洞时,您将收到类似以下的报告:
=== COSMOS SDK 漏洞扫描结果 ===
项目: my-cosmos-chain
扫描文件数: 6 (.go)
发现漏洞数: 2
---
[CRITICAL] 不正确的GetSigners()
---
## 5. 漏洞模式(9种模式)
我检查9种基于CosmWasm的关键漏洞模式。有关详细的检测模式、代码示例、缓解措施和测试策略,请参阅[VULNERABILITY_PATTERNS.md](resources/VULNERABILITY_PATTERNS.md)。
### 模式摘要:
1. **缺少代币验证** ⚠️ CRITICAL - 接受任意代币单位
2. **授权不足** ⚠️ CRITICAL - 缺少发送者/管理员验证
3. **缺少余额检查** ⚠️ HIGH - 未验证足够余额
4. **不当回复处理** ⚠️ HIGH - 不安全的子消息回复处理
5. **缺少回复ID检查** ⚠️ MEDIUM - 未验证回复ID
6. **不当IBC包验证** ⚠️ CRITICAL - 未验证的IBC包
7. **未验证执行消息** ⚠️ HIGH - 缺少消息验证
8. **整数溢出** ⚠️ HIGH - 未检查的算术操作
9. **通过子消息的可重入性** ⚠️ MEDIUM - 子消息前的状态变更
有关完整的漏洞模式及代码示例,请参阅[VULNERABILITY_PATTERNS.md](resources/VULNERABILITY_PATTERNS.md)。
## 5. 扫描工作流
### 步骤1:平台识别
1. 识别Cosmos SDK版本(`go.mod`)
2. 定位自定义模块(`x/*/`)
3. 查找ABCI方法(`abci.go`, BeginBlocker, EndBlocker)
4. 识别消息类型(`types/msgs.go`, `.proto`)
### 步骤2:关键路径分析
关注共识关键代码:
- BeginBlocker / EndBlocker实现
- 消息处理器(execute, DeliverTx)
- 修改状态的Keeper方法
- CheckTx优先级逻辑
### 步骤3:非确定性扫描
**这是Cosmos链的最高优先级检查。**
```bash
# 搜索非确定性模式
grep -r "range.*map\[" x/
grep -r "\bint\b\|\buint\b" x/ | grep -v "int32\|int64\|uint32\|uint64"
grep -r "float32\|float64" x/
grep -r "go func\|go routine" x/
grep -r "select {" x/
grep -r "time.Now()" x/
grep -r "rand\." x/
对于每个发现:
- 验证它位于共识关键路径
- 确认导致非确定性
- 评估严重性(链停止 vs 数据不一致)
步骤4:ABCI方法分析
审查BeginBlocker和EndBlocker:
- [ ] 计算复杂度是否有限制?
- [ ] 没有无限迭代?
- [ ] 没有嵌套在大集合上的循环?
- [ ] 易崩溃操作是否验证?
- [ ] 已使用最大状态进行基准测试?
步骤5:消息验证
对于每种消息类型:
- [ ] GetSigners()地址与处理器使用是否匹配?
- [ ] 所有错误返回是否检查?
- [ ] 在CheckTx中为关键消息设置优先级?
- [ ] 处理器是否已注册(或使用v0.47+自动注册)?
步骤6:算术与记账
- [ ] sdk.Dec操作使用乘前除法模式?
- [ ] 舍入有利于协议而非用户?
- [ ] 自定义记账是否与x/bank同步?
- [ ] 不变式检查是否到位?
6. 报告格式
发现模板
## [CRITICAL] EndBlocker中的非确定性映射迭代
**位置**: `x/dex/abci.go:45-52`
**描述**:
EndBlocker迭代一个无序映射以分发奖励,导致不同验证器以不同顺序处理用户并产生不同状态根。这将使链停止,当验证器无法达成共识时。
**漏洞代码**:
```go
// abci.go, 第45行
func EndBlocker(ctx sdk.Context, k keeper.Keeper) {
rewards := k.GetPendingRewards(ctx) // 返回map[string]sdk.Coins
for user, amount := range rewards { // 非确定性顺序
k.bankKeeper.SendCoins(ctx, moduleAcc, user, amount)
}
}
攻击场景:
- 多个用户有未决奖励
- 不同验证器由于映射随机化以不同顺序迭代
- 如果任何奖励分发在迭代中失败,状态分歧
- 验证器产生不同应用哈希
- 链停止 - 无法达成共识
建议: 在迭代前对映射键排序:
func EndBlocker(ctx sdk.Context, k keeper.Keeper) {
rewards := k.GetPendingRewards(ctx)
// 收集并排序键以进行确定性迭代
users := make([]string, 0, len(rewards))
for user := range rewards {
users = append(users, user)
}
sort.Strings(users) // 确定性顺序
// 按排序顺序处理
for _, user := range users {
k.bankKeeper.SendCoins(ctx, moduleAcc, user, rewards[user])
}
}
参考:
- building-secure-contracts/not-so-smart-contracts/cosmos/non_determinism
- Cosmos SDK文档:确定性
---
## 7. 优先级指南
### 关键 - 链停止风险
- 非确定性(任何形式)
- ABCI方法崩溃
- 缓慢ABCI方法
- 不正确GetSigners(允许未经授权操作)
### 高 - 资金损失风险
- 缺少错误处理(bankKeeper.SendCoins)
- 破损记账(会计不匹配)
- 缺少消息优先级(oracle/紧急消息)
### 中 - 逻辑/DoS风险
- 舍入错误(协议价值泄漏)
- 未注册消息处理器(功能破损)
---
## 8. 测试建议
### 非确定性测试
```bash
# 为不同架构构建
GOARCH=amd64 go build
GOARCH=arm64 go build
# 运行相同操作,比较状态根
# 必须在不同架构间一致
# 并发操作的模糊测试
go test -fuzz=FuzzEndBlocker -parallel=10
ABCI基准测试
func BenchmarkBeginBlocker(b *testing.B) {
ctx := setupMaximalState() // 最坏情况状态
b.ResetTimer()
for i := 0; i < b.N; i++ {
BeginBlocker(ctx, keeper)
}
// 必须在 < 1 秒内完成
require.Less(b, b.Elapsed()/time.Duration(b.N), time.Second)
}
不变式测试
// 在集成测试中运行不变式
func TestInvariants(t *testing.T) {
app := setupApp()
// 执行操作
app.DeliverTx(...)
// 检查不变式
_, broken := keeper.AllInvariants()(app.Ctx)
require.False(t, broken, "检测到不变式违规")
}
9. 额外资源
- Building Secure Contracts:
building-secure-contracts/not-so-smart-contracts/cosmos/ - Cosmos SDK文档: https://docs.cosmos.network/
- CodeQL for Go: https://codeql.github.com/docs/codeql-language-guides/codeql-for-go/
- Cosmos安全最佳实践: https://github.com/cosmos/cosmos-sdk/blob/main/docs/docs/learn/advanced/17-determinism.md
10. 快速参考清单
完成Cosmos链审计前:
非确定性(关键):
- [ ] 共识代码中没有映射迭代
- [ ] 没有平台依赖类型(int, uint, float)
- [ ] 消息处理器/ABCI中没有协程
- [ ] 没有多个通道的select语句
- [ ] 没有rand, time.Now(), 内存地址
- [ ] 所有序列化是确定性的
ABCI方法(关键):
- [ ] BeginBlocker/EndBlocker计算上有限
- [ ] 没有无限迭代
- [ ] 没有嵌套在大集合上的循环
- [ ] 所有易崩溃操作已验证
- [ ] 已用最大状态进行基准测试
消息处理(高):
- [ ] GetSigners()匹配处理器地址使用
- [ ] 所有错误返回已检查
- [ ] 关键消息在CheckTx中优先
- [ ] 所有消息类型已注册
算术与记账(中):
- [ ] 使用乘前除法模式
- [ ] 舍入有利于协议
- [ ] 自定义记账与x/bank同步
- [ ] 不变式检查已实施
测试:
- [ ] 跨架构构建测试
- [ ] ABCI方法基准测试
- [ ] 不变式在CI中检查
- [ ] 集成测试覆盖所有消息