By:Kong@ 慢霧安全團隊

梅開二度 —— PancakeBunny 被黑分析

據慢霧區消息,2021 年 07 月 17 日,DeFi 收益聚合器 PancakeBunny 在 Polygon 上的版本遭受閃電貸攻擊,慢霧安全團隊第一時間介入分析,並將結果分享如下。

值得注意的是本次攻擊與 5 月 20 日 PancakeBunny 在幣安智能鏈上的版本遭受的閃電貸攻擊類似。此前慢霧安全團隊也進行了簡要分析,具體可查看:代幣閃崩,差點歸零 – PancakeBunny 被黑簡析

攻擊細節分析

首先攻擊者從 AAVE 中閃電貸借出大量的 USDC、USDT、WETH 代幣,並將借來的 USDC 與 USDT 代幣轉入 SushiSwap 中添加流動性以獲得 SLP。

梅開二度 —— PancakeBunny 被黑分析

隨後攻擊者進行了本次攻擊最爲關鍵的操作:將添加流動性獲得的 LP 的一小部分抵押至 VaultSushiFlipToFlip 合約中,爲獲得 polyBUNNY 代幣獎勵做準備。而其餘大部分 LP 都抵押到 MiniChefV2 中,並將存款收益地址指定爲 VaultSushiFlipToFlip 合約。

梅開二度 —— PancakeBunny 被黑分析

接下來爲了減少攻擊成本,使用借來的 100,000 個 WETH 代幣,在 QuickSwap 中將其兌換成 WMATIC 代幣 (在後面的分析將會說明爲何這樣會減少攻擊成本)

梅開二度 —— PancakeBunny 被黑分析

隨後攻擊者調用了 VaultSushiFlipToFlip 合約的 withdrawAll 函數,以獲取抵押的 SLP 與 polyBUNNY 代幣獎勵。我們切入此函數進行具體分析:

梅開二度 —— PancakeBunny 被黑分析

梅開二度 —— PancakeBunny 被黑分析

在上圖代碼第 162 行與 163 行,分別通過 balanceOf 函數與 principalOf 函數獲取攻擊者抵押憑證換算成用戶通過 VaultSushiFlipToFlip 合約在 MiniChefV2 中抵押的 SLP 數量以及用戶在 VaultSushiFlipToFlip 合約中抵押時記錄的 SLP 數量。理論上這兩個數量不應相差太多,但通過分析 balanceOf 函數我們發現:其是通過 balance 函數獲取 VaultSushiFlipToFlip 合約在 MiniChefV2 中抵押的 SLP 數量與用戶持有的憑證佔比相乘得到 amount 的。

由於攻擊者已提前將大量的 SLP 未通過 VaultSushiFlipToFlip 合約直接在 MiniChefV2 合約中抵押並將受益地址指給 VaultSushiFlipToFlip 合約,因此 balance 函數將會獲取到一個比預期大得多的值,而攻擊者的憑證佔比卻又是正常的,最後導致賦給 amount 的是個比預期大得多的值。這就直接導致了在上圖代碼第 176 行計算出的 performanceFee 參數是個非預期的巨大值。

隨後將此異常的 performanceFee 參數傳入 mintForV2 函數中參與鑄造 polyBUNNY 代幣獎勵的計算,我們切入此函數進行分析:

梅開二度 —— PancakeBunny 被黑分析

梅開二度 —— PancakeBunny 被黑分析

我們可以發現其通過調用 mintFor 函數進行具體的邏輯處理,首先在上圖代碼第 205 行將 SLP 發送給 Pair 合約,爲後續移除流動性做準備。由於 shouldMarketBuy 函數最終價格比較計算爲 false,因此將通過 if 邏輯調用_zapAssets 函數。我們切入_zapAssets 函數繼續分析:

梅開二度 —— PancakeBunny 被黑分析

在_zapAssets 函數,由於 asset 爲 SLP 因此將通過 else if 邏輯先通過調用 SushiSwap Router 合約的 removeLiquidity 函數進行移除流動性,隨後通過_tokenToAsset 函數將移除流動性獲得 USDC 與 USDT 代幣分別在 QuickSwap 中兌換成 polyBUNNY 與 WETH 代幣並在 QuickSwap 中添加流動性。接下來我們對_tokenToAsset 函數進行分析:

梅開二度 —— PancakeBunny 被黑分析

通過簡單分析我們可以發現,其將通過 if 邏輯直接調用 zapPolygon 合約的 zapInToken 函數,這裏不再贅述判斷條件的分析。接下來跟進 zapInToken 函數分析:

