iis服务器助手广告广告
返回顶部
首页 > 资讯 > 操作系统 >Solidity 合约安全,常见漏洞 (下篇)
  • 756
分享到

Solidity 合约安全,常见漏洞 (下篇)

安全区块链智能合约安全威胁分析web安全 2023-08-30 16:08:45 756人浏览 泡泡鱼
摘要

Solidity 合约安全,常见漏洞 (下篇) Solidity 合约安全,常见漏洞 (上篇) 不安全的随机数 目前不可能用区块链上的单一交易安全地产生随机数。区块链需要是完全确定的,否则分布式节点将无法达成关于状态的共识。因为它们是完全

Solidity 合约安全,常见漏洞 (下篇)

Solidity 合约安全,常见漏洞 (上篇)

不安全的随机数

目前不可能用区块链上的单一交易安全地产生随机数。区块链需要是完全确定的,否则分布式节点将无法达成关于状态的共识。因为它们是完全确定的,所以任何 "随机"的数字都可以被预测到。下面的掷骰子函数可以被利用。

contract UnsafeDice {    function randomness() internal returns (uint256) {        return keccak256(abi.encode(msg.sender, tx.origin, block.timestamp, tx.gasprice, blockhash(block.number - 1);    }    // our dice can land on one of {0,1,2,3,4,5}function rollDice() public payable {        require(msg.value == 1 ether);        if (randomness() % 6) == 5) {            msg.sender.call{value: 2 ether}("");        }    }}contract ExploitDice {    function randomness() internal returns (uint256) {        return keccak256(abi.encode(msg.sender, tx.origin, block.timestamp, tx.gasprice, blockhash(block.number - 1);    }    function betSafely(IUnsafeDice game) public payable {        if (randomness % 6) == 5)) {            game.betSafely{value: 1 ether}()        }        // else don't do anything    }}

如何来产生随机数并不重要,因为攻击者可以完全复制它。使用更多的 "熵"的来源,如 msg.sender、时间戳等,不会有任何影响,因为智能合约也可以预测它。

错误使用 Chainlink 随机数 oracle

Chainlink 是一个流行的解决方案,以获得安全的随机数。它分两步进行。首先,智能合约向预言机处发送一个随机数请求,然后在一些区块之后,预言机以一个随机数作为回应。
由于攻击者无法预测未来,所以他们无法预测随机数。
除非智能合约错误地使用预言机:

  • 请求随机数的智能合约必须在随机数返回之前不做任何事情。否则,攻击者可以监视返回随机数的预言机的 mempool,并在前面运行预言机,知道随机数会是什么。
  • 随机数预言机本身可能会试图操纵你的应用程序。如果没有其他节点的共识,他们不能挑选随机数,但如果你的应用程序同时请求几个随机数,他们可以扣留和重新排序
  • 最终性在以太坊或大多数其他 EVM 链上不是即时的。仅仅因为某些区块是最新的,并不意味着它不一定会保持这种状态。这被称为 “链上重组”。事实上,链可以改变的不仅仅是最后一个区块。这就是所谓的 “深度重组”。Etherscan 报告了各种链的 re-orgs,例如以太坊重组和 PolyGon 重组。在 Polygon 上,重组的深度可以达到 30 个或更多的区块,所以等待更少的区块会使应用变得脆弱(当 zk-evm 成为 Polygon 上的标准共识时,这种情况可能会改变,因为最终性将与以太坊的一致,但这是未来的预测,而不是目前的事实)。
  • 下面是其他 Chainlink 随机数的安全考虑。

从价格 Oracle 中获取陈旧的数据

Chainlink 没有 SLA(服务水平协议)来保持它的价格预言机在一定时间范围内的更新。当链上的交易严重拥堵时,价格更新可能会被延迟。
使用价格预言机的智能合约必须明确地检查数据是否陈旧,即最近在某个阈值内被更新。否则,它不能对价格做出可靠的决策。
还有一个更复杂的问题,如果价格没有变化超过偏差阈值,预言机可能不会更新价格以节省 Gas,所以这可能会影响到什么时间阈值被认为是 “陈旧”。
了解智能合约所依赖的 Oracle 的服务水平协议是很重要的。

只依赖一个预言机

无论一个预言机看起来多么安全,将来都可能发现攻击。对此的唯一防御措施是使用多个独立的预言机。

一般来说,预言机是很难正确的

区块链可以是相当安全的,但首先把数据放到链上就必须进行某种链外操作,这就放弃了区块链提供的所有安全保证。即使预言机者保持诚实,他们的数据来源也可以被操纵。例如,一个信使可以可靠地报告来自中心化交易所的价格,但这些价格可以被大量的买入和卖出订单所操纵。同样,依赖于传感器数据或一些 WEB2 api 的预言机也会受到传统黑客攻击的影响。
一个好的智能合约架构在可能的情况下会完全避免使用预言机。

混合计算

考虑以下合约

contract MixedAccounting {  uint256 myBalance;  function deposit() public payable {    myBalance = myBalance + msg.value;  }  function myBalanceIntrospect() public view returns (uint256) {    return address(this).balance;  }  function myBalanceVariable() public view returns (uint256) {    return myBalance;  }  function notAlwaysTrue() public view returns (bool) {    return myBalanceIntrospect() == myBalanceVariable();  }}

上面的合约没有接收或回退函数,所以直接将以太传送给它就会回退。然而,合约可以用自毁的方式强行向它发送以太。在此案例中,myBalanceIntrospect()会比 myBalanceVariable() 大。两种以太币的计算方法都没有问题,但如果你同时使用这两种方法,那么合约可能会有不一致的行为。
这同样适用于 ERC20 代币。

contract MixedAccountingERC20 {  IERC20 token;  uint256 myTokenBalance;  function deposit(uint256 amount) public {    token.transferFrom(msg.sender, address(this), amount);    myTokenBalance = myTokenBalance + amount;  }  function myBalanceIntrospect() public view returns (uint256) {    return token.balanceOf(address(this));  }  function myBalanceVariable() public view returns (uint256) {    return myTokenBalance;  }  function notAlwaysTrue() public view returns (bool) {    return myBalanceIntrospect() == myBalanceVariable();  }}

我们再次不能假设 myBalanceIntrospect()和 myBalanceVariable()总是返回相同的值。可以直接将 ERC20 代币转账到 MixedAccountingERC20,绕过存款函数,不更新 myTokenBalance 变量。
在用反省检查余额时,应避免严格使用相等检查,因为余额可以被外人随意改变。

把加密证明当作密码一样对待

这不是 Solidity 的一个怪癖,更多的是开发者对如何使用密码学来赋予地址特殊权限有普遍误解。下面的代码是不安全的:

contract InsecureMerkleRoot {  bytes32 merkleRoot;  function airdrop(bytes[] calldata proof, bytes32 leaf) external {    require(MerkleProof.verifyCalldata(proof, merkleRoot, leaf), "not verified");    require(!alreadyClaimed[leaf], "already claimed airdrop");    alreadyClaimed[leaf] = true;    mint(msg.sender, AIRDROP_AMOUNT);  }}

这段代码是不安全的,原因有三:

  1. 任何知道被选中进行空投的地址的人都可以重新创建 Merkle 树并创造一个有效的证明。
  2. 叶子没有 Hash。攻击者可以提交一个与 Merkle 根相同的叶子,并绕过 require 语句。
  3. 即使上述两个问题被修复,一旦有人提交了有效的证明,他们就可以被抢跑。

加密证明(Merkle 树、签名等)需要与 msg.sender 绑定,攻击者在没有获得私钥的情况下无法操纵。

Solidity 不会向上转型 uint 大小

function limitedMultiply(uint8 a, uint8 b) public pure returns (uint256 product) {  product = a * b;}

尽管 product 是一个uint256变量,但乘法结果不会大于 255,否则代码将被回退。
这个问题可以通过向上转型每个变量来解决:

function unlimitedMultiply(uint8 a, uint8 b) public pure returns (uint256 product) {  product = uint256(a) * uint256(b);}

在结构中的整数相乘,也会出现这样的情况。当乘以在结构中的小数值时,你应该注意到这一点:

struct Packed {  uint8 time;  uint16 rewardRate}//...Packed p;p.time * p.rewardRate; // this might revert!

Solidity 截断不会回退

Solidity 并不检查将一个整数转换为一个较小的整数是否安全。除非某些业务逻辑能确保向下转型是安全的,否则应该使用 SafeCast 这样的库。

function test(int256 value) public pure returns (int8) {  return int8(value + 1); // overflows and does not revert}

对存储指针的写入不会保存新数据

这段代码看起来像是把 myArray[1]中的数据复制到了 myArray[0]中,但其实不是。如果你把函数的最后一行注释掉,编译器会说这个函数应该变成一个视图函数。对 foo 的写入并没有写到底层存储。

contract DoesNotWrite {  struct Foo {    uint256 bar;  }  Foo[] public myArray;  function moveToSlot0() external {    Foo storage foo = myArray[0];    foo = myArray[1]; // myArray[0] 不会改变    // we do this to make the function a state    // changing operation    // and silence the compiler warning    myArray[1] = Foo({bar: 100});  }}

所以不要写到存储指针。

删除包含动态数据类型的结构体并不会删除动态数据

如果一个映射(或动态数组)在一个结构体内,并且该结构被删除,那么映射或数组将不会被删除。
除了删除数组之外,删除关键字只能删除一个存储槽。如果该存储槽包含对其他存储槽的引用,这些存储槽不会被删除。

contract NestedDelete {  mapping(uint256 => Foo) buzz;  struct Foo {    mapping(uint256 => uint256) bar;  }  Foo foo;  function addToFoo(uint256 i) external {    buzz[i].bar[5] = 6;  }  function getFromFoo(uint256 i) external view returns (uint256) {    return buzz[i].bar[5];  }  function deleteFoo(uint256 i) external {    // internal map still holds the data in the    // mapping and array    delete buzz[i];  }}

现在让我们做以下交易序列

  1. addToFoo(1)
  2. getFromFoo(1) 返回 6
  3. deleteFoo(1)
  4. getFromFoo(1) 仍然返回 6!

记住,在 Solidity 中,map 永远不会是 "空"的。因此,如果有人访问一个已经被删除的项目,交易将不会回退,而是返回该数据类型的零值。

来源地址:https://blog.csdn.net/weixin_28733483/article/details/132466173

--结束END--

本文标题: Solidity 合约安全,常见漏洞 (下篇)

本文链接: https://www.lsjlt.com/news/383266.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Solidity 合约安全,常见漏洞 (下篇)
    Solidity 合约安全,常见漏洞 (下篇) Solidity 合约安全,常见漏洞 (上篇) 不安全的随机数 目前不可能用区块链上的单一交易安全地产生随机数。区块链需要是完全确定的,否则分布式节点将无法达成关于状态的共识。因为它们是完全...
    99+
    2023-08-30
    安全 区块链 智能合约 安全威胁分析 web安全
  • Web常见安全漏洞有哪些
    本篇内容主要讲解“Web常见安全漏洞有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Web常见安全漏洞有哪些”吧!1、什么是SQL注入?SQL注入,就是通过...
    99+
    2024-04-02
  • 中间件安全—Tomcat常见漏洞
    中间件安全—Tomcat常见漏洞 1.Tomcat常见漏洞1.1.前言1.2.文件上传 (CVE-2017-12615)1.2.1.漏洞原理1.2.2.影响版本1.2.3.漏洞复现1.2.3....
    99+
    2023-10-25
    tomcat 中间件 web安全 信息与通信 服务器
  • PHP网站常见安全漏洞有哪些
    这篇“PHP网站常见安全漏洞有哪些”文章,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要参考一下,对于“PHP网站常见安全漏洞有哪些”,小编整理了以下知识点,请大家跟着小编的步伐一步一步的慢慢理解,接下来就让我们进入...
    99+
    2023-06-06
  • web应用常见的安全漏洞有哪些
    本篇内容介绍了“web应用常见的安全漏洞有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.SQL 注...
    99+
    2024-04-02
  • ASP Web安全漏洞:您应该了解的5种最常见的漏洞
    ASP(Active Server Pages)是一种流行的 Web 开发技术,允许开发人员创建动态和交互式的 Web 应用程序。然而,ASP 应用程序也容易受到各种安全漏洞的攻击。这些漏洞可能允许攻击者访问敏感数据、破坏应用程序或在服...
    99+
    2024-02-07
    ASP Web安全 漏洞 防御
  • 服务器安全补丁:5个最常见的安全漏洞
    服务器安全补丁是软件或操作系统中已知安全漏洞的修复程序,旨在防止网络攻击者利用这些漏洞对服务器进行攻击。及时安装安全补丁对于保护服务器安全至关重要。 以下是五个最常见的服务器安全漏洞: 1. SQL注入漏洞 SQL注入漏洞允许攻击者通过...
    99+
    2024-02-27
    服务器安全补丁 安全漏洞 网络攻击 数据泄露 补丁安装
  • PHP Web应用程序中的常见安全漏洞
    PHP 是一种流行的服务器端脚本语言,用于开发动态 Web 应用程序。但是,与任何其他软件一样,PHP Web 应用程序也可能遭受安全攻击。在本文中,我们将讨论 PHP Web 应用程序中一些最常见的安全漏洞以及如何避免它们。1. SQL ...
    99+
    2023-10-23
    php
  • ASP 重定向:避免常见错误和安全漏洞。
    ASP 重定向:避免常见错误和安全漏洞 ASP(Active Server Pages)是一种动态网页技术,允许开发人员在 HTML 页面中嵌入服务器端脚本。ASP 重定向是一种常见的技术,用于将用户重定向到另一个 URL。然而,如果不正确...
    99+
    2023-10-27
    重定向 打包 面试
  • 非常全面!PHP常见漏洞代码总结!
    本篇文章给大家带来了关于PHP漏洞的相关知识,其中主要给大家总结介绍PHP的常见漏洞代码都有哪些,非常全面详细,下面一起来看一下,希望对需要的朋友有所帮助。漏洞总结PHP 文件上传漏洞只验证MIME类型: 代码中验证了上传的MIME类型,绕...
    99+
    2023-05-14
    漏洞 php
  • Python开发注意事项:避免常见的安全漏洞
    Python作为一种简单易学的编程语言,被广泛应用于各类软件开发项目中。然而,随着互联网的发展和信息安全的重要性日益凸显,开发者们也越来越需要关注代码的安全性。本文将介绍一些在Python开发过程中需要注意的常见安全漏洞,并提供一些避免这些...
    99+
    2023-11-22
    sql注入 输入验证 跨站脚本攻击(XSS)
  • 常见的Web安全漏洞及测试方法是什么
    这篇文章主要讲解了“常见的Web安全漏洞及测试方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“常见的Web安全漏洞及测试方法是什么”吧!一、安全测试6项基本原则:认证:对认证的用户的...
    99+
    2023-06-05
  • 如何在PHP开发中避免常见的安全漏洞?
    如何在PHP开发中避免常见的安全漏洞?PHP是一种常用的服务器端脚本语言,广泛应用于Web开发。然而,由于其易用性和灵活性,PHP应用程序容易受到各种安全威胁。为了保护Web应用程序免受黑客攻击和数据泄露,开发者需要采取一些防范措施。下面是...
    99+
    2023-11-03
    安全漏洞 跨站脚本攻击 以防止SQL注入
  • 提高Linux服务器的安全性:常见安全漏洞和修复方法
    提高Linux服务器的安全性是确保服务器不易受到恶意攻击和未经授权的访问的重要措施之一。以下是一些常见的安全漏洞和修复方法:1. 更...
    99+
    2023-10-09
    Linux
  • 美国服务器常见的网络安全漏洞有哪些
    美国服务器常见的网络安全漏洞有:1、美国服务器安装的操作系统没有进行安全配置;2、美国服务器没有对CGI程序代码进行审计考查;3、美国服务器遭遇拒绝服务攻击;4、采用了网络安全设备,因为操作不当导致美国服务器出现网络安全漏洞;5、缺少网络安...
    99+
    2024-04-02
  • PHP网站常见的安全漏洞及防御方法有哪些
    本篇内容主要讲解“PHP网站常见的安全漏洞及防御方法有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PHP网站常见的安全漏洞及防御方法有哪些”吧!一、常见PHP网站安全漏洞对于PHP的漏洞,...
    99+
    2023-07-04
  • 揭秘Java Spring Boot Security:常见的安全漏洞与防御策略
    1. 常见的安全漏洞 1.1 未验证CSRF令牌 跨站点请求伪造(CSRF)是一种攻击,其中攻击者诱使合法用户在不知情的情况下执行恶意操作。Spring Boot Security默认禁用CSRF保护,开发人员需要手动启用并正确配置CS...
    99+
    2024-02-02
    Java Spring Boot Security 安全漏洞 防御策略
  • 避免PHP安全漏洞陷阱:常见的错误和预防措施
    ...
    99+
    2024-04-02
  • 【网络安全篇】php伪协议-漏洞及其原理
    🏆今日学习目标: 🍀学习php伪协议 ✅创作者:贤鱼 ⏰预计时间:35分钟 🎉个人主页:贤鱼的个人主页 🔥专栏系列:网络安全 &#x...
    99+
    2023-08-30
    php web安全 安全
  • Python开发注意事项:避免常见的安全漏洞和攻击
    Python作为一种广泛应用的编程语言,在大量的软件开发项目中得到了广泛的应用。然而,由于它的广泛使用,一些开发者可能会忽视一些常见的安全注意事项,从而导致软件系统的易受攻击和安全漏洞的产生。因此,在Python开发过程中,避免常见的安全漏...
    99+
    2023-11-22
    攻击 安全漏洞 注意事项
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作