一篇文章看懂cosmos重委託漏洞

摘要

Cosmos SDK 在 2019年 5 月底發現存在嚴重安全漏洞,該團隊隨後發佈了補丁,並與全球驗證人共同進行了升級,從收到漏洞報告到修復主網共用了72小時。

攻擊者可利用該漏洞繞過委託金贖回時的鎖定時間。

在介紹漏洞細節之前,先介紹一下cosmos的投票機制。

staking:投票機制

Cosmos中持幣人可以將自己的貨幣委託給validator,當validator出塊時,持幣人獲得收益。
當持幣人遇到了佣金更低、網絡狀態更好的validator,不想繼續委託原來的validator時。
可以unbond之前的validator。這需要等待21天。21天結束之後,委託的貨幣會被返還,然後持幣人就可以委託其他validator了。

redelegation:一鍵更換validator

redelegation功能 使持幣人不用等待21天的unbonding週期,可以立即更換至其他validators。
唯一的限制是21天時間內,最多更換7次validators。
目前 Cosmostation 錢包已經支持redelegation功能。
redelegation截圖

漏洞介紹

Cosmos重委託漏洞,使得持幣人在贖回委託金時,不必再等待21天的時間。
Cosmos 團隊的 Jack Zampolin 分享了一個程序,可以發現那些利用漏洞提前撤回委託的惡意交易。
Jack Zampolin

該漏洞導致7250個Atom代幣被提前贖回,當時每個Atom價值6美元。
截止2019年5月31日,使用上述惡意方法解除委託的 Atoms 大約爲43,500美元。

補丁代碼分析

Cosmos SDK 0.34.6 版本發佈了重委託漏洞的補丁,並在區塊高度 482100 時(大約2019年5月31日早上 10 點)生效。

cosmos重委託漏洞 補丁commit 鏈接如下:
https://github.com/cosmos/cosmos-sdk/commit/80234baf91a15dd9a7df8dca38677b66b8d148c1

代碼修改的重點在於
github.com/cosmos/cosmos-sdk/x/staking/keeper/delegation.go,L585-L638:
Keeper.Undelegate函數
代碼修改
可見Undelegate函數中592行做了一個硬分叉,分叉高度是UndelegatePatchHeight等於482100

在分叉高度前的代碼中,有一處關於completeNow的判斷

if completeNow {
	balance := sdk.NewCoin(k.BondDenom(ctx), returnAmount)
	if !balance.IsZero() {
		if _, err := k.bankKeeper.UndelegateCoins(ctx, delAddr, sdk.Coins{balance}); err != nil {
			return completionTime, err
		}
	}
	return completionTime, nil
}

如果completeNow等於 True,就直接退還委託的貨幣,而無需等待21天。
在Keeper.getBeginInfo函數中,我們發現
要使completeNow == True,需要validator.status == sdk.Unbonded
completeNow=True

不同的completeTime / completeNow

當持幣人想要撤銷對validator的委託時,需要等待completeTime後,委託金纔會返還給持幣人。
對於completeTime,不同情況有不同的值。

  • 如果validator此時是Bonded狀態,贖回委託金需要經歷21天的時間。
  • 如果validator處於UnBonding狀態,持幣人從該validator解綁定需要的鎖定期等於該validator的鎖定期(小於或等於21天)。
  • 如果validator處於UnBonded狀態,則不需要鎖定期,持幣人抵押的股權可立即變回代幣。這也就是上面代碼中提到的validator.status == sdk.UnbondedcompleteNow == True

這樣設計的本意的是,當validator節點因作惡或意外被Jail後,持幣人可以儘快取回抵押的股權,避免造成損失。

漏洞利用方法

攻擊者想要撤銷對validatorA的委託,拿回委託金。但是又不想等待21天的unbonding。
於是攻擊者使用cosmostation錢包提供的redelegation方法,將委託對象立刻轉換爲一個狀態爲Unbonded的validator。
接着再進行undelegate操作,Keeper.Undelegate函數收到completeNow == True
便調用k.bankKeeper.UndelegateCoins立刻歸還了委託金。
攻擊者便可以繞過鎖定期限制,瞬間贖回委託金。

漏洞危害

漏洞不會造成用戶的財產損失,但是可以讓攻擊者繞過21天的委託金鎖定。
這會讓cosmos設計的經濟模型變得不穩定,破壞交易的公平。

總結

cosmos重委託漏洞的本質,是新功能redelegation和舊功能unbonded立刻贖回機制,兩者的邏輯出現衝突。
在開發過程中,開發人員需要對新功能可能涉及到的舊代碼有充分的瞭解。

參考資料

Cosmos staking module
Node A-Team 分析文章 Cosmos Hub Security Vulnerability regarding Redelegation and Unbonding
Cosmos攻略:Staking 新手實用工具指南
cosmos源碼分析之四Staking模塊
jessysaurusrex 記錄的幾個cosmos 1day
Cosmos的解綁定漏洞分析

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章