梅開二度 —— PancakeBunny 被黑分析

同樣通過對判斷條件的簡單分析,我們可以指定其將通過上圖代碼第 133 行進入 else 邏輯,接下來調用 _swapTokenForMATIC 函數通過下圖代碼第 221 行 if 邏輯設定的代幣兌換路徑 **“USDC -> WETH -> WMATIC\”**,USDT 代幣的兌換路徑同樣如此。

梅開二度 —— PancakeBunny 被黑分析

由於在此之前,攻擊者已經使用借來的 100\\,000 個 WETH 代幣在 QuickSwap 中 通過 “WETH -> WMATIC” 將其兌換成大量的 WMATIC 代幣,所以上述通過 **“USDC/USDT -> WETH -> WMATIC”**路徑兌換到的 WMATIC 代幣變得很少,因此接下來通過_swapMATICToFlip 函數將 WMATIC 代幣兌換成的 WETH 與 polyBUNNY 代幣就會較少,導致最後轉給 BUNNY_POOL 的 LP 會較少,達到減少消耗攻擊者付出的 SLP 目的,最終減少了一部分攻擊成本。

接下來我們再看 mintFor 函數,在完成上述一系列操作後,將通過 amountBunnyToMint 函數計算需要鑄造的 polyBUNNY 代幣數量,而通過下圖我們可以看出參與計算的 contributionInETH 參數來自於 priceCalculator 合約的 valueOfAsset 函數,但 valueOfAsset 函數接收的參數卻是我們先前所說的_performanceFee 參數,這是一個非預期的巨大值。

梅開二度 —— PancakeBunny 被黑分析

我們可以對 valueOfAsset 函數進行簡單的分析:

梅開二度 —— PancakeBunny 被黑分析

由於 asset 是 SLP,因此將通過上圖代碼第 155 行調用_getPairPrice 函數,通過對此函數進行分析我們可以發現,參與價格獲取的途徑都爲可信的預言機,因此攻擊者無法直接操控預言機進行攻擊。但由於參與計算的 amount 即_performanceFee 是個非預期的巨大值,因此最終通過乘法計算得出的 valueInETH 與 valueInUSD 都是非預期的巨大值。

梅開二度 —— PancakeBunny 被黑分析

梅開二度 —— PancakeBunny 被黑分析

隨後會將獲得的非預期的 contributionInETH 參數傳入 amountBunnyToMint 函數進行鑄幣數量計算。

梅開二度 —— PancakeBunny 被黑分析

而這裏的 priceOfETH 與 priceOfBunny 都取自可信的 ChainLink 與 官方自行喂價的預言機,因此最終經過乘法計算後,得到的鑄幣數量 mintBunny 是個非預期的巨大值。導致最終攻擊者獲得了大量的 polyBUNNY 代幣獎勵。

攻擊流程

1. 攻擊者在 AAVE 閃電貸借出 USDT/USDC/WETH 代幣,並在 SushiSwap 中添加流動性獲得 SLP。

2. 將大部分的 SLP 轉入 MiniChefV2 中並將受益地址指定給 VaultSushiFlipToFlip 合約,小部分抵押到 VaultSushiFlipToFlip 合約中。

3. 由於攻擊者的大部分抵押到 MiniChefV2 中的 SLP 受益地址指定給 VaultSushiFlipToFlip 合約,導致 VaultSushiFlipToFlip 獲取到錯誤的 balanceOf 造成 performanceFee 變成一個非預期的巨大值。

4. 最終鑄造 polyBUNNY 代幣獎勵使用了此非預期的 performanceFee 參數,導致額外鑄造了大量的 polyBUNNY 代幣給攻擊者。

5. 最後攻擊者拋售 polyBUNNY 代幣,歸還閃電貸,獲利走人。

總結

此次攻擊與第一次不同的點在於:並非是預言機被操控導致鑄幣數量錯誤,而是 VaultSushiFlipToFlip 合約獲取在 MiniChefV2 中抵押的抵押品數量時,錯誤地獲取了攻擊者未通過 VaultSushiFlipToFlip 抵押的抵押品數量,導致參數鑄幣的參數異常。最終鑄造出額外的 polyBUNNY 代幣。

參考交易鏈接:

https://polygonscan.com/tx/0x25e5d9ea359be7fc50358d18c2b6d429d27620fe665a99ba7ad0ea460e50ae55

來源鏈接:mp.weixin.qq.com