coadx结合deepseet写的安全审计报告

Viewed 112

Mixin Network 安全审计报告
范围: mixin (核心链)、kraken (WebRTC SFU)、ocean.one (DEX)、safe (冷钱包)
方法: 白盒代码审计 + 架构分析 + 已知漏洞关联
评级定义: Critical / High / Medium / Low / Info

  1. 🔴 Critical — 严重漏洞
    C-01: TransactionMaximumSize 限制绕过可能引发内存 DoS
    位置: config/reader.go L36, p2p/transport.go L11

// config/reader.go
TransactionMaximumSize = 1024 * 1024 * 4 // 4MB

// p2p/transport.go
TransportMessageMaxSize = 32 * 1024 * 1024 // 32MB
问题: P2P 传输层接受最大 32MB 的 TransportMessage,但交易体仅限制在 4MB。虽然交易验证层会拒绝超大的交易,但攻击者可以先发送 32MB 的垃圾数据到 P2P 网络层,导致节点在解析/验证之前就分配大块内存。如果恶意节点批量发送此类消息,可能导致内存耗尽。

建议: 在 P2P 传输解包阶段就应用 TransactionMaximumSize 限制,避免数据进入上层处理前就被解析分配。

C-02: 非终态交易的缓存队列可能被 DoS 攻击
位置: kernel/queue.go L50-L60

// queue.go FIXME 注释
// FIXME not mark invalid tx as stale is to ensure final graph sync
// but we need some way to mitigate cache transaction DoS attack from nodes
问题: 代码中明确定义了 CachePoolSnapshotsLimit = 256,且 CachePool 使用有缓冲 channel。但 LoopCacheQueue 中当交易验证失败时,continue 不会标记为 stale 也不会清除,意味着无效交易会无限期留在缓存队列中。攻击者可大量发送无效交易,填满整个 CachePool(256 slots),阻碍有效交易的处理。

建议: 对无效交易设置重试次数上限,超过后自动清除,或者使用 LRU/时间窗口淘汰策略。

  1. 🟠 High — 高危漏洞
    H-01: RPC 无认证/鉴权机制
    位置: rpc/server.go

问题: RPC 服务(getinfo, gettransaction, sendrawtransaction, getutxo, getdeposittransaction)完全没有任何认证或鉴权。攻击者如果获得节点 RPC 端口访问权限,可以:

调用 sendrawtransaction 提交任意交易
通过 getutxo 遍历 UTXO 集合
获取完整的网络拓扑信息
建议: 添加 IP 白名单或可选的签名认证(类似 Bitcoin Core 的 rpcuser/rpcpassword 或 TLS 客户端证书)。

H-02: CallMixinRPC 无 TLS 且未验证服务端身份
位置: rpc/client.go

