こんにちは!スマートコントラクトの開発に挑戦されている皆さん、日々のコーディングお疲れ様です。
ブロックチェーンの世界では、一度デプロイ(公開)してしまったプログラムは、原則として後から修正できません。現実世界で言うなら、「鍵をかけ忘れたまま、二度と開かない自動ドアの家を建てる」ようなものです。泥棒が入り放題の状態で家が完成してしまうのを防ぐために、私たちは何重もの防犯対策を講じる必要があります。
今回は、新人の開発者さんやセキュリティに初めて触れる方に向けて、自動でコードの欠陥を見つけてくれる「静的解析ツール」の活用法と、それを日々の開発に組み込むワークフローを優しく紐解いていきます。一歩ずつ、一緒に学んでいきましょう!
—
1. なぜスマートコントラクトのセキュリティは難しいのか?
ブロックチェーン上で動くスマートコントラクトは、お金や重要な資産を直接扱います。通常のWebアプリであれば、バグを見つけたら慌ててパッチ当て(修正プログラムの適用)をすれば済みますが、ブロックチェーンの世界ではそれが許されません。
家の鍵の例え話で考えてみましょう
皆さんが新しく家を建てたとします。
- 通常のWeb開発:鍵の閉め忘れに気づいたら、後から鍵屋さんを呼んで新しい鍵に交換できますよね。
- スマートコントラクト開発:一度家が完成して鍵を挿した瞬間、その鍵穴はコンクリートで固められ、二度と交換できません。もし泥棒の抜け道(脆弱性)が隠れていたら、世界中の泥棒からいつでも資産を盗まれてしまいます。
だからこそ、家を建てる前の「設計図の段階」で、プロの泥棒(攻撃者)の視点になって徹底的に欠陥をチェックする必要があるのです。そのチェックを人間ではなく、コンピュータに自動でやってもらうのが「静的解析ツール」になります。
—
2. 頼れる相棒:SlitherとMythrilの使い分け
スマートコントラクトの自動解析ツールとして、業界でデファクトスタンダードとなっているのが Slither(スリザー) と Mythril(ミスリル) です。この2つの違いを、身近な防犯グッズに例えてみましょう。
Slither(スリザー)=「自動ホームセキュリティのセンサー」
- 特徴:とにかく動作が高速で、コードをサッとスキャンして「ここに危険な隙間がありますよ」と大量の警報を鳴らしてくれます。
- 得意なこと:変数の初期化忘れ、古い書き方の検出、アクセス制御の不備など、よくある「うっかりミス」を秒速で見つけます。
- いつ使う?:コードを書くたびに、毎分・毎秒のように動かしてチェックするのに最適です。
Mythril(ミスリル)=「専門のセキュリティ調査員による徹底的な侵入テスト」
- 特徴:仮想的なシミュレーション(シンボリック実行)を行い、「もし攻撃者がこの順番で操作したら、金庫を開けられてしまうか?」を深く推理します。
- 得意なこと:複雑なロジックの裏をかいた高度な攻撃(リエントランシー攻撃など)の検知。
- いつ使う?:コードが完成し、本番に出す前の最終チェックとしてじっくり時間をかけて動かします。
—
3. 実践!Slitherでコントラクトを診断してみよう
それでは実際に、Slitherを使って脆弱性を検知するハンズオンをやってみましょう。今回は、わざとセキュリティ上の欠陥(古いSolidityの書き方や、誰でも引き出せてしまう危険な関数)を含んだコントラクトを用意しました。
脆弱性のあるサンプルコード
以下のコードを VulnerableBank.sol という名前で保存してみましょう。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// 【危険な例】アクセス制御が甘い銀行コントラクト
contract VulnerableBank {
mapping(address => uint256) public balances;
// 預金機能
function deposit() public payable {
balances[msg.sender] += msg.value;
}
// 引き出し機能(誰でも他人の残高を引き出せてしまう深刻なバグがあります)
function withdraw(address target, uint256 amount) public {
require(balances[target] >= amount, "Insufficient balance");
// 残高の更新が送金より後に行われている(リエントランシーの危険性)
(bool success, ) = msg.sender.call{value: amount}("");
require(success, "Transfer failed");
balances[target] -= amount;
}
}
Slitherの実行コマンド
Python環境が整っていれば、ターミナルで以下のコマンドを実行するだけでSlitherを動かせます。
# Slitherがインストールされていない場合は pip でインストールします
pip install slither-analyzer
# 先ほどのコントラクトに対して静的解析を実行します
slither VulnerableBank.sol
実行すると、コンソール上に赤や黄色で「Warning」や「Optimization」といった警告メッセージがずらっと表示されます。Slitherは、人間が見落としがちな「危険な書き方」をズバッと指摘してくれるのです。
—
4. 泥棒を入らせない!CI/CDパイプラインへの組み込み
「ツールが便利なのは分かったけれど、毎回手動でコマンドを打つのは忘れそう……」ですよね。その通りです!人間の記憶や習慣はあてになりません。
そこで、開発者がコードをGitHubにプッシュ(保存)した瞬間に、自動でSlitherが動き出してチェックしてくれる仕組み(CI/CDパイプライン)を作りましょう。これは、玄関に自動防犯カメラを設置するようなものです。
GitHub Actionsの設定ファイル
プロジェクトのルートディレクトリに .github/workflows/security-check.yml というファイルを作成し、以下の設定を記述します。
name: Smart Contract Security Check
# GitHubにコードがプッシュされた時や、プルリクエストが作られた時に自動で発動します
on:
push:
branches: [ "main", "develop" ]
pull_request:
branches: [ "main", "develop" ]
jobs:
slither-analysis:
runs-on: ubuntu-latest
steps:
# 1. 自分のコードをサーバーにダウンロードします
- name: Checkout repository
uses: actions/checkout@v3
# 2. Pythonの環境を準備します
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
# 3. Slitherとその依存関係をインストールします
- name: Install Slither
run: |
python -m pip install --upgrade pip
pip install slither-analyzer
# 4. Slitherを実行して脆弱性をスキャンします
# (もし重大な脆弱性が見つかった場合、このジョブが失敗してプッシュをブロックします)
- name: Run Slither Analysis
run: slither . --fail-none
この設定をしておけば、うっかりセキュリティ事故につながるコードを書いたままチームの共有スペース(mainブランチなど)にコードを混ぜようとしても、GitHubが「ちょっと待った!」と自動でエラーを出して止めてくれます。
—
5. まとめと次のステップ
今回は、スマートコントラクトを守るための静的解析ツール(Slither / Mythril)の基本と、CI/CDを使った自動化のワークフローについて解説しました。
- Slitherで日々のコーディング中の「うっかりミス」を秒速チェックする。
- GitHub Actionsなどの自動化ツールを使い、人間がチェックを忘れない仕組みを作る。
セキュリティ対策は、「一度やって終わり」のイベントではなく、日々の開発に組み込む「習慣」です。最初は難しく感じるかもしれませんが、自動化の仕組みを一度整えてしまえば、あなたの強力な味方になってくれます。
一歩ずつ、安全で信頼されるスマートコントラクトを作っていきましょう!それでは次回の記事もお楽しみに!
コメント