code4rena-2024-08-chakra-m02
[M-02] Missing ERC20Method validation at destination allows non-transfer tx to be handled as transfers
Summary
Cairo 구현과는 다르게, Solidity에서는 전달 받은 메시지에서 method_id를 확인하지 않았다. 이는 크로스체인 브리지의 무결성을 훼손하고 의도하지 않은 조작을 가할 수 있게 한다.
Keyword
bridge, cross chain, lack of input validation
Vulnerability
Cairo 핸들러는 크로스 체인 메시지를 수신하면 메시지를 이를 디코딩하여 적절한 지 확인한다.
payload_type이 ERC20 인지 확인한다.method_id가 Transfer 함수인지 확인한다.
fn receive_cross_chain_msg(ref self: ContractState, cross_chain_msg_id: u256, from_chain: felt252, to_chain: felt252,
from_handler: u256, to_handler: ContractAddress, payload: Array<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 message :Message= decode_message(payload);
let payload_type = message.payload_type;
@> assert(payload_type == PayloadType::ERC20, 'payload type not erc20');
let payload_transfer = message.payload;
@> let transfer = decode_transfer(payload_transfer);
@> assert(transfer.method_id == ERC20Method::TRANSFER, 'ERC20Method must TRANSFER');
...
}하지만 Solidity의 핸들러는 payload_type만 확인하고, method_id는 확인하지 않는다.
function receive_cross_chain_msg(
uint256 /**txid */,
string memory from_chain,
uint256 /**from_address */,
uint256 from_handler,
PayloadType payload_type,
bytes calldata payload,
uint8 /**sign type */,
bytes calldata /**signaturs */
) external onlySettlement returns (bool) {
// from_handler need in whitelist
if (is_valid_handler(from_chain, from_handler) == false) {
return false;
}
bytes calldata msg_payload = MessageV1Codec.payload(payload);
require(isValidPayloadType(payload_type), "Invalid payload type");
@> if (payload_type == PayloadType.ERC20) {
// Cross chain transfer
{
// Decode transfer payload
@> ERC20TransferPayload memory transfer_payload = codec
.deocde_transfer(msg_payload);
if (mode == SettlementMode.MintBurn) {
_erc20_mint(
AddressCast.to_address(transfer_payload.to),
transfer_payload.amount
);
return true;
}
...Impact
잘못된 method_id 메시지를 정상으로 통과시킬 수 있다.
Mitigation
Solidity 구현에서도 method_id 를 확인한다.
Memo
현재 사용되는 method_id는 Transfer 뿐이므로 Low라고 이의가 있었지만, 노드가 오딧 범위가 아니기 때문에 좀 더 관대하게 취약점으로 인정한 것 같다.
tags: bughunting, chakra, smart contract, starknet, solidity, bridge, cross chain, severity medium, lack-of-input-validation-vul