本文分析了Damn Vulnerable DeFi V4第5题The Rewarder中的漏洞。该漏洞存在于claimRewards()函数中,由于合约在处理完所有claims后才标记为已领取,攻击者可以通过提交多个相同Merkle proof的claim,多次领取奖励,从而耗尽合约中的token。文章还提供了防止此漏洞的机制。
这个解释假设你事先了解此挑战中的智能合约,并将专门关注漏洞分析。
一个合约正在分发 Damn Valuable 代币和 WETH 的奖励。
要申领奖励,用户必须证明他们包含在选定的受益人集合中。但不用担心 gas。该合约已经过优化,允许在同一交易中申领多个代币。
Alice 已经申领了她的奖励。你也可以申领你的!但你已经意识到合约中存在一个关键漏洞。
从分发者处尽可能多地保存资金。将所有已追回的资产转移到指定的追回账户。
获得资金的唯一方法是 claimRewards() 函数,所以让我们关注它。该函数允许我们通过一个请求来申领 DVT 和 WETH 奖励。
我们可以注意到的第一个漏洞是,该函数在两种情况下将我们的奖励标记为已申领:
在最后一次迭代期间
当要申领的代币发生变化时
此外,我们可以单笔交易中处理的申领数量没有限制。这创建了一个漏洞利用路径,我们可以在同一代币和批次上提交多个相同的申领(使用相同的有效 Merkle 证明,因为 ‘player’ 是合法的受益人)。由于合约仅在代币切换时或处理结束时才将申领标记为已申领,我们可以多次申领我们的奖励并耗尽合约。
读取分发 JSON 文件,以找到我们对 DVT 和 WETH 代币的合法申领金额
为同一代币和同一批次(批次 0)创建多个申领的数组
对于每个代币:
使用有效的 Merkle 证明进行第一次申领(因为我们的地址在受益人名单上)
使用相同的 Merkle 证明进行多次后续申领
合约将验证每个申领的证明,但仅在处理完所有申领后才将批次标记为已申领
执行交易以耗尽分配器中的几乎所有代币
将所有已追回的资产转移到指定的追回帐户
可以通过立即将申领标记为已申领而不是批量处理来防止此漏洞。合约应在继续下一个申领之前,以原子方式验证并完成每个申领。
function claimRewards(Claim[] memory inputClaims, IERC20[] memory inputTokens) external {
Claim memory inputClaim;
IERC20 token;
uint256 bitsSet; // accumulator
uint256 amount;
for (uint256 i = 0; i < inputClaims.length; i++) {
inputClaim = inputClaims[i];
uint256 wordPosition = inputClaim.batchNumber / 256;
uint256 bitPosition = inputClaim.batchNumber % 256;
if (token != inputTokens[inputClaim.tokenIndex]) {
token = inputTokens[inputClaim.tokenIndex];
bitsSet = 1 << bitPosition; // 设置给定位置的位
amount = inputClaim.amount;
} else {
bitsSet = bitsSet | 1 << bitPosition;
amount += inputClaim.amount;
}
bytes32 leaf = keccak256(abi.encodePacked(msg.sender, inputClaim.amount));
bytes32 root = distributions[token].roots[inputClaim.batchNumber];
if (!_setClaimed(token, inputClaim.amount, wordPosition, 1 << bitPosition)) revert AlreadyClaimed();
if (!MerkleProof.verify(inputClaim.proof, root, leaf)) revert InvalidProof();
inputTokens[inputClaim.tokenIndex].transfer(msg.sender, inputClaim.amount);
}
}
包含解决方案的 GitHub 存储库:https://github.com/HamMnatsakanyan/damn-vulnerable-defi-solutions/
- 原文链接: coinsbench.com/damn-vuln...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!