func CallMixinRPC(node, method string, params []any) ([]byte, error) {
client := &http.Client{Timeout: 20 * time.Second}
// ...
req, err := http.NewRequest("POST", node, bytes.NewReader(body))
// 使用 HTTP,没有 TLS 也没有证书校验
问题: Go SDK 客户端使用 http(明文 HTTP)连接 RPC 节点,容易遭受中间人攻击(MITM)。攻击者可以篡改返回的交易数据、伪造 UTXO 信息,导致 SDK 用户发送错误的交易。

建议:

默认使用 HTTPS,且验证服务端证书
或者添加 InsecureSkipVerify 配置项但给出警告
H-03: Validate() 中 LockInputs 的竞态条件可能导致双花
位置: kernel/self.go L43-L61

func (node *Node) lockAndPersistTransaction(tx *common.VersionedTransaction, finalized bool) error {
for i := time.Duration(0); i < time.Second; i += time.Millisecond * 100 {
err := tx.LockInputs(node.persistStore, finalized)
if errors.Is(err, badger.ErrConflict) {
time.Sleep(i)
continue
}
// ...
err = node.persistStore.WriteTransaction(tx)
// ...
}
panic(...)
}
问题: lockAndPersistTransaction 在遇到 badger.ErrConflict 时进行指数退避重试(最长 1 秒),超过后 panic。如果共识节点对此 panic 无自动恢复机制,一个精心构造的并发写入冲突就能使节点崩溃。此外,LockInputs 与 WriteTransaction 不是原子操作 — 中间状态存在极小时间窗口的竞争。

建议:

使用 Badger 的事务(txn.Commit)而非手动锁定
对 panic 增加优雅降级逻辑,而非直接崩溃
H-04: 聚合签名验证的 batch.go 中随机数质量不够强
位置: crypto/batch.go L135

buf := make([]byte, 32)
ReadRand(buf[:16])
_, err = Rcoeffs[i].SetCanonicalBytes(buf)
问题: 批量验证(BatchVerify)使用 16 字节(128 位)随机数作为每个签名的权重系数,且其余 16 字节为零。虽然 128 位足够安全,但文档中说"128-bit random Scalar",实际代码却是 buf[:16] 填充随机 + buf[16:] 全零,再转为 32 字节 Scalar。如果 ReadRand 失败或熵不足,批量验证的可靠性会下降。

建议: 使用完整的 32 字节随机数,或者使用伪随机(如基于 SHA512)权重系数确保确定性。

H-05: key.go 中 DeterministicHashDerive 种子复用
位置: crypto/key.go L52-L55

func (k Key) DeterministicHashDerive() Key {
seed := Sha256Hash(k[:])
return NewKeyFromSeed(append(seed[:], seed[:]...)) // 种子被重复拼接
}
问题: NewKeyFromSeed 内部使用 SetUniformBytes(接受 64 字节均匀分布的输入),但这里将 32 字节的 SHA256 输出拼接两次变成 64 字节。这意味着输入空间的熵没有增加(仍然是 32 字节的熵分布在 64 字节中)。虽然这不直接产生漏洞,但说明了密码学处理上不够严谨,可能在更复杂的派生链中引入弱点。

建议: 使用 HKDF 或基于 Blake3 的 64 字节扩展。

  1. 🟡 Medium — 中危漏洞
    M-01: 签名实现中的 Ed25519 小群组攻击防护分析
    位置: crypto/point.go

func isPrimeOrderPoint(p *edwards25519.Point) bool {
if p.Equal(edwards25519.NewIdentityPoint()) == 1 {
return false
}
cleared := edwards25519.NewIdentityPoint().MultByCofactor(p)
restored := edwards25519.NewIdentityPoint().ScalarMult(invEightScalar, cleared)
return restored.Equal(p) == 1
}
评价: 项目中确实实现了小群组攻击防护(decodePoint 调用 isPrimeOrderPoint),这是好的。但 isPrimeOrderPoint 的实现采用乘法逆元检查而非简单的 MultByCofactor + 判零。该自定义逻辑可能引入边缘情况。标准做法应为:

func isPrimeOrderPoint(p *edwards25519.Point) bool {
return p.MultByCofactor(p).Equal(edwards25519.NewIdentityPoint()) == 1
}
当前实现更保守,但自定义的检查方式未经广泛审计,有实现错误的可能性。

M-02: Blake3 哈希在多方计算场景中部分使用不安全的长度
位置: crypto/hash.go — 各个哈希函数

问题: 代码中混合使用 Blake3Hash(32 字节)和 Sha256Hash(32 字节)等不同的哈希函数。在共识协议中,不同安全属性的哈希函数混用可能带来冲突攻击面扩张。建议统一使用 Blake3(256位)作为共识相关哈希。

M-03: TransactionType() 逻辑依赖遍历顺序,可能被重放
位置: common/transaction.go L60-L92

func (tx *SignedTransaction) TransactionType() uint8 {
for _, in := range tx.Inputs {
if in.Mint != nil { return TransactionTypeMint }
if in.Deposit != nil { return TransactionTypeDeposit }
// ...
}
// 根据 Output 类型判断...
}
问题: TransactionType 的判定逻辑取决于 Inputs 和 Outputs 的遍历顺序。如果攻击者创建同时有 Mint 输入和 Deposit 输入的混合交易,根据遍历顺序只会被判定为 Mint 类型,可能绕过某些类型的特定验证逻辑。

建议: 增加校验,确保交易类型明确互斥,不允许混合类型的输入。

M-04: P2P 认证超时不可配置
位置: p2p/handle.go(authenticate 中的 3 秒超时)

select {
case err := <-auth:
// ...
case <-time.After(3 * time.Second):
return nil, fmt.Errorf("authenticate timeout")
}
问题: 认证超时硬编码为 3 秒。在高延迟网络环境(如跨洲节点)下可能导致合法节点被频繁踢出,攻击者可以通过延迟攻击(通过缓慢发送认证消息)来破坏节点连接。

建议: 将超时时间设为可配置,或根据网络情况动态调整。

M-05: kraken 项目零测试覆盖
位置: kraken/engine/ 全部文件

问题: kraken 是一个生产环境 WebRTC SFU(纯 Go 实现),但没有任何单元测试。WebRTC 涉及复杂的信令交互、ICE 连接、音频编解码,缺乏测试意味着回归风险极高。任何修改都可能引入崩溃或安全漏洞。

建议: 至少为 RPC handler、peer 管理、房间管理等核心逻辑添加单元测试。

  1. 🔵 Low — 低危/信息性
    L-01: 全局日志变量
    位置: logger/log.go

var (
level int
filter *regexp.Regexp
)
问题: 注释标注 // FIXME GLOBAL VARIABLES,但留存至今。全局日志变量在多实例/多节点场景下可能导致日志行为不一致。

L-02: RPC 返回数据类型不安全
位置: rpc/server.go

问题: CallMixinRPC 中大量使用 panic(string(raw)) 处理 JSON 解析错误,意味着任意 RPC 返回的畸形数据都会导致 SDK 节点崩溃。这是拒绝服务攻击的入口。

L-03: GenerateTLSConfig 自签名证书凭据有限
位置: p2p/quic.go

问题: P2P 使用的 TLS 是自签名证书(generateTLSConfig),无法抵御中间人攻击。虽然 P2P 协议本身有消息签名验证(PeerMessage.signature),但 TLS 层不验证证书链意味着流层本身不提供端到端的安全性。

L-04: RawTransaction 提交无速率限制
建议: sendrawtransaction RPC 应添加频率限制,防止攻击者用大量垃圾交易冲击网络。

L-05: 依赖的第三方库未做版本锁定安全审计
badger, quic-go, edwards25519, blake3 等依赖的版本需要持续跟踪 CVE。当前时间点(2026-05-27)的建议是确认所使用的版本无已知严重漏洞。

  1. 📊 总体风险评估
    级别 数量 关键发现
    Critical 2 DoS: 传输层大小限制绕过、缓存队列填充攻击
    High 5 无 RPC 认证、明文 RPC 通信、并发双花风险、聚合验证随机数弱、密钥推导不够严谨
    Medium 5 Ed25519 小群组检查、哈希混用、交易类型判定歧义、P2P 超时硬编码、kraken 零测试
    Low 5 全局变量、panic 作为错误处理、TLS 自签名、无速率限制、第三方依赖审计缺失
    整体评价
    这份代码在同类项目中安全性属于中上水平。 主要亮点:

✅ 密码学用法较为严谨 — Ed25519 家族使用 filippo.io/edwards25519(官方实现),支持 CoSi 聚合签名
✅ 输入验证充分 — 交易格式、签名、引用关系等有系统性验证
✅ 惩罚机制 — slash.go 定义了 4 种 slash 规则来惩罚作恶节点
✅ 无明显的双花漏洞 — UTXO 模型 + 确定性锁机制设计得当
最需要优先修复的 3 个问题:

RPC 无认证 (H-01) — RPC 暴露给攻击者可导致全面攻陷
P2P 消息大小绕过 (C-01) — 是最容易发起的 DoS 攻击
LockInputs 竞争 panic (H-03) — 攻击者可让共识节点反复崩溃

0 Answers