背景資訊
攻擊交易:https://app.blocksec.com/explorer/tx/eth/0x9a1d02a7cb9fef11fcec2727b1f9e0b01bc6bcf5542f5b656c84d6400a1b4604
漏洞合約:https://etherscan.io/address/0x8a30d684b1d3f8f36b36887a3deca0ef2a36a8e3#code
LockedStaking
合約提供質押功能,使用者呼叫 stake
函式質押時會根據質押時長立即計算收益 yield
,並且記錄在使用者的收益 user.yield
上。等到該筆質押的時間過後,使用者可以呼叫 unStake
函式取回本金和收益。
Trace 分析
攻擊者不斷用同一筆資金進行 start
和 unStake
操作,攻擊者建立新合約 strat 存入 500000 VSTR,然後透過 0x1f2c 合約 呼叫 unStake
取回 520000 VSTR。
start
操作就是透過新建立的合約進行 stake
漏洞分析
問題出在 LockedStaking
合約的 unStake
函式,unStake
函式對質押的狀態檢查與更新存在問題,導致在使用者的質押到期後,可以無限次進行取款。
require
檢查的user.stakeAmount
引數,在unstake
操作後不更新- 在
unstake
操作後更新的user.isActive
引數,卻不檢查。
那麼攻擊者可以無限次 unstake
來獲取 VSTR,為什麼還需要建立新合約進行 stake
操作呢?
因為在 unstake
的時候會更新 data.totalStaked -= stakeAmount;
,如果不建立新合約進行 stake
操作增加 data.totalStaked
的值,就會發生下溢位。