本文從源代碼層面詳解介紹了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;
Solend提案通過,Solend Labs可臨時接管巨鯨賬戶:6月19日消息,Solana生態借貸協議Solend發起的治理提案已獲得通過,贊成票1,155,431(97.5%)。該提案支持對占借款總額20%以上的巨鯨制定特殊的保證金要求,如果用戶的借款超過主池所有借款的20%,則需要35%的特殊清算門檻;授予Solend Labs緊急權力以暫時接管鯨魚的賬戶,以便清算可以在場外交易中執行,避免將Solana推到極限,這將通過智能合約升級來完成。一旦鯨魚的賬戶達到安全水平,緊急權力將被撤銷。
此前消息,Solend創始人Rooter敦促某個巨鯨(3oSE開頭地址)盡快償還貸款,以避免清算風險。Solend已臨時禁用其Main Pool的USDC、USDT和SOL借款。[2022/6/20 4:38:59]
functionattack()public{
x=1;
x=2;
}
}
在UnusedStoreEliminator優化時,x=1顯然對于函數attack()的整個執行是冗余的。自然的,優化后的Yul代碼會將x=1;刪除來降低合約的gas消耗。
接下來考慮在中間插入對自定義函數調用:
Solana鏈上合成資產協議Parcl完成750萬美元戰略融資,Solana Ventures和Dragonfly等參投:5月20日消息,Solana鏈上合成資產協議Parcl宣布完成750萬美元戰略融資,Archetype、Dragonfly、NotBoring、Solana Ventures、FJLABS、Fifth Wall、JAWS(Barry Sternlicht)、Hack VC、IA Capital&Eberg Capital、BigBrainHoldings、以及天使投資人Santiago Santos參投。
Parcl是一家通過Solana區塊鏈將房地產投資數字化的初創公司,通過合成資產“Parcls”提供投資敞口,使每個人都有機會參與房地產市場,而無需承擔與擁有或交易硬資產相關的負擔。此前報道,3月2日,Parcl完成410萬美元的種子輪融資,Archetype領投。[2022/5/20 3:31:19]
contractEocene{
uintpublicx;
functionattack(uinti)public{
x=1;
y(i);
x=2;
Solana Pay上線交易請求功能,可實現商家和消費者之間的雙向交互:5月5日消息,Solana 發推稱其支付協議 Solana Pay 現已上線交易請求功能,可實現商家和消費者之間的雙向交互,目前可以通過結賬應用和移動錢包之間的交互請求將任何 Solana 交易帶入現實世界,從而實現 NFT 鑄造、動態折扣、代幣化忠誠度計劃等。
此前消息,2 月份,Solana Labs 宣布推出 Solana Pay 支付協議,使得商家可以直接從消費者處接受加密支付,目前支持穩定幣 USDC、Solana 的原生代幣 SOL 以及其他基于 Solana的代幣。[2022/5/5 2:51:36]
}
functiony(uinti)internal{
if(i>0){
return;
}
assembly{return(0,0。
}
}
顯然,由于y()函數的調用,我們需要判斷y()函數是否會影響函數attack()的執行,如果y()函數可以導致整個函數執行流終止(注意,不是回滾,Yul代碼中的return()函數可以實現),那么x=1顯然是不能刪除的,所以對于上面的合約來說由于y()函數中存在assembly{return(0,0。可以導致整個消息調用終止,x=1自然不能被刪除。
Terra社區新提案提議向Orca、Solend、C98、FantomMaker分配150萬美元UST:4月15日消息,Terra社區發起新的Agora提案,提議分配150萬美元UST用于Orca(43.2萬美元)、Solend(55萬美元)、C98(3萬美元)和FantomMaker(50萬美元)的流動性激勵。[2022/4/15 14:26:10]
但在Solidity編譯器中,由于代碼邏輯的問題,使得x=1在編譯時被錯誤的刪除,永久改變了代碼邏輯。
實際編譯測試結果如下:
震驚!不應該被優化的x=1的Yul代碼丟了!欲知后事如何,請往下看。
在solidiry編譯器代碼的UnusedStoreEliminator中,通過SSA變量追蹤和控制流追蹤來判斷一個Storage寫入操作是否是冗余的。當進入一個自定義函數中時,UnusedStoreEliminator如果遇到:
memory或storage寫入操作:將memory和storage寫入操作存儲到m_store變量中,并將該操作的初始狀態設置為Undecided;
Solana 生態 NFT 交易市場 Solanat 將推出 NFT Launchpad:3月21日消息,Solana 生態 NFT 交易市場 Solanat 宣布即將推出 NFT Launchpad。該 NFT 鑄造平臺將提供 3% 的項目費、獨特的動畫等。[2022/3/21 14:08:29]
函數調用:獲取函數的memory或storage讀寫操作位置,并和m_store變量中存儲的所有Undecided狀態下的操作進行對比:
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優化步驟。
如果想要從合約代碼層面進行漏洞緩解,考慮到多個優化步驟的復雜性,以及實際函數調用流的復雜性,請尋找專業的安全人員進行代碼審計來幫助發現合約中的因為該漏洞導致的安全問題。
BitfinexAlpha|隨著美聯儲繼續抗擊通貨膨脹,比特幣市場在喜憂參半的前景中趨于穩定當前的宏觀經濟的前景喜憂參半,仍有一些挑戰需要克服.
1900/1/1 0:00:00概要 此報告將調查由Tangible發行的USDR穩定幣所帶來的風險。該團隊于2023年3月提交了一個提案,旨在將CRV激勵添加到Polygon上的USDR/am3CRV池中.
1900/1/1 0:00:00日前,“孫宇晨美術館”重磅亮相。作為主講人,波場TRON創始人孫宇晨在開箱視頻中向大家介紹了多個頂級藏品。本期我們聚焦畢加索的《戴項鏈的躺臥裸女》,帶大家了解藏品背后的故事.
1900/1/1 0:00:00加密貨幣交易平臺BitMEX概述了未來幾個月加密貨幣行業可能出現的三種情況。該公司認為美聯儲很可能在年底前停止加息,引發資金流入全球資本市場和避險資產.
1900/1/1 0:00:00區塊鏈瀏覽器TRONSCAN最新數據顯示,截至2023年4月3日,波場TRON賬戶總數達到150,379,816,正式突破1.5億.
1900/1/1 0:00:00作者記者獲悉,網易旗下區塊鏈項目網易星球已于4月11日上線資訊挖礦功能。據新規則介紹,玩家每日有效瀏覽資訊大于2條且累計超過60秒即可獲得“原力”,點擊廣告也有機會得“原力”,分配“原力”的范圍.
1900/1/1 0:00:00