Hacking Smart Contract Solidity ブロックチェーン

[Solidity-Bug Bounty] 悪意のあるコードを隠す方法を1からわかりやすく解説

かるでね

こんにちは!CryptoGamesというブロックチェーンゲーム企業でエンジニアをしているかるでねです!
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

このブログ以外でも情報発信しているので、よければ他の記事も見ていってください。

今回はスマートコントラクトにおいて、「悪意のあるコードを隠す方法とその対処法」について紹介していきます!

仕組みは意外と単純ですが、注意しないと資金の喪失などにも繋がりかねないのでこの記事でしっかり学んでいってください。

Solidityスキルを1段階あげたい方やバグ・バウンティに参加したいバグハンターを目指している方は必須の知識となるので、この記事で学んでいってください。

バグ・バウンティが何かわからない人は以下の記事を読んでください。

悪意のあるコードを隠す方法

Solidityでは「悪意のあるコードを隠す」を隠すことができてしまいます。

正確に言うと「悪意のある外部コントラクト」を隠すことができます。

悪意のある外部コントラクトを隠すことで、ユーザーや開発者が予想しない動作を引き起こすことができてしまい、資金の喪失につながります。

仕組みとしては単純なので次章で実際にコードを見せながら確認していきましょう!

悪のあるコードを隠す

前章では「悪意のあるコードを隠す」とはどういったことなのかについて解説してきました。

この章では実際に「悪意のあるコードを隠す」を隠していきたいと思います。

コード解説

CallContract

contract CallContract {
    SafeContract safeContract;

    constructor(address _safeContract) {
        safeContract = SafeContract(_safeContract);
    }

    function log() public payable {
        safeContract.log();
    }
}

SafeContractのアドレスを受け取り、SafeContract内のlog関数を呼び出すコントラクトです。

SafeContract

contract SafeContract {
    string public message;

    function log() public {
        message = "safe!!!";
    }
}

log関数が呼ばれると、message変数に「safe!!!」と言う文字列が格納されます。

MaliciousContract

contract MaliciousContract {
    string public message;

    function log() public {
        message = "Malicious!!!";
    }
}

log関数が呼ばれると、message変数に「Malicious!!!」と言う文字列が格納されます。

実行

では早速実行していきましょう!

CallContractをデプロイするときに、SafeContractのアドレスではなく、MaliciousContractのアドレスを渡しています。

その結果CallContractlog関数を実行するとMaliciousContractlog関数が呼ばれてしまっています。

当たり前じゃね?」と思う方もいると思いますが、動作自体は当たり前なのですがコードを見る際に意外と見落とされがちなポイントのため注意が必要です。

今回のようにコード上ではSafeContractを使用しているように見える場面でも、実はコントラクトアドレスがSafeContractではなく別の悪意あるコントラクトである可能性があります。

そのコントラクト内の関数を実行したことにより、自分の資金が悪意あるユーザーの手に渡ってしまうことも起こりえます。

Etherscanでも悪意あるコード自体は表示されず、手がかりはコントラクトアドレスのみになります。

コード全体

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.13;

contract CallContract {
    SafeContract safeContract;

    constructor(address _safeContract) {
        safeContract = SafeContract(_safeContract);
    }

    function log() public payable {
        safeContract.log();
    }
}

contract SafeContract {
    string public message;

    function log() public {
        message = "safe!!!";
    }
}

contract MaliciousContract {
    string public message;

    function log() public {
        message = "Malicious!!!";
    }
}

対処法

ではどのようにすれば悪意ある外部コントラクトを呼んでいるか確認するのかというと、実際にEtherscanなどで外部コントラクのアドレスを調べ、悪意あるコードを実行しようとしていないか調査する必要があります。

開発者やリサーチャーでない限りコードを実際に見ることはないと思うので、最低限自分が使用するアプリやサービスが監査を受けているかなどを見ておくと良いです。

スマートコントラクトの監査とは、スマートコントラクトのセキュリティ専門企業やバグバウンティコンテストなどで脆弱性がないか調査してもらうことです。

バグバウンティについてよくわからない方は以下を参考にしてください。

最後に

今回はスマートコントラクトにおいて、「悪意のあるコードを隠す方法とその対処法」について紹介してきました。

いかがだったでしょうか?

普段よく使用しているものでもしっかり注意する必要があると言うことが伝われば嬉しいです!

もし何か質問などがあれば以下のTwitterなどから連絡ください!

普段はSolidityやブロックチェーン、Web3についての情報発信をしています。

Twiiterでは気になった記事などを共有しているので、ぜひフォローしてくれると嬉しいです!

参考

-Hacking, Smart Contract, Solidity, ブロックチェーン
-, ,