TON漏洞扫描器Skill ton-vulnerability-scanner

这个技能是TON漏洞扫描器,用于审计TON区块链上使用FunC编写的智能合约,检测整数作为布尔值误用、假冒Jetton合约和未检查gas的TON转发等关键漏洞,提高合约安全性。关键词:TON、智能合约、漏洞扫描、安全审计、FunC、Jetton、区块链安全。

智能合约 0 次安装 0 次浏览 更新于 3/14/2026

名称: TON漏洞扫描器 描述: 扫描TON(The Open Network)智能合约,检测3种关键漏洞,包括整数作为布尔值误用、假冒Jetton合约和未检查gas的TON转发。适用于FunC合约的审计。

TON漏洞扫描器

1. 目的

系统性地扫描TON区块链上使用FunC编写的智能合约,针对平台特定的安全漏洞进行检测,涉及布尔逻辑、Jetton代币处理和gas管理。此技能编码了3种TON架构独有的关键漏洞模式。

2. 何时使用此技能

  • 审计TON智能合约(FunC语言)
  • 审查Jetton代币实现
  • 验证代币转移通知处理器
  • TON dApp上线前的安全评估
  • 审查gas转发逻辑
  • 评估布尔条件处理

3. 平台检测

文件扩展名和指示器

  • FunC文件: .fc, .func

语言/框架标记

;; FunC合约指示器
#include "imports/stdlib.fc";

() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
    ;; 合约逻辑
}

() recv_external(slice in_msg) impure {
    ;; 外部消息处理器
}

;; 常见模式
send_raw_message()
load_uint(), load_msg_addr(), load_coins()
begin_cell(), end_cell(), store_*()
transfer_notification operation
op::transfer, op::transfer_notification
.store_uint().store_slice().store_coins()

