code4rena-2024-08-chakra-h12

[H-12] Handler’s receive_cross_chain_callback() will always set the tx_status to SETTLED on source chain & burn the tokens (MintBurn Mode) even when the msg fails on destination

보고서

Summary

Starknet 의 MintBurn 모드 핸들러는 요청을 받을 때 토큰을 컨트랙트에 전송해두고, 목적지 체인의 콜백 메시지를 받은 후 이를 소각한다. 그런데 콜백에서 보낸 성공 여부를 확인하지 않고 무조건 소각하여 문제가 되었다.

Keyword

logic flaw, cross chain, bridge

Vulnerability

Starknet 의 MintBurn 모드 핸들러는 요청을 받을 때 토큰을 컨트랙트에 전송해두고, 목적지 체인의 콜백 메시지를 받은 후 이를 소각한다. 그런데 receive_cross_chain_callback 에서 목적지 체인에서의 성공 여부(cross_chain_msg_status)와 상관없이 항상 토큰을 소각한다. 또한 cross_chain_msg_status 와는 상관 없이 CrossChainTxStatus::SETTLED 상태를 저장하여 성공 처리 한다.

fn receive_cross_chain_callback(ref self: ContractState, cross_chain_msg_id: felt252, from_chain: felt252, to_chain: felt252,
from_handler: u256, to_handler: ContractAddress, cross_chain_msg_status: u8) -> bool{
    assert(to_handler == get_contract_address(),'error to_handler');
 
    assert(self.settlement_address.read() == get_caller_address(), 'not settlement');
 
    assert(self.support_handler.read((from_chain, from_handler)) && 
            self.support_handler.read((to_chain, contract_address_to_u256(to_handler))), 'not support handler');
 
    let erc20 = IERC20MintDispatcher{contract_address: self.token_address.read()};
@>  if self.mode.read() == SettlementMode::MintBurn{
@>      erc20.burn_from(get_contract_address(), self.created_tx.read(cross_chain_msg_id).amount);
    }
    let created_tx = self.created_tx.read(cross_chain_msg_id);
    self.created_tx.write(cross_chain_msg_id, CreatedCrossChainTx{
        tx_id: created_tx.tx_id,
        from_chain: created_tx.from_chain,
        to_chain: created_tx.to_chain,
        from:created_tx.from,
        to:created_tx.to,
        from_token: created_tx.from_token,
        to_token: created_tx.to_token,
        amount: created_tx.amount,
@>      tx_status: CrossChainTxStatus::SETTLED
    });
 
    return true;
}

Impact

토큰을 소각하면 안 되는 상황에 토큰을 소각하고, 잘못된 상태를 저장한다.

Mitigation

cross_chain_msg_status 를 확인하여 목적지 체인에서 성공했을 때만 토큰을 소각하거나 CrossChainTxStatus::SETTLED 상태를 저장하도록 한다.


tags: bughunting, chakra, smart contract, starknet, cairo, bridge, cross chain, logic flaw, severity high