摘要
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功能。
漏洞介紹
Cosmos重委託漏洞,使得持幣人在贖回委託金時,不必再等待21天的時間。
Cosmos 團隊的 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
不同的completeTime / completeNow
當持幣人想要撤銷對validator的委託時,需要等待completeTime後,委託金纔會返還給持幣人。
對於completeTime,不同情況有不同的值。
- 如果validator此時是Bonded狀態,贖回委託金需要經歷21天的時間。
- 如果validator處於UnBonding狀態,持幣人從該validator解綁定需要的鎖定期等於該validator的鎖定期(小於或等於21天)。
- 如果validator處於UnBonded狀態,則不需要鎖定期,持幣人抵押的股權可立即變回代幣。這也就是上面代碼中提到的
validator.status == sdk.Unbonded
則completeNow == 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的解綁定漏洞分析