code4rena-2024-08-chakra-h09
[H-09] Inconsistent Handler Validation Behavior in Cairo ERC20Handler’s Cross-Chain Callback
Summary
Solidity 구현체에서는 핸들러가 유효하지 않을 때, 실패 상태를 기록하고 종료한다. Cairo 구현체에서는 핸들러가 유효하지 않을 때 트랜잭션을 취소시킨다. 체인별 동작의 불일치는 체인 별 상태의 불일치를 만들 것이다. 또한, Cairo 에서는 Solidity 구현과는 다르게 오류를 핸들링 할 수 없다.
Keyword
bridge, cross chain, business logic vul
Vulnerability
ERC20Handler의 Cairo 구현체에서 receive_cross_chain_callback 함수는 핸들러를 검증하기 위해 assert 문을 사용한다. 이로 인해 핸들러가 유효하지 않거나 허용 리스트에서 제거된 경우 트랜잭션이 취소된다. 이 동작은 Solidity 구현체와 다르다. Solidity 구현체는 유효하지 않은 핸들러에 대해 false를 반환한다.
Cairo 구현은 다음과 같다. 핸들러가 유효하지 않은 경우 트랜잭션을 취소한다. 트랜잭션은 현재 상태(대부분 Pending)로 유지된다.
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');
// ... rest of the function
}Solidity 구현은 다음과 같다. 핸들러가 유효하지 않은 경우 트랜잭션을 취소하지 않고 상태를 기록한다.
function receive_cross_chain_callback(
uint256 txid,
string memory from_chain,
uint256 from_handler,
CrossChainMsgStatus status,
uint8 /* sign_type */,
bytes calldata /* signatures */
) external onlySettlement returns (bool) {
@> if (is_valid_handler(from_chain, from_handler) == false) {
return false;
}
// ... rest of the function
}
function processCrossChainCallback(
uint256 txid,
string memory from_chain,
uint256 from_handler,
address to_handler,
CrossChainMsgStatus status,
uint8 sign_type,
bytes calldata signatures
) internal {
require(
create_cross_txs[txid].status == CrossChainMsgStatus.Pending,
"Invalid transaction status"
);
if (
@> ISettlementHandler(to_handler).receive_cross_chain_callback(
txid,
from_chain,
from_handler,
status,
sign_type,
signatures
)
) {
create_cross_txs[txid].status = status;
} else {
@> create_cross_txs[txid].status = CrossChainMsgStatus.Failed;
}
}Impact
이 취약점은 다음과 같은 문제를 초래할 수 있다.
- Cairo 구현에서 거래가 무기한으로 대기 상태에 머물 수 있음
- 다양한 체인 구현 간 거래 상태의 불일치
- 크로스체인 운영의 잠재적 차단
- 무효한 핸들러 시나리오의 처리 및 복구 어려움
Mitigation
Cairo 구현체를 Solidity 구현체와 동일하게 변경한다. 핸들러가 유효하지 않을 때 트랜잭션을 취소하지 말고 상태를 기록한다.
Memo
단순히 두 버전의 구현체가 다른 것이 취약점이 될 수 있나? 이런 이슈는 저지를 타는 것 같으니 일단 제출하는 게 나은 것 같다.
tags: bughunting, chakra, smart contract, starknet, cairo, bridge, cross chain, severity high, business-logic-vul