By:Kong@ 慢霧安全團隊
據慢霧區消息,2021 年10 月27 日,Cream Finance 再次遭受攻擊,損失約1.3 億美金,慢霧安全團隊第一時間介入分析,並將簡要分析分享如下。
攻擊核心
本次攻擊的核心在於利用Cream 借貸池對抵押物價格獲取的缺陷,惡意操控拉高了其抵押物的價格,使得攻擊者可以從Cream 借貸池借出更多的代幣。
攻擊細節
首先攻擊者從DssFlash 中閃電貸借出5 億個DAI,隨後將藉出的5 億個DAI 抵押至yearn 的yDAI 池中,以獲得約4.5 億個yDAI 憑證。
隨後攻擊者將獲得的yDAI 代幣在Curve 的yDAI/yUSDC/yUSDT/yTUSD 池子中進行單幣流動性添加,以獲得相應的流動性憑證。緊接著攻擊者就將獲得的憑證抵押到yUSD 池子中以獲得yUSD 憑證,為後續在Cream crYUSD 借貸池中抵押做準備。
之後攻擊者開始向Cream 的crYUSD 借貸池中抵押其獲得yUSD 憑證,為了擴大其抵押規模,攻擊者從AAVE 閃電貸借出約52.4 萬個WETH,並將其抵押到Cream 的crETH 池子中。
攻擊者通過在crETH 池子中抵押大量ETH,來使得其有足夠的借貸能力將crYUSD 池子中的yUSD 全部借出並重複抵押到crYUSD 池子中,隨後通過在crYUSD 池子中進行循環貸以槓桿的形式擴大了本身在crYUSD 池子中yUSD 的抵押規模,為後續操控價格獲利做準備。
隨後為了獲得yDAI/yUSDC/yUSDT/yTUSD 4Pool 憑證以操控價格,攻擊者用約1,873 個ETH 從Uniswap V3 中兌換出約745 萬個USDC,並通過Curve 3Pool 將其兌換成DUSD 代幣約338 萬個。
接下來攻擊者通過獲得的DUSD 代幣從YVaultPeak 中贖回yDAI/yUSDC/yUSDT/yTUSD 4Pool 憑證,並利用此憑證從yUSD 池子中取回yDAI/yUSDC/yUSDT/yTUSD 代幣。
隨後攻擊者開始進行此次攻擊的關鍵操作,其將約843 萬個yDAI/yUSDC/yUSDT/yTUSD 代幣直接轉回yUSD 池子中,由於其不是通過正常抵押操作進行抵押的,所以這843 萬個yDAI/yUSDC/yUSDT/yTUSD 代幣並沒有被單獨記賬,而是直接分散給了yDAI/yUSDC/yUSDT/yTUSD 憑證的持有者,這相當於直接拉高了其share 的價格。
在crToken 中由於其抵押物價格被惡意拉高了,因此攻擊者抵押的大量yUSD 可以使其借出更多的資金,最後攻擊者將Cream 的其他15 個池子全部借空。接下來我們跟進Cream 的crToken 借貸池中具體借貸邏輯。
從cToken 合約中我們可以看到,主要藉貸檢查在borrowAllowed 函數中:
我們跟進borrowAllowed 函數,可以看到在427 行,其會根據getHypotheticalAccountLiquidityInternal 函數檢查實時狀態下的該賬戶所對應的所有cToken 的資產價值總和和借貸的資產價值總和,並通過對比cToken 的資產價值和借貸的Token 價值和,來判斷用戶是否還可以繼續借貸。
我們跟進getHypotheticalAccountLiquidityInternal 函數,可以發現對於抵押物的價值獲取來自886 行的oracle.getUnderlyingPrice。
我們跟進預言機的getUnderlyingPrice 函數,可以容易的發現其將通過代幣150 行的getYvTokenPrice 函數進行價格獲取。
繼續跟進getYvTokenPrice 函數,由於yvTokenInfo.version 為V2,因此將通過yVault 的pricePerShare 函數進行價格獲取。
跟進pricePerShare 可以發現其直接返回了_shareValue 作為價格,而_shareValue 是通過_totalAssets 除合約的總share 數量(self.totalSupply) 來計算單個share 的價格的。因此攻擊者只需要操控_totalAssets 將其拉高就可以提高單個share 的價格從而使得攻擊者的抵押物價值變高以藉出更多的其他代幣。
我們可以查看下_totalAssets 是如何獲取的,從772 行我們可以很清晰的看到,_totalAssets 是直接取的當前合約的yDAI/yUSDC/yUSDT/yTUSD 代幣數量,以及抵押在策略池中的資產數額相加獲得的。因此攻擊者通過直接往yUSD 合約中轉入yDAI/yUSDC/yUSDT/yTUSD 代幣就可以拉高share 價格從而完成獲利。
通過Ethtx.info 可以清晰的看到pricePerShare 前後變化:
最後攻擊者在藉空其他池子後歸還了閃電貸獲利離場。
總結
本次攻擊是典型的利用閃電貸進行價格操控,由於Cream 的借貸池在獲取yUSD 池子share 價格時直接使用了其pricePerShare 接口,而此接口是通過合約的抵押物餘額與策略池抵押資產數額相加除總share 數來計算單個share 的價格的。因此用戶直接往yUSD 轉入抵押物就可以很容易的拉高單個share 價格,最終使得Cream 借貸池中抵押物可以藉出更多的資金。
附:前兩次Cream Finance 被黑分析回顧