uni-due-syssec/eth-reentrancy-attack-patterns

GitHub: uni-due-syssec/eth-reentrancy-attack-patterns

收录论文中多种以太坊智能合约重入攻击模式的可复现示例,用于安全研究及安全工具检测能力评估。

Stars: 115 | Forks: 22

# 重入攻击模式 (Re-Entrancy Attack Patterns) 这些攻击模式是在评估 `Sereum` 时发现的,这是一种针对重入攻击的运行时监控解决方案,它利用污点追踪 (taint tracking) 和动态写锁来检测并防止重入攻击。更多信息请参阅我们的论文 *"Sereum: Protecting Existing Smart Contracts Against Re-Entrancy Attacks"* ([arxiv 预印本](https://arxiv.org/abs/1812.05934))。 对于每种类型的攻击模式,本仓库包含一个易受攻击合约和攻击的小型示例实现。易受攻击的合约和攻击者合约的源代码包含在 `*.sol` 文件中。我们还为每个示例提供了一个 `*_setup.js` 文件,用于在开发区块链上部署合约并利用示例合约中的漏洞。这些脚本假定它们运行在 geth 开发模式区块链 (`geth --dev`) 中。 ### 跨函数重入 (Cross-function re-entrancy) **示例:** `./cross-function.sol` 示例中的 Token 合约容易受到始于 `withdrawAll` 函数的重入攻击。然而,攻击者无法重入 `withdrawAll`。相反,攻击者必须重入合约的 `exchangeAndWithdrawToken` 函数来利用该漏洞并耗尽易受攻击合约中的 ether。 ### 委托重入 (Delegated re-entrancy) **示例:** `./delegated.sol` `Bank` 合约使用了一个通过 `delegatecall` 调用的库来执行 ether 发送。这掩盖了 `withdraw` 函数中的重入漏洞。任何静态分析工具在仅分析 `Bank` 合约而不分析该合约与其库的组合时,都无法检测到此漏洞。 ### 基于 Create 的重入 (Create-based re-entrancy) **示例:** `./create-based.sol` 在此示例中,多个合约相互交互。`Bank` 合约利用 `CREATE` 指令(即 Solidity 中的 `new`)来创建新的子合约。合约创建会立即触发新创建合约的构造函数的执行。此构造函数可以向未知地址执行外部调用。这可能导致重入场景,即攻击者在子合约构造函数执行期间重入合约。为了使静态分析工具能够发现此类问题,它们必须 (1) 同时分析合约组合,并且 (2) 将 `CREATE` 指令视为外部调用,类似于 `CALL` 指令。 ## 已测试工具 下表列出了我们测试的工具和版本。如果工具检测到测试用例,我们用 "Yes" 标记,否则为 "No"。Mythril、Securify 和 Slither 使用保守策略,即标记外部调用之后的每一个状态更新。这将防止所有重入漏洞,但也会导致相当多的误报。例如,对于基于 Create 的重入漏洞,合约创建者极有可能想要修改状态(例如,注册新创建合约的地址)。另一个例子是使用互斥锁 (mutex) 进行手动锁定,这种策略总是会报告此类情况。 | Tool | Version | Simple | Cross-Function | Delegated | Create-based | | ------------- | ----------- | ---------------------- | ---------------------- | --------- | ------------ | | Oyente | 0.2.7 | Yes | No | No1 | No | | Mythril | v0.19.9 | Partial (conservative) | Partial (conservative) | No | Partial (conservative) | | Securify | 2018-08-01 | Partial (conservative) | Partial (conservative) | No | No | | Manticore2 | 0.2.2 | Yes | Yes3 | No | No | | Slither5 | 0.6.4 | Yes (conservative) | Yes (conservative) | Yes (conservative) | No | | ECFChecker | geth1.8port | Yes | Yes4 | Yes | No | | Sereum | | Yes | Yes | Yes | Yes | * 1 Oyente 在库合约中检测到重入。然而,库合约本身可以说不容易受到重入攻击。 * 2 我们评估了启用 `--detect-reentrancy-advanced` 的检测器。另一个检测器 `--detect-reentrancy` 使用类似于 Mythril 和 Securify 的策略。 * 3 然而,其他测试(例如 `manual-lock.sol`)显示 Manticore 有时不够准确,即使实际上不可能发起重入攻击也会报告。 * 4 然而,我们为跨函数重入攻击设计了一个未被 ECFChecker 检测到的不同示例。详情请参阅下一节。 * 5 与其他工具相比,Slither 在 Solidity 源代码级别工作。它具有类似于 Mythril 和 Securify 的策略,即它报告使用低级 Solidity `call` 或 `delegatecall` 函数进行外部调用后的任何状态更新。 ## 测试用例:手动锁 文件 `manual-lock.sol` 包含同一合约的多个版本。这些合约可用于评估重入检测工具的质量。 该文件包含三个功能等效的合约: * `VulnBankNoLock` 容易受到简单的同函数重入攻击。 * `VulnBankBuggyLock` 由于不完整的锁定机制,容易受到跨函数重入攻击。 * `VulnBankSecureLock` 由于锁定机制而不易受到攻击。然而,该锁定机制可能导致误报。 此外,针对所有这些合约实现了两种类型的攻击。 * `MallorySameFunction` 实现了简单的同函数重入 * `MalloryCrossFunction` 实现了跨函数重入攻击 静态分析工具很难正确分析这些合约。Oyente 仅检测简单的重入漏洞,而不报告跨函数重入。另一方面,Manticore 在 BuggyLock 和 SecureLock 版本中都检测到重入错误,从而导致误报。Slither 和 Mythril 将外部调用后的任何状态更新标记为问题,因此报告每个合约都有问题,即使 `SecureLock` 变体是不可利用的。 | Tool \ Testcase | NoLock | BuggyLock | SecureLock | | --------------- | -------- | --------- | ---------- | | Oyente | Yes | No | No | | Manticore | Yes | Yes | Yes | | Mythril | Yes | Yes | Yes | | Slither | Yes | Yes | Yes | | Expected | Yes | Yes | No | 对于动态分析工具,我们使用了易受攻击合约和攻击合约的多种组合。我们验证工具是否检测到针对同函数和跨函数重入攻击的攻击行为。 | Testcase \ Tool | ECFChecker | Sereum | Expected | | ---------------------------| ---------- | --------- | -------- | | NoLock + SameFunction | Yes | Yes | Yes | | NoLock + CrossFunction | No | Yes | Yes | | BuggyLock + SameFunction | No | Yes | No | | BuggyLock + CrossFunction | No | Yes | Yes | | SecureLock + SameFunction | No | Yes | No | | SecureLock + CrossFunction | No | Yes | No | Sereum 报告所有合约的原因是,锁定机制本身表现出的模式与重入攻击完全相同。因此 Sereum 报告了对锁变量的重入攻击,因为 Sereum 无法知道锁变量的语义。 ## 无条件重入 (Unconditional Re-Entrancy) **示例:** `./unconditional.sol` 通常,重入攻击会试图破坏应用程序的业务逻辑检查。每个检查(`if`、`require`、`assert` 等)在 EVM 级别都实现为条件跳转 (`JUMPI`)。虽然当然不太可能,但可以编写一个在发送 ether 之前不执行任何检查的合约。在此示例中,该功能转移用户投资的所有 ether。此示例仅可通过重入漏洞被利用。~~目前 Sereum 未检测到此示例,因为我们认为这是一种不太可能的情况。我们计划在未来的 sereum 版本中检测此类漏洞。~~ | Tool | Detected | | --------------- | --- | | Oyente | Yes | | Manticore | Yes | | Slither | Yes | | Mythril | Yes | | ECFChecker | Yes | | Sereum | ~~No~~ Yes1 | * 1 我们扩展了 Sereum 以覆盖此类重入,通过追踪从存储变量到调用参数的数据流。 另一个非常简单的示例是以下合约,它部署在 Ethereum 区块链的 [0xb7c5c5aa4d42967efe906e1b66cb8df9cebf04f7](https://etherscan.io/address/0xb7c5c5aa4d42967efe906e1b66cb8df9cebf04f7#code) 处。 ## 在学术工作中引用 如果你想在学术工作中引用这些攻击模式,请引用以下论文: ``` @inproceedings{sereum-ndss19, title = "Sereum: Protecting Existing Smart Contracts Against Re-Entrancy Attacks", booktitle = "Proceedings of the Network and Distributed System Security Symposium ({NDSS'19})", author = "Rodler, Michael and Li, Wenting and Karame, Ghassan and Davi, Lucas", year = 2019 } ```
标签:CISA项目, DEFI安全, Geth, Sereum, Solidity, Write Locks, 以太坊, 动态污点分析, 区块链安全, 基于创建的重入, 委托调用重入, 数据可视化, 智能合约审计, 智能合约漏洞, 自定义脚本, 自定义脚本, 跨函数重入, 重入攻击