本文从源代码层面详解介绍了Solidity(0.8.13<=solidity<0.8.17)编译器在编译过程中,因为Yul优化机制的缺陷导致的状态变量赋值操作被错误删除的中/高漏洞原理及相应的预防措施。
帮助合约开发人员提高合约开发时的安全意识,有效规避或缓解SOL-2022-7漏洞对合约代码安全性的影响。
1.漏洞详情
Yul优化机制是Solidity编译合约代码的可选项,可以通过优化机制减少合约中某些冗余的指令,从而降低合约部署和执行过程中的gas费用,具体的Yul优化机制可以参考官方文档。
在编译过程的UnusedStoreEliminator优化步骤中,编译器会将“冗余”的Storage写入操作移除,但由于对“冗余”的识别缺陷,当某个Yul函数块调用特定的用户定义函数(函数内部存在某个分支不影响调用块的执行流),且在该Yul函数块中被调用函数前后存在对同一状态变量的写入操作,会导致在Yul优化机制将块中该用户定义函数被调用前的所有的Storage写入操作从编译层面被永久删除。
考虑如下代码:
contractEocene{
uintpublicx;
functionattack()public{
加密KOL ZachXBT:链游SolChicks开发商未向社区披露UST暴雷损失的2000万美元资金:11月16日消息,加密KOL ZachXBT表示,根据Solana上P2E游戏Sol Chicks开发商Catheon Gaming首席执行官和首席运营官之间新泄露的消息,由于2022年5月的UST暴雷事件,该项目损失了高达2000万美元的财库资金,并决定不通知社区。
Zach XBT联系了Catheon Gaming首席运营官对此发表评论,其表示关于UST--我们与我们最大的私人持有者讨论并披露了这一问题。但为了项目的最佳利益,不冒不必要的风险选择不公开宣布,而且我们没有杠杆。
此外,Zach XBT表示查看SolchicksSaft的ETH地址(0x89af65FF45F00149C6d847e9344F9dE5989641D0),发现他们似乎没有将资金保存在多重签名中。[2022/11/16 13:10:47]
x=1;
x=2;
}
}
在UnusedStoreEliminator优化时,x=1显然对于函数attack()的整个执行是冗余的。自然的,优化后的Yul代码会将x=1;删除来降低合约的gas消耗。
接下来考虑在中间插入对自定义函数调用:
Solana 将在纽约开设实体店和 Web3“大使馆”:金色财经报道,以Solana为主题的线下实体商店Solana Spaces将在纽约市开业,该店位于 Hudson Yards,与同名区块链网络背后的组织 Solana Foundation 合作推出。Solana Spaces在推特表示:在商店内,您将了解 Solana 的工作原理,以及 Web3 是什么。我们将为您设置一个钱包和您的第一个 NFT,并指导您完成您的第一个链上交易,我们将这个空间设计为Solana 的‘文化中心’和‘大使馆’。除了 NFT 和Phantom 钱包教程之外,该商店还将为消费者提供互动艺术装置,以及大量出售 Solana 品牌商品,包括限量版Blanksoles运动鞋。[2022/7/28 2:42:30]
contractEocene{
uintpublicx;
functionattack(uinti)public{
x=1;
y(i);
x=2;
}
functiony(uinti)internal{
if(i>0){
return;
}
Blockware Solutions?宣布与 SEVA 建立新的合作伙伴关系:金色财经报道,?比特币矿机公司Blockware Solutions?宣布与 SEVA 建立新的合作伙伴关系。Blockware Solutions 已经启动了一项 150 兆瓦的矿场,以扩大其在 SunPark 的比特币采矿业务,Blockware Solutions 将在第一阶段的建设中投资1000 万美元。第一阶段将是一个占地 20 英亩的 60 兆瓦设施,将采用浸没式冷却采矿和托管业务。该项目预计将于 2022 年第四季度开始。[2022/5/27 3:44:38]
assembly{return(0,0。
}
}
显然,由于y()函数的调用,我们需要判断y()函数是否会影响函数attack()的执行,如果y()函数可以导致整个函数执行流终止(注意,不是回滚,Yul代码中的return()函数可以实现),那么x=1显然是不能删除的,所以对于上面的合约来说由于y()函数中存在assembly{return(0,0。可以导致整个消息调用终止,x=1自然不能被删除。
但在Solidity编译器中,由于代码逻辑的问题,使得x=1在编译时被错误的删除,永久改变了代码逻辑。
实际编译测试结果如下:
数据:Solana上DeFi协议总锁仓量为67亿美元:金色财经报道,DeFiLlama数据显示,Solana上DeFi协议总锁仓量为67亿美元.其中,锁仓量排名前三的协议分别是MarinadeFinance(7.26亿美元)、Serum(6.92亿美元)、Raydium(6.54亿美元)。[2022/4/16 14:28:17]
震惊!不应该被优化的x=1的Yul代码丢了!欲知后事如何,请往下看。
在solidiry编译器代码的UnusedStoreEliminator中,通过SSA变量追踪和控制流追踪来判断一个Storage写入操作是否是冗余的。当进入一个自定义函数中时,UnusedStoreEliminator如果遇到:
memory或storage写入操作:将memory和storage写入操作存储到m_store变量中,并将该操作的初始状态设置为Undecided;
函数调用:获取函数的memory或storage读写操作位置,并和m_store变量中存储的所有Undecided状态下的操作进行对比:
基于Solana的短视频分享平台Chingari推出加密钱包:2月15日消息,基于 Solana 的短视频分享平台 Chingari 宣布推出加密钱包,旨在帮助其用户在平台内转移其平台 Token GARI。据悉,用户可以通过观看短视频来赚取 GARI,并使用 GARI 作为小费打赏他们最喜欢的短视频创作者,或者在平台内购买商品。目前 Chingari 平台的月活用户已达到 3500 万人。
此前报道,短视频分享平台 Chingari 于 2021 年 10 月宣布完成 1900 万美元融资。[2022/2/15 9:53:17]
1.如果是对m_store中存储操作的写入覆盖,则将m_store中对应的操作状态改为Unused
2.如果是对m_store中存储操作的读取,则将对应m_store中的对应操作状态改为Used
3.如果该函数没有任何可以继续执行消息调用的分支,将m_store中所有的内存写操作改为Unused
1.在上诉条件下,如果函数可以终止执行流,将m_store中,状态为Undecided状态的storage写操作改为Used;反之,标识为Unused
函数结束:将所有标记为Unused的写入操作删除
对memory或storage写入操作的初始化代码如下:
可以看到,将遇到的memory和storage写入操作存储到m_store中
遇到函数调用时的处理逻辑代码如下:
其中,operationFromFunctionCall()和applyOperation()实现上诉的2.1,2.2处理逻辑。位于下方的基于函数的canContinue和canTerminate进行判断的If语句实现2.3逻辑。
需要注意,正是下方的If判断的缺陷,导致了漏洞的存在!!!
operationFromFunctionCall()来获取该函数的所有memory或storage读写操作,这里需要注意,Yul中存在很多的内置函数,例如sstore(),return()。这里可以看到对于内置函数和用户定义函数有不同的处理逻辑。
而applyOperation()函数则是将从operationFromFuncitonCall()获取的所有读写操作进行对比,来判断存储到m_store中的是否在该次函数调用中被读写,并修改m_store中的对应的操作状态。
考虑上述的UnusedStoreEliminator优化逻辑对Eocene合约的attack()函数的处理:
将x=1存储操作到m_store变量中,状态设置为Undecided
1.遇到y()函数调用,获取y()函数调用的所有读写操作
2.遍历m_store变量,发现y()调用引起的所有读写操作和x=1无关,x=1状态仍然是Undecided
1.获取y()函数的控制流逻辑,因为y()函数存在可以正常返回的分支,所以canContinue为True,不进入If判断。x=1状态仍然为Undecided!!!
3.遇到x=2存储操作:
1.遍历m_store变量,发现处于Undecided状态的x=1,x=2操作覆盖x=1,设置x=1状态为Unused。
2.将x=2操作存入m_store,初始状态为undecided。
4.函数结束:
1.将所有m_store中undecided状态的操作状态改为Used
2.将所有m_store中Unused状态的操作删除
显然,在调用函数时,如果被调用函数可以终止消息执行,应该将被调用函数前所有的Undecided状态的写入操作改为Used,而不是依旧保留为Undecided,导致位于被调用函数前的写入操作被错误的删除。
此外,需要注意的是,每个用户自定义函数控制流标识是会传递的,所以在多个函数递归调用的场景下,即便最底层函数满足上诉逻辑,x=1也有可能被删除。
在Solidity中,举例了基本相同的逻辑下,不会受到影响的合约代码。但,该代码不受该漏洞的影响并不是因为UnusedStoreEliminator的处理逻辑存在其他可能,而是在UnusedStoreEliminator之前的Yul优化步骤中,存在FullInliner优化过程会将微小或只有一次调用的被调用函数,嵌入到调用函数中,避免了漏洞触发条件中的用户定义函数。
contractNormal{
uintpublicx;
functionf(boola)public{
x=1;
g(a);
x=2;
}
functiong(boola)internal{
if(!a)
assembly{return(0,0。
}
}
编译结果如下:
函数g(boola)被嵌入到函数f()中,避免了用户定义函数的漏洞条件,避免了漏洞的产生。
2.解决方案
最根本的解决方案是不使用在受影响范围的solidity编译器进行编译,如果需要使用漏洞版本的编译器,可以考虑在编译时去除UnusedStoreEliminator优化步骤。
如果想要从合约代码层面进行漏洞缓解,考虑到多个优化步骤的复杂性,以及实际函数调用流的复杂性,请寻找专业的安全人员进行代码审计来帮助发现合约中的因为该漏洞导致的安全问题。
2022年,波场TRON参与了行业每一个重要叙事,站在不同的角度,每一次叙事都展现了波场全新的身份。2022波场TRON展示的硬核身份有哪些,我们将通过系列海报来一一揭晓.
1900/1/1 0:00:00各位朋友,欢迎来到SignalPlus宏观点评。SignalPlus宏观点评每天为各位更新宏观市场信息,并分享我们对宏观趋势的观察和看法。欢迎追踪订阅,与我们一起关注最新的市场动态.
1900/1/1 0:00:002月6日,土耳其先后发生两次震源深度20公里的7.8级强烈地震,这是自1939年以来土耳其遭遇的最大地震,波及叙利亚、黎巴嫩、塞浦路斯、希腊、伊朗等国,据土耳其媒体当地时间8日凌晨发布消息称,土耳其副总统奥克塔伊表示.
1900/1/1 0:00:00作为全球增速最快的公链,过去一年波场TRON在国际化与合规化上取得了诸多历史性突破,全球影响力也大幅跃升.
1900/1/1 0:00:00公链作为Web3世界的基础设施和底层技术,是Dapp的基石,是生态和社区的聚集地。从Layer1到Layer3,公链项目层出不穷.
1900/1/1 0:00:00加密货币交易平台BitMEX概述了未来几个月加密货币行业可能出现的三种情况。该公司认为美联储很可能在年底前停止加息,引发资金流入全球资本市场和避险资产。在这种情况下,比特币和以太坊等加密货币可能会受益.
1900/1/1 0:00:00