项目结构

  • contracts/*.fc - FunC合约源文件
  • wrappers/*.ts - TypeScript包装器
  • tests/*.spec.ts - 合约测试
  • ton.config.tswasm.config.ts - TON项目配置

工具支持

  • TON Blueprint: TON开发框架
  • toncli: TON合约的CLI工具
  • ton-compiler: FunC编译器
  • 主要手动审查(自动化工具有限)

4. 此技能如何工作

调用时,我将:

  1. 搜索您的代码库中的FunC/Tact合约
  2. 分析每个合约以查找3种漏洞模式
  3. 报告发现,包括文件引用和严重性
  4. 提供修复针对每个识别出的问题
  5. 检查重放防护和发送者验证

5. 示例输出

当发现漏洞时,您将获得类似以下的报告:

=== TON漏洞扫描结果 ===

项目: my-ton-contract
已扫描文件: 3 (.fc, .tact)
发现漏洞: 2

---

[CRITICAL] 缺少重放防护
文件: contracts/wallet.fc:45
模式: 无序列号或随机数验证


---

## 5. 漏洞模式(3种模式)

我检查3种TON独有的关键漏洞模式。有关详细检测模式、代码示例、缓解措施和测试策略,请参见[VULNERABILITY_PATTERNS.md](resources/VULNERABILITY_PATTERNS.md)。

### 模式摘要:

1. **缺少发送者检查** ⚠️ CRITICAL - 特权操作上无发送者验证
2. **整数溢出** ⚠️ CRITICAL - FunC中未检查的算术
3. **不正确的gas处理** ⚠️ HIGH - 不足的gas预留

有关完整漏洞模式及代码示例,请参见[VULNERABILITY_PATTERNS.md](resources/VULNERABILITY_PATTERNS.md)。
## 5. 扫描工作流程

### 步骤1: 平台识别
1. 验证FunC语言(`.fc` 或 `.func` 文件)
2. 检查TON Blueprint或toncli项目结构
3. 定位合约源文件
4. 识别与Jetton相关的合约

### 步骤2: 布尔逻辑审查
```bash
# 查找布尔类变量
rg "int.*is_|int.*has_|int.*flag|int.*enabled" contracts/

# 检查用作布尔值的正整数
rg "= 1;|return 1;" contracts/ | grep -E "is_|has_|flag|enabled|valid"

# 查找布尔类值的NOT操作
rg "~.*\(|~ " contracts/

对于每个布尔值:

  • [ ] 使用-1表示真,0表示假
  • [ ] NOT不使用1或其他正整数
  • [ ] 逻辑操作正确工作

步骤3: Jetton处理器分析

# 查找transfer_notification处理器
rg "transfer_notification|op::transfer_notification" contracts/

对于每个Jetton处理器:

  • [ ] 验证发送者地址
  • [ ] 发送者与存储的Jetton钱包地址对比检查
  • [ ] 无发送者验证时,不信任forward_payload
  • [ ] 具有设置Jetton钱包地址的管理功能

步骤4: Gas/转发金额审查

# 查找转发金额使用
rg "forward_ton_amount|forward_amount" contracts/
rg "load_coins\(\)" contracts/

# 查找send_raw_message调用
rg "send_raw_message" contracts/

对于每个传出消息:

  • [ ] 转发金额是固定的/有界的
  • [ ] 或用户提供的金额根据msg_value验证:msg_value >= tx_fee + forward_amount
  • [ ] 合约余额免受耗尽
  • [ ] 使用适当的send_raw_message标志

步骤5: 手动审查

TON合约需要彻底的手动审查:

  • 使用~, &, |操作符的布尔逻辑
  • 消息解析和验证
  • gas经济和费用计算
  • 存储操作和数据序列化

6. 报告格式

发现模板

## [CRITICAL] 假冒Jetton合约 - 缺少发送者验证

**位置**: `contracts/staking.fc:85-95` (recv_internal, transfer_notification处理器)

**描述**:
`transfer_notification`操作处理器不验证发送者是预期的Jetton钱包合约。任何攻击者都可以发送假冒的`transfer_notification`消息,声称已转移代币,从而为自己充值而无需实际存入任何Jettons。

**漏洞代码**:
```func
// staking.fc, 第85行
if (op == op::transfer_notification) {
    int jetton_amount = in_msg_body~load_coins();
    slice from_user = in_msg_body~load_msg_addr();

    ;; 错误: 无sender_address验证!
    ;; 攻击者可以声称任何jetton_amount

    credit_user(from_user, jetton_amount);
}

攻击场景:

  1. 攻击者部署恶意合约
  2. 恶意合约向质押合约发送transfer_notification消息
  3. 消息声称攻击者转移了1,000,000 Jettons
  4. 质押合约未检查发送者而攻击者
  5. 攻击者现在可以从合约中提取或获得利益而无需存入

概念证明:

// 攻击者发送假冒transfer_notification
const attackerContract = await blockchain.treasury("attacker");

await stakingContract.sendInternalMessage(attackerContract.getSender(), {
  op: OP_CODES.TRANSFER_NOTIFICATION,
  jettonAmount: toNano("1000000"), // 假冒金额
  fromUser: attackerContract.address,
});

// 攻击者成功充值而无需发送真实Jettons
const balance = await stakingContract.getUserBalance(attackerContract.address);
expect(balance).toEqual(toNano("1000000")); // 攻击成功

建议: 存储预期的Jetton钱包地址并验证发送者:

global slice jetton_wallet_address;

() recv_internal(...) impure {
    load_data();  ;; 从存储加载jetton_wallet_address

    slice cs = in_msg_full.begin_parse();
    int flags = cs~load_uint(4);
    slice sender_address = cs~load_msg_addr();

    int op = in_msg_body~load_uint(32);

    if (op == op::transfer_notification) {
        ;; 关键: 验证发送者
        throw_unless(error::wrong_jetton_wallet,
            equal_slices(sender_address, jetton_wallet_address));

        int jetton_amount = in_msg_body~load_coins();
        slice from_user = in_msg_body~load_msg_addr();

        ;; 安全地攻击用户
        credit_user(from_user, jetton_amount);
    }
}

参考:

  • building-secure-contracts/not-so-smart-contracts/ton/fake_jetton_contract

---

## 7. 优先级指南

### 关键(需要立即修复)
- 假冒Jetton合约(未经授权的铸造/充值)

### 高(发布前修复)
- 整数作为布尔值(逻辑错误,条件损坏)
- 未检查gas的TON转发(余额耗尽)

---

## 8. 测试建议

### 单元测试
```typescript
import { Blockchain } from "@ton/sandbox";
import { toNano } from "ton-core";

describe("安全测试", () => {
  let blockchain: Blockchain;
  let contract: Contract;

  beforeEach(async () => {
    blockchain = await Blockchain.create();
    contract = blockchain.openContract(await Contract.fromInit());
  });

  it("应使用正确的布尔值", async () => {
    // 测试TRUE = -1, FALSE = 0
    const result = await contract.getFlag();
    expect(result).toEqual(-1n); // 真
    expect(result).not.toEqual(1n); // 不是1!
  });

  it("应拒绝假冒Jetton转移", async () => {
    const attacker = await blockchain.treasury("attacker");

    const result = await contract.send(
      attacker.getSender(),
      { value: toNano("0.05") },
      {
        $$type: "TransferNotification",
        query_id: 0n,
        amount: toNano("1000"),
        from: attacker.address,
      }
    );

    expect(result.transactions).toHaveTransaction({
      success: false, // 应拒绝
    });
  });

  it("应验证gas以转发金额", async () => {
    const result = await contract.send(
      user.getSender(),
      { value: toNano("0.01") }, // 不足的gas
      {
        $$type: "Transfer",
        to: recipient.address,
        forward_ton_amount: toNano("1"), // 尝试转发1 TON
      }
    );

    expect(result.transactions).toHaveTransaction({
      success: false,
    });
  });
});

集成测试

// 使用真实Jetton钱包测试
it("应接受来自真实Jetton钱包的转移", async () => {
  // 部署实际的Jetton minter和钱包
  const jettonMinter = await blockchain.openContract(JettonMinter.create());
  const userJettonWallet = await jettonMinter.getWalletAddress(user.address);

  // 在合约中设置jetton钱包
  await contract.setJettonWallet(userJettonWallet);

  // 从Jetton钱包进行真实转移
  const result = await userJettonWallet.sendTransfer(
    user.getSender(),
    contract.address,
    toNano("100"),
    {}
  );

  expect(result.transactions).toHaveTransaction({
    to: contract.address,
    success: true,
  });
});

9. 额外资源


10. 快速参考清单

完成TON合约审计前:

布尔逻辑(高):

  • [ ] 所有布尔值使用-1(真)和0(假)
  • [ ] 不使用正整数(1, 2等)作为布尔值
  • [ ] 返回布尔值的函数返回-1表示真
  • [ ] 使用~, &, |的布尔逻辑使用正确的值
  • [ ] 测试验证布尔操作正确工作

Jetton安全(关键):

  • [ ] transfer_notification处理器验证发送者地址
  • [ ] 发送者与存储的Jetton钱包地址对比检查
  • [ ] Jetton钱包地址在初始化时存储
  • [ ] 具有设置/更新Jetton钱包地址的管理功能
  • [ ] 无发送者验证时,不信任forward_payload
  • [ ] 使用假冒Jetton合约测试验证拒绝

Gas和转发金额(高):

  • [ ] 转发TON金额是固定的/有界的
  • [ ] 或用户提供的金额验证:msg_value >= tx_fee + forward_amount
  • [ ] 合约余额免受耗尽
  • [ ] 使用适当的send_raw_message标志
  • [ ] 测试验证无法通过过量转发金额耗尽合约

测试:

  • [ ] 针对所有三种漏洞类型的单元测试
  • [ ] 与真实Jetton合约的集成测试
  • [ ] 所有操作的gas成本分析
  • [ ] 主网前的测试网部署