首页 网络安全 正文
  • 本文约3078字,阅读需15分钟
  • 14
  • 0

Trust Wallet Core 安全漏洞CVE-2025-66692

摘要

栋科技漏洞库关注到Trust Wallet Core受影响版本中存在缓冲区溢出漏洞,该漏洞现已被追踪为CVE-2025-66692,CVSS 3.X评分7.5。

Trust Wallet Core是Trust Wallet公司的开源的、跨平台、以移动为中心的库,支撑钱包应用与 Web3 项目快速实现多链资产安全管理。

一、基本情况

Trust Wallet Core是Trust Wallet生态的核心底层库,提供私钥管理、地址生成、交易签名等低级别密码学功能,支持130 +主流区块链。

Trust Wallet Core专注于钱包底层核心能力,不包含 UI与上层业务逻辑,其主打跨平台、多链兼容的加密钱包基础能力,适配多链协议。

Trust Wallet Core 安全漏洞CVE-2025-66692

栋科技漏洞库关注到Trust Wallet Core受影响版本中存在缓冲区溢出漏洞,该漏洞现已被追踪为CVE-2025-66692,CVSS 3.X评分7.5。

二、漏洞分析

CVE-2025-66692漏洞是Trust Wallet Core 5668c67之前版本中的安全漏洞,该漏洞源于PublicKey::verify方法存在缓冲区过度读取。

该漏洞源于Trust Wallet Core的PublicKey::verify()方法中存在缓冲区溢出,攻击者可能会通过特制输入造成拒绝服务(DoS)。

由于PublicKey::verify()方法接受一个Data&类型的signature参数(std::vector<uint8_t>),在将其传递给加密函数之前未验证其大小:

1、文件:PublicKey.cpp

bool PublicKey::verify(const Data& signature, const Data& message) const {
    switch (type) {
    case TWPublicKeyTypeSECP256k1:
    case TWPublicKeyTypeSECP256k1Extended:
        return ecdsa_verify_digest(&secp256k1, bytes.data(), 
                                   signature.data(),  // NO SIZE VALIDATION
                                   message.data()) == 0;

预期行为与实际行为

预期:所有加密验证函数都预期恰好需要64个字节:

ECDSA(SECP256k1/NIST256p1):64字节(32字节R + 32字节S)

ED25519/Curve25519:64字节签名

实际:ecdsa_verify_digest 在读取签名字节时未进行边界检查:

2、文件:TrezorCrypto/ecdsa

int ecdsa_verify_digest(..., const uint8_t *sig, ...) {
    bn_read_be(sig, &r);        // Reads bytes 0-31
    bn_read_be(sig + 32, &s);   // Reads bytes 32-63
    // If sig has < 64 bytes -> BUFFER OVER-READ
}

如果signature.size()小于64,则在调用任何加密函数之前,就会导致立即发生越界访问。

三、POC概念验证

1、将此测试添加到tests/PublicKeyTests.cpp文件中:

管理员已设置登录后刷新可查看

3、步骤:

将上述测试添加到 PublicKeyTests.cpp

构建:cmake --build build

运行:./build/tests/tests --gtest_filter="*VerifyShortSignatureCrash"

观察:分段错误

3、漏洞证据

证据1:PublicKey.cpp中缺少验证

// src/PublicKey.cpp - NO size check before crypto operations
bool PublicKey::verify(const Data& signature, const Data& message) const {
    switch (type) {
    case TWPublicKeyTypeSECP256k1:
    case TWPublicKeyTypeSECP256k1Extended:
        // signature.data() passed directly without size check
        return ecdsa_verify_digest(&secp256k1, bytes.data(), 
                                   signature.data(), message.data()) == 0;

证据2:ecdsa_verify_digest需要64个字节

// TrezorCrypto/ecdsa.c
int ecdsa_verify_digest(const ecdsa_curve *curve, const uint8_t *pub_key,
                        const uint8_t *sig, const uint8_t *digest) {
    // ...
    bn_read_be(sig, &r);        // Reads bytes 0-31 (32 bytes)
    bn_read_be(sig + 32, &s);   // Reads bytes 32-63 (32 bytes)
    // Total: 64 bytes expected, NO length parameter

证据3:生产代码使用了此漏洞

// src/FIO/Signer.cpp
bool Signer::verify(const PublicKey& pubKey, const Data& data, const Data& signature) {
    return pubKey.verify(TW::data(signature.data() + 1, signature.size() - 1), data);
    // signature parameter comes from external input (network transactions)
    // NO validation before creating Data and passing to verify()
}

证据4:其他代码验证通过,此代码未通过(不一致性)

// src/EOS/Transaction.cpp
Signature::Signature(const Data& sig, Type type) : data(sig), type(type) {
    if (sig.size() != DataSize) {  // SIZE VALIDATION PRESENT
        throw std::invalid_argument("Invalid signature size!");
    }
}

// But PublicKey::verify() has NO such check
// Inconsistency indicates oversight/bug
Evidence 5: CURVE25519 Direct Array Access
// src/PublicKey.cpp
case TWPublicKeyTypeCURVE25519: {
    // ...
    ed25519PublicKey[31] |= signature[63] & 0x80;  // Access signature[63]
    // ...
    verifyBuffer[63] &= 127;  // Access again
    // If signature.size() < 64 -> Immediate out-of-bounds access
}

证据6:测试缺口表明遗漏了漏洞

// tests/PublicKeyTests.cpp - All tests use VALID signatures
TEST(PublicKeyTests, Verify) {
    // ...
    const auto signature = privateKey.sign(digest);  // Valid 65-byte signature
    EXPECT_TRUE(publicKey.verify(signature, digest));  // Never tests size < 64
}

// NO test case for signature.size() < 64
// Vulnerability went undetected due to insufficient test coverage

4、利用路径

(1)恶意/易受攻击的区块链创建带有短签名的交易

(2)交易通过区块链网络进行传播

(3)Trust Wallet同步和调用:

管理员已设置登录后刷新可查看

(4)使用短签名(例如,10个字节)调用 PublicKey::verify()

(5)无大小验证 → 直接进入加密函数

(6)加密函数尝试从10字节的缓冲区中读取64个字节

(7)缓冲区溢出 → 分段错误 → 钱包崩溃

5、补救

在 PublicKey::verify() 方法的开头添加签名大小验证:

bool PublicKey::verify(const Data& signature, const Data& message) const {
    // FIX: Validate signature size before any processing
    const size_t expectedSigSize = 64;  // All signature types use 64 bytes
    if (signature.size() != expectedSigSize) {
        return false;  // Invalid signature size
    }

    switch (type) {
    case TWPublicKeyTypeSECP256k1:
    case TWPublicKeyTypeSECP256k1Extended:
        return ecdsa_verify_digest(&secp256k1, bytes.data(), 
                                   signature.data(), 
                                   message.data()) == 0;
    // ... rest of code unchanged

四、影响范围

Trust Wallet Core <= 5668c67

五、参考链接

Trust Wallet Core >= 5668c67

六、参考链接

管理员已设置登录后刷新可查看



扫描二维码,在手机上阅读
评论
更换验证码
友情链接