名称: 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.ts或wasm.config.ts- TON项目配置
工具支持
- TON Blueprint: TON开发框架
- toncli: TON合约的CLI工具
- ton-compiler: FunC编译器
- 主要手动审查(自动化工具有限)
4. 此技能如何工作
调用时,我将:
- 搜索您的代码库中的FunC/Tact合约
- 分析每个合约以查找3种漏洞模式
- 报告发现,包括文件引用和严重性
- 提供修复针对每个识别出的问题
- 检查重放防护和发送者验证
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);
}
攻击场景:
- 攻击者部署恶意合约
- 恶意合约向质押合约发送
transfer_notification消息 - 消息声称攻击者转移了1,000,000 Jettons
- 质押合约未检查发送者而攻击者
- 攻击者现在可以从合约中提取或获得利益而无需存入
概念证明:
// 攻击者发送假冒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. 额外资源
- Building Secure Contracts:
building-secure-contracts/not-so-smart-contracts/ton/ - TON文档: https://docs.ton.org/
- FunC文档: https://docs.ton.org/develop/func/overview
- TON Blueprint: https://github.com/ton-org/blueprint
- Jetton标准: https://github.com/ton-blockchain/TEPs/blob/master/text/0074-jettons-standard.md
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成本分析
- [ ] 主网前的测试网部署