code4rena-2024-08-chakra-h05
[H-05] settlement.cairo doesn’t process callback correctly leading to CrossChainMsgStatus marked as SUCCESS even if it failed on destination chain
Summary
목적지 체인에서의 성공 여부를 저장/사용해야 하는 곳에 잘못된 값을 기록하였다. 목적지 체인에서 실패했더라도 성공으로 표시될 수 있다. 브릿지이기 때문에 잘못된 상태나 이벤트를 발생하는 것이 크리티컬한 이슈로 취급되었다.
Keyword
bridge, cross chain, wrong state, event
Vulnerability
크로스체인으로 메시지를 보낸 후 목적지 체인에서 처리, 처리 결과를 다시 출발지 체인의 receive_cross_chain_callback 를 통해 전달한다. 파라미터 cross_chain_msg_status는 목적지 체인에서의 성공 여부를 나타낸다.
그런데 cross_chain_msg_status 값은 created_tx에 저장되지 않는다. created_tx에 저장되는 값은 handler.receive_cross_chain_callback의 리턴값이며, 이 함수가 실패하지 않는다면 함상 true를 리턴한다. 이 함수가 실패한다면 트랜잭션이 취소되므로 false를 리턴하지 않는다.
따라서 실제로 목적지에서 성공했는지 여부를 저장하지 않고, 모든 실행 결과는 SUCCESS 상태로 저장된다.
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,
sign_type: u8,
signatures: Array<(felt252, felt252, bool)>,
) -> bool {
...
let mut message_hash_temp: felt252 = LegacyHash::hash(from_chain, (cross_chain_msg_id, to_chain, from_handler, to_handler));
let message_hash_final:felt252 = LegacyHash::hash(message_hash_temp, cross_chain_msg_status);
self.check_chakra_signatures(message_hash_final, signatures);
let handler = IHandlerDispatcher{contract_address: to_handler};
@> let success = handler.receive_cross_chain_callback(cross_chain_msg_id, from_chain, to_chain, from_handler, to_handler , cross_chain_msg_status);
let mut state = CrossChainMsgStatus::PENDING;
@> if success{ // handler.receive_cross_chain_callback 가 실패하지 않는다면 항상 true 리턴
@> state = CrossChainMsgStatus::SUCCESS;
}else{
@> state = CrossChainMsgStatus::FAILED;
}
self.created_tx.write(cross_chain_msg_id, CreatedTx{
tx_id:cross_chain_msg_id,
@> tx_status:state,
from_chain: to_chain,
to_chain: from_chain,
from_handler: to_handler,
to_handler: from_handler
});
self.emit(CrossChainResult {
cross_chain_settlement_id: cross_chain_msg_id,
from_address: get_tx_info().unbox().account_contract_address,
from_chain: to_chain,
from_handler: to_handler,
to_chain: from_chain,
to_handler: from_handler,
@> cross_chain_msg_status: state,
});
return true;
}Impact
목적지 체인에서의 성공 여부를 저장/사용해야 하는 곳에 잘못된 값이 기록된다. 목적지 체인에서 실패했더라도 성공으로 표시될 수 있다.
Mitigation
handler.receive_cross_chain_callback 가 성공했을 시 목적지 체인에서의 상태를 기록한다.
let success = handler.receive_cross_chain_callback(cross_chain_msg_id, from_chain, to_chain, from_handler, to_handler , cross_chain_msg_status);
let mut state = CrossChainMsgStatus::PENDING;
if success{
- state = CrossChainMsgStatus::SUCCESS;
+ state = cross_chain_msg_status;
}else{
state = CrossChainMsgStatus::FAILED;
}tags: bughunting, chakra, smart contract, starknet, cairo, bridge, cross chain, severity high, wrong state, cairo event