code4rena-2024-08-chakra-h03

[H-03] SettlementSignatureVerifier is missing check for duplicate validator signatures

보고서

Summary

서명을 확인할 때 중복된 서명이 있는지 확인하지 않았다. Solidity와 Cairo 양쪽에 서명 확인 기능이 있었는데 양쪽 모두 이슈가 있었다. 이 취약점으로 인해 한 명의 밸리데이터 만으로 인증하여 잠겨있는 모든 토큰을 꺼내가거나 민팅, 소각할 수 있다.

Keyword

bridge, cross chain, lack of input validation, signature, theft

Vulnerability

Solidity에서, verifyECDSA 에서 서명을 확인할 때 중복된 서명이 있는지 확인하지 않는다. 단지 서명자가 validator로 등록되어 있는지만 확인한다. 이 함수를 호출하는 verify 함수나 verify 를 호출하는 함수 역시 중복된 서명이 있는지 확인하지 않는다. 따라서 validator 한 명의 서명으로도 verify 할 수 있다. Validator는 receive_cross_chain_msg 를 자유롭게 호출하여 토큰을 꺼내가거나 민팅받을 수 있다. 또한 receive_cross_chain_callback 를 호출하여 토큰을 소각시킬 수 있다.

    function verifyECDSA(
        bytes32 msgHash,
        bytes calldata signatures
    ) internal view returns (bool) {
        require(
            signatures.length % 65 == 0,
            "Signature length must be a multiple of 65"
        );
 
        uint256 len = signatures.length;
        uint256 m = 0;
        for (uint256 i = 0; i < len; i += 65) {
            bytes memory sig = signatures[i:i + 65];
            if (
@>              validators[msgHash.recover(sig)] && ++m >= required_validators
            ) {
                return true;
            }
        }
 
        return false;
    }

Cairo에서, check_chakra_signatures 함수에서 서명을 확인할 때, 서명이 중복되었는지는 확인하지 않는다. 따라서 한 명의 Validator 서명 만으로 verify 할 수 있다. Validator는 receive_cross_chain_msg 를 자유롭게 호출하여 토큰을 꺼내가거나 민팅받을 수 있다. 또한 receive_cross_chain_callback 를 호출하여 토큰을 소각 시킬 수 있다.

#[generate_trait]
impl InternalImpl of InternalTrait {
    // validate signatures should > required_validators_num
    // @param message_hash the perdsen hash of message 
    // @param the signatures corresponding to each verifier
    fn check_chakra_signatures(
        self: @ContractState, message_hash: felt252, signatures: Array<(felt252, felt252, bool)>
    ){
        let mut pass_count = 0;
        let mut i = 0;
        loop {
            if i > signatures.len()-1{
                break;
            }
            let (r,s,y) = * signatures.at(i);
            let pub_key: felt252 = recover_public_key(message_hash,r,s,y).unwrap();
@>          if self.chakra_validators_pubkey.read(pub_key) > 0{
@>              pass_count += 1;
            }
            i += 1;
        };
@>      assert(pass_count >= self.required_validators_num.read(), 'Not enough validate signatures');
    }
}

Impact

이 취약점으로 인해 한 명의 밸리데이터 만으로 인증하여 잠겨있는 모든 토큰을 꺼내가거나 민팅, 소각할 수 있다.

Mitigation

Solidity에서, verifyECDSA 에서 서명을 확인한 주소를 기록하고, 중복이 있다면 트랜잭션을 취소 시킨다. Cairo에서, check_chakra_signatures 에서 서명을 확인한 주소를 기록하고, 중복이 있다면 트랜잭션을 취소 시킨다.


tags: bughunting, chakra, smart contract, starknet, cairo, solidity, crypto theft, bridge, cross chain, signature, severity high