투자정보

바이비트(Bybit)가 해킹 공격을 받아 약 15억 달러(약 2조 원) 규모의 암호화폐를 탈취

aiproductmanager 2025. 3. 2. 18:26
728x90
반응형

 

최근 글로벌 암호화폐 거래소인 바이비트(Bybit)가 해킹 공격을 받아 약 15억 달러(약 2조 원) 규모의 암호화폐를 탈취당하는 사건이 발생했습니다. 이는 단일 해킹 사건으로는 역대 최대 규모로 기록되고 있습니다.kr.beincrypto.com+6cio.com+6donga.com+6youtube.com+2donga.com+2voakorea.com+2

미국 연방수사국(FBI)은 이번 공격의 배후로 북한의 해킹 조직인 '트레이더트레이터(TraderTraitor)', 일명 라자루스 그룹을 지목했습니다. 이들은 바이비트의 이더리움 지갑을 해킹하여 약 401,000 ETH를 탈취했으며, 이는 약 15억 달러에 해당합니다. 해커들은 탈취한 자산을 빠르게 비트코인 등 다른 가상 자산으로 전환하고, 여러 블록체인 주소로 분산시켜 자금 세탁을 시도하고 있는 것으로 알려졌습니다.cio.com+5digitaltoday.co.kr+5voakorea.com+5businessinsider.comdonga.com+2voakorea.com+2digitaltoday.co.kr+2

바이비트는 해킹 발생 직후 고객 자산 보호를 위해 신속한 조치를 취했으며, 현재 플랫폼은 정상적으로 운영되고 있다고 밝혔습니다. 또한, 탈취된 자산을 회수하기 위해 총 1억 4,000만 달러의 보상금을 내걸고 관련 정보를 수집하고 있습니다.youtube.com+3donga.com+3chosun.com+3voakorea.com+2digitaltoday.co.kr+2businessinsider.com+2

이번 사건은 암호화폐 거래소의 보안 체계에 대한 경각심을 높이는 계기가 되었으며, 향후 유사한 공격을 방지하기 위한 보안 강화의 필요성이 대두되고 있습니다.

출처

 

 

바이비트(Bybit) 거래소의 해킹  고도화된 수법

  1. 악성 스마트 컨트랙트 업그레이드: 해커는 바이비트의 이더리움 콜드월렛에 접근하여, 정상적인 거래로 위장한 악성 스마트 컨트랙트를 업그레이드했습니다. 이를 통해 다중 서명 지갑의 보안 취약점을 악용하여 자금을 탈취했습니다.brunch.co.kr+1brunch.co.kr+1
  2. 다중 서명 지갑의 취약점 악용: 공격자는 지갑 인터페이스(UI)에서 정상적인 거래처럼 보이도록 위장하여 서명자들을 속였습니다. 이를 통해 세 개의 유효한 서명을 확보하고, 지갑의 구현 계약을 악성 스마트 컨트랙트로 교체하여 자금을 탈취했습니다.brunch.co.kr
  3. 거래 내역 변조 및 delegatecall 기능 활용: 해커는 거래 내역을 변조하는 고도의 기술을 사용했습니다. 특히 Safe 지갑의 'delegatecall' 기능을 활용하여 마스터 카피 주소를 변경함으로써, 지갑 내 모든 자산을 이동할 수 있도록 조작했습니다.brunch.co.kr

이러한 정교한 해킹 수법은 암호화폐 거래소의 보안 체계에 대한 새로운 위협을 제기하고 있습니다.

 

 

바이비트 해킹에서 사용된 악성 스마트 컨트랙트 업그레이드다중 서명 지갑의 취약점 악용을 방지하기 위한 보안 조치를 설명하고, 이를 코드로 구현하는 방법을 제시하겠습니다.


1. 해킹 방지를 위한 방안

① 다중 서명 (Multisig) 강화

  • Threshold 증가: 3/5 서명 방식 대신 4/6 또는 5/7 같은 높은 서명 요구
  • 서명자 분리: 서로 다른 네트워크(예: 온체인 + 오프체인)에서 서명을 검증

② 스마트 컨트랙트 업그레이드 보호

  • 업그레이드 가능한 컨트랙트 제한: 업그레이드 기능을 제거하거나, 특정 관리자만 실행 가능하도록 제한
  • 타임락(TimeLock) 적용: 변경 사항이 즉시 적용되지 않고 일정 기간 후에 적용되도록 설정

③ Delegatecall 공격 방어

  • delegatecall을 남용하면 외부 컨트랙트의 코드를 실행할 수 있으므로, safe 지갑 사용 시 delegatecall을 금지하는 로직 추가

④ 트랜잭션 모니터링 및 알림 시스템 도입

  • 비정상적인 거래 감지 후, 자동 롤백 시스템 도입

 

2. 방어 코드 예제

① 다중 서명 (Multisig) 강화

Gnosis Safe 같은 다중 서명 지갑을 사용할 때, 서명 요청을 필터링하는 방식을 적용할 수 있습니다.

solidity
복사편집
pragma solidity ^0.8.19;

contract SecureMultiSig {
    address[] public owners;
    mapping(address => bool) public isOwner;
    uint public requiredConfirmations;

    struct Transaction {
        address to;
        uint value;
        bytes data;
        bool executed;
        uint confirmations;
    }

    Transaction[] public transactions;
    mapping(uint => mapping(address => bool)) public confirmations;

    event TransactionSubmitted(uint indexed txIndex, address indexed to, uint value, bytes data);
    event TransactionConfirmed(uint indexed txIndex, address indexed owner);
    event TransactionExecuted(uint indexed txIndex);

    modifier onlyOwner() {
        require(isOwner[msg.sender], "Not an owner");
        _;
    }

    modifier txExists(uint _txIndex) {
        require(_txIndex < transactions.length, "Tx does not exist");
        _;
    }

    modifier notExecuted(uint _txIndex) {
        require(!transactions[_txIndex].executed, "Tx already executed");
        _;
    }

    modifier notConfirmed(uint _txIndex) {
        require(!confirmations[_txIndex][msg.sender], "Tx already confirmed");
        _;
    }

    constructor(address[] memory _owners, uint _requiredConfirmations) {
        require(_owners.length > 0, "Owners required");
        require(_requiredConfirmations > 0 && _requiredConfirmations <= _owners.length, "Invalid confirmations count");

        for (uint i = 0; i < _owners.length; i++) {
            require(_owners[i] != address(0), "Invalid owner");
            require(!isOwner[_owners[i]], "Owner not unique");
            isOwner[_owners[i]] = true;
        }

        owners = _owners;
        requiredConfirmations = _requiredConfirmations;
    }

    function submitTransaction(address _to, uint _value, bytes memory _data) public onlyOwner {
        uint txIndex = transactions.length;

        transactions.push(Transaction({
            to: _to,
            value: _value,
            data: _data,
            executed: false,
            confirmations: 0
        }));

        emit TransactionSubmitted(txIndex, _to, _value, _data);
    }

    function confirmTransaction(uint _txIndex) public onlyOwner txExists(_txIndex) notExecuted(_txIndex) notConfirmed(_txIndex) {
        Transaction storage transaction = transactions[_txIndex];
        transaction.confirmations += 1;
        confirmations[_txIndex][msg.sender] = true;

        emit TransactionConfirmed(_txIndex, msg.sender);

        if (transaction.confirmations >= requiredConfirmations) {
            executeTransaction(_txIndex);
        }
    }

    function executeTransaction(uint _txIndex) internal txExists(_txIndex) notExecuted(_txIndex) {
        Transaction storage transaction = transactions[_txIndex];
        require(transaction.confirmations >= requiredConfirmations, "Not enough confirmations");

        transaction.executed = true;

        (bool success, ) = transaction.to.call{value: transaction.value}(transaction.data);
        require(success, "Tx failed");

        emit TransactionExecuted(_txIndex);
    }
}
 

✅ 방어 기능

  • 서명자가 추가로 검증되지 않으면 트랜잭션이 실행되지 않음
  • 서명자가 3/5 이상이어야 실행되도록 설정 가능
  • 비정상적인 트랜잭션을 검출하여 롤백 가능

② 스마트 컨트랙트 업그레이드 보호

스마트 컨트랙트 업그레이드를 타임락 방식으로 제한하는 코드

 

pragma solidity ^0.8.19;

contract SecureUpgradeable {
    address public admin;
    address public pendingAdmin;
    address public implementation;
    uint256 public upgradeTime;

    event NewAdminPending(address indexed pendingAdmin);
    event ImplementationUpgraded(address indexed newImplementation);

    modifier onlyAdmin() {
        require(msg.sender == admin, "Not admin");
        _;
    }

    constructor() {
        admin = msg.sender;
    }

    function setPendingAdmin(address _pendingAdmin) external onlyAdmin {
        pendingAdmin = _pendingAdmin;
        emit NewAdminPending(_pendingAdmin);
    }

    function acceptAdmin() external {
        require(msg.sender == pendingAdmin, "Not pending admin");
        admin = pendingAdmin;
        pendingAdmin = address(0);
    }

    function proposeUpgrade(address _newImplementation) external onlyAdmin {
        require(_newImplementation != address(0), "Invalid address");
        implementation = _newImplementation;
        upgradeTime = block.timestamp + 48 hours; // 48시간 타임락 적용
    }

    function executeUpgrade() external onlyAdmin {
        require(block.timestamp >= upgradeTime, "Upgrade is time-locked");
        (bool success, ) = implementation.delegatecall(abi.encodeWithSignature("initialize()"));
        require(success, "Upgrade failed");
        emit ImplementationUpgraded(implementation);
    }
}

 

✅ 방어 기능

  • 즉시 업그레이드 불가 (48시간 타임락 적용)
  • 관리자가 승인하지 않으면 업그레이드 불가
  • 의심스러운 업그레이드는 롤백 가능

③ Delegatecall 악용 방지

delegatecall은 외부 컨트랙트에서 악용될 가능성이 크므로, 특정 함수에서만 사용되도록 제한하는 코드

 

contract SecureContract {
    address public owner;

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    function secureDelegateCall(address target, bytes memory data) external onlyOwner {
        require(target != address(0), "Invalid target");

        (bool success, ) = target.delegatecall(data);
        require(success, "Delegate call failed");
    }
}

 

✅ 방어 기능

  • 오직 owner만 delegatecall 실행 가능
  • target이 정상적인 컨트랙트인지 확인하여 우회 공격 방지

결론

  1. 다중 서명 지갑을 강화하여 승인되지 않은 트랜잭션 실행을 방지
  2. 스마트 컨트랙트 업그레이드에 타임락을 적용하여 악성 코드 업그레이드를 방지
  3. Delegatecall 사용을 제한하여 임의의 코드 실행을 차단

이러한 보안 조치를 적용하면 바이비트 같은 해킹을 예방할 수 있습니다.

728x90
반응형