code4rena-2023-09-centrifuge-m01
[M-01] onlyCentrifugeChainOrigin() can’t require msg.sender equal axelarGateway
Summary
Axelar 브릿지는 Gateway가 직접 수신자 컨트랙트에게 메시지를 전달해주지 않는다. 하지만 코드는 execute 함수를 Gateway가 호출해줄 것으로 가정하고 호출자를 제한한다. 따라서 execute 함수는 호출될 수 없고, 브릿징된 메시지는 실행되지 않을 것이다.
Keyword
bug, logic flaw
Vulnerability
Axelar 브릿지는 목적지 체인의 메시지를 수신하는 컨트랙트를 브릿지 Endpoint가 호출하지 않는다. 보내진 메시지는 Axelar Gateway에 등록되고, 이 메시지를 소비하기 위해서는 대상 컨트랙트의 execute 함수를 직접 콜하거나 가스 비용을 지불하고 자동으로 호출해주는 서비스를 이용해야 한다.
따라서 execute 함수는 Axelar Gateway로부터 호출되지 않는다.
Axelar 브릿지로 넘어온 메시지를 받아서 처리하는 Router 컨트랙트의 execute 함수에서는 onlyCentrifugeChainOrigin modifier로 호출자를 제한한다.
require(msg.sender == address(axelarGateway), "AxelarRouter/invalid-origin")로 호출자가 Axelar Gateway이기를 요구한다. 하지만 Axelar Gateway는 이 함수를 호출해주지 않을 것이다.
function execute(
bytes32 commandId,
string calldata sourceChain,
string calldata sourceAddress,
bytes calldata payload
@> ) public onlyCentrifugeChainOrigin(sourceChain, sourceAddress) {
bytes32 payloadHash = keccak256(payload);
require(
axelarGateway.validateContractCall(commandId, sourceChain, sourceAddress, payloadHash),
"Router/not-approved-by-gateway"
);
gateway.handle(payload);
}
modifier onlyCentrifugeChainOrigin(string calldata sourceChain, string calldata sourceAddress) {
@> require(msg.sender == address(axelarGateway), "AxelarRouter/invalid-origin");
require(
keccak256(bytes(axelarCentrifugeChainId)) == keccak256(bytes(sourceChain)),
"AxelarRouter/invalid-source-chain"
);
require(
keccak256(bytes(axelarCentrifugeChainAddress)) == keccak256(bytes(sourceAddress)),
"AxelarRouter/invalid-source-address"
);
_;
}Impact
router.execute()가 실행될 수 없어 브릿징된 명령이 실행되지 않는다. 프로토콜이 작동하지 않는다.
Mitigation
msg.sender 제한을 삭제한다.
modifier onlyCentrifugeChainOrigin(string calldata sourceChain, string calldata sourceAddress) {
- require(msg.sender == address(axelarGateway), "AxelarRouter/invalid-origin");
require(
keccak256(bytes(axelarCentrifugeChainId)) == keccak256(bytes(sourceChain)),
"AxelarRouter/invalid-source-chain"
);
require(
keccak256(bytes(axelarCentrifugeChainAddress)) == keccak256(bytes(sourceAddress)),
"AxelarRouter/invalid-source-address"
);
_;
}Memo
아마 LayerZero 와 헷갈려서 이렇게 짠 것 같다. LayerZero는 Endpoint가 수신인의 함수를 호출하는 방식이지만 Axelar는 그렇지 않다.
tags: bughunting, centrifuge, smart contract, solidity, bridge, axelar, logic flaw, severity medium