jjzjj

tx.origin 与 msg.sender

安泽1314 2024-06-06 原文

我最近一直在玩ethernaut web3/solidity 游戏,在第 4 级上,我浪费了几分钟来了解 tx.origin 和 msg.sender 之间的区别,它们在solidity 中构建全局变量。

根据solidity文档,tx.origin 保存交易发送者的地址,msg.sender 保存消息发送者的地址。那么这到底是什么意思呢?

msg.sender:指直接调用智能合约函数的账户地址或智能合约地址。

tx.origin:指调用智能合约函数的账户地址,只有账户地址可以是tx.origin。

一张图片胜过千言万语

您可能会注意到,账户地址和智能合约地址都可以是 msg.sender 但 tx.origin 将始终是账户/钱包地址。

强烈建议始终使用 msg.sender 进行授权或检查调用智能合约的地址。并且永远不要使用 tx.origin 进行授权,因为这可能会使合约容易受到网络钓鱼攻击。

THORChain最近损失了 800 万美元,是的,由于tx.origin 的滥用,在一次攻击中损失了 800 万美元,请务必仔细检查 tx.origin 是如何在智能合约中使用的,再见👋。

使用 tx.origin 进行网络钓鱼

msg.sender和有什么区别tx.origin

如果合约 A 调用 B,B 调用 C,则在 Cmsg.sender中是 B,并且tx.origin是 A。

漏洞

恶意合约可以欺骗合约所有者调用只有所有者才能调用的函数。

// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; /* Wallet is a simple contract where only the owner should be able to transfer Ether to another address. Wallet.transfer() uses tx.origin to check that the caller is the owner. Let's see how we can hack this contract */ /* 1. Alice deploys Wallet with 10 Ether 2. Eve deploys Attack with the address of Alice's Wallet contract. 3. Eve tricks Alice to call Attack.attack() 4. Eve successfully stole Ether from Alice's wallet What happened? Alice was tricked into calling Attack.attack(). Inside Attack.attack(), it requested a transfer of all funds in Alice's wallet to Eve's address. Since tx.origin in Wallet.transfer() is equal to Alice's address, it authorized the transfer. The wallet transferred all Ether to Eve. */ contract Wallet { address public owner; constructor() payable { owner = msg.sender; } function transfer(address payable _to, uint _amount) public { require(tx.origin == owner, "Not owner"); (bool sent, ) = _to.call{value: _amount}(""); require(sent, "Failed to send Ether"); } } contract Attack { address payable public owner; Wallet wallet; constructor(Wallet _wallet) { wallet = Wallet(_wallet); owner = payable(msg.sender); } function attack() public { wallet.transfer(owner, address(wallet).balance); } }  
 

预防技术

使用msg.sender代替tx.origin

function transfer(address payable _to, uint256 _amount) public { require(msg.sender == owner, "Not owner"); (bool sent, ) = _to.call{ value: _amount }(""); require(sent, "Failed to send Ether"); } 

参考

https://medium.com/@nicolezhu/ethernaut-lvl-4-walkthrough-how-to-abuse-tx-origin-msg-sender-ef37d6751c8

有关tx.origin 与 msg.sender的更多相关文章

  1. ruby 在 `gem_original_require' : no such file to load -- CloudyScripts (LoadError) - 2

    在Ubuntu和Ruby1.8.7上,我通过以下方式安装了CloudyScripts:geminstallgeminstallCloudyScripts当我尝试执行此操作时:require'rubygems'require'CloudyScripts'我收到以下错误:/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in`gem_original_require':nosuchfiletoload--CloudyScripts(LoadError)from/usr/lib/ruby/1.8/rubygems/custom_require.r

  2. ruby - 为 ruby​​ 套接字定义的 MSG_ 选项在哪里? - 2

    在Ruby类Socket::recv的文档中,提到了第二个选项参数“flag”,据说它是零个或多个MSG_选项。我检查了几个不同的站点,但无法找到MSG_选项。谁能指出这些标志的文档? 最佳答案 除了前面的Socket::之外,它们与CBSD套接字堆栈中相应的#define同名。(作为记录,为了回答您提出的确切问题,我应该在Ruby源代码树中说"inext/socket/socket.c"。)所以:>>require'socket'=>true>>Socket::MSG_PEEK=>2您可能可以通过键入man2recv来查看,但您可

  3. ruby-on-rails - ruby /RoR : calling original method via super()? - 2

    在RoR应用程序中,我想在我的一个模型中专门化ActiveRecord的update_attributes()方法,提取一些属性进行特殊处理,并将其余属性传递给原始的update_attributes()方法。详情:classPremise对super.update_attributes(attr)的调用引发错误:undefinedmethod`update_attributes'fortrue:TrueClass...这让我怀疑我真的不了解Ruby中的super关键字。我错过了什么?具体来说,如何调用原始的update_attributes()方法? 最佳

  4. ruby 摩卡 : is there an equivalent to rspec-mocks' #and_call_original? - 2

    Rspec-mocks具有expect(some_object).toreceive(:some_method).and_call_original。我可以用Mocha做这个吗?如果可以,怎么做?some_object.expects(:some_method).......什么? 最佳答案 我相当确定没有办法做到这一点。浏览sourcecode,有评论提到完全替换了原来的方法。#Theoriginalimplementationofthemethodisreplacedduringthetestandthenrestoredatt

  5. javascript - "error": "Invalid origin" using dropbox chooser - 2

    DropBoxChooserExample$(function(){vardbChooser=$("#db-chooser");dbChooser.on("DbxChooserSuccess",function(e){//Herewewilllistenwhenafileis//chosenfromdropbox,insertitintothepage//andinitializetheJcropplugine=e.originalEvent;varname=e.files[0].name;});});这是我尝试实现保管箱选择器的示例代码。我已经创建了一个应用程序,并且确实传递了应用程

  6. javascript - ReactJS - ReactMount : Root element has been removed from its original container. 新容器 - 2

    这个错误是什么意思?如何解决?ReactMount:Rootelementhasbeenremovedfromitsoriginalcontainer.Newcontainer在这之后我得到了这个:Uncaughtobjectreact.js:15915invariantreact.js:15915ReactMount.findComponentRootreact.js:10584ReactMount.findReactNodeByIDreact.js:10480getNodereact.js:10089(anonymousfunction)react.js:7307(anonymou

  7. javascript - 设置Access-Control-Allow-Origin可能存在的安全问题 - 2

    我看到设置“*”通配符存在安全风险,即Access-Control-Allow-Origin:"*"我想知道在设置具体域时是否存在任何安全风险,即Access-Control-Allow-Origin:http://www.example.com 最佳答案 CORSheader通常用于JavaScriptAJAX请求。浏览器有一个内置的安全机制,不允许您查询其他域,除非它们通过设置这些CORSheader明确允许。实际上并没有太大的安全风险。无论如何,您始终可以发送恶意请求。浏览器只是集体决定玩好。需要注意的一件事是您不一定总是要发

  8. javascript - GAE( python ): set Access-Control-Allow-Origin - 2

    我在googleappengine(python)中有一个静态页面,我想从另一个页面$.load()此页面的内容->因此我遇到了CORS问题。如何在GAE中设置允许所有域加载页面内容?(Access-Control-Allow-Origin:*) 最佳答案 在app.yaml中http_headers:X-Foo-Header:fooX-Bar-Header:barvaluehttps://developers.google.com/appengine/docs/python/config/appconfig#Static_Dire

  9. javascript - 缺少 CORS header 'Access-Control-Allow-Origin' - 2

    我正在尝试将webUntis(docs)API用于学校项目。现在,我只是尝试与API建立任何类型的连接。varresult;consturl='https://api.webuntis.dk/api/status';varxhr=newXMLHttpRequest();xhr.open('GET',url,true);xhr.setRequestHeader('Access-Control-Allow-Origin','*');xhr.setRequestHeader('Content-type','application/json');xhr.setRequestHeader('Ac

  10. javascript - 尽管 header 正确,但 CORS Access-Control-Allow-Origin - 2

    我正在尝试在客户端上使用jQuery(1.7.1)驱动的ajax和apache服务的python(django)服务器来设置简单的跨源资源共享。根据我阅读过的所有说明,我的header设置正确,但我不断收到以下错误:XMLHttpRequestcannotloadhttp://myexternaldomain.com/get_data.Originhttp://localhost:8080isnotallowedbyAccess-Control-Allow-Origin.我正在尝试发送的header(我不确定它是否通过了浏览器)是:RequestURL:http://myexterna

随机推荐