mcpField
B
blockchain-auditor

blockchain-auditor

github.com/ckorhonenセキュリティ2253 回インストール5 週間前に更新
リポジトリ

blockchain-auditor について

検証済みソースコードや未検証バイトコードを調べる、セキュリティ監査向けのスマートコントラクト監査スキルです。脆弱性の発見からフォーク上での検証、深刻度評価付きレポートまでを段階的に進めます。

主な機能

  1. 01ソースコードとバイトコードの調査
  2. 02一般的なコントラクト脆弱性の確認
  3. 03DeFi 固有の攻撃面の分析
  4. 04フォーク上でのエクスプロイト検証
  5. 05深刻度評価とレポート作成

活用シーン

  1. 01検証済みスマートコントラクトの監査
  2. 02バイトコードのみのコントラクトの調査
  3. 03フォーク環境での DeFi 脆弱性テスト
  4. 04脆弱性レポートの作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/ckorhonen/claude-skills --skill blockchain-auditor

インストール後、Claude Code で/blockchain-auditorを入力して読み込まれたか確認します。

同梱ファイルreference.md

詳細

ブロックチェーンセキュリティ監査担当

体系的にスマートコントラクトを監査し、権限のないアカウントが資金を引き出したり、不正にアクセスしたりできる脆弱性を特定します。

クイックスタート

# For verified contracts (Etherscan source available)
cast etherscan-source <address> --chain mainnet

# For unverified contracts (bytecode only)
cast code <address> --rpc-url $ETH_RPC_URL
cast disassemble <bytecode>

# Fork testing
forge test --fork-url $ETH_RPC_URL -vvv

# Static analysis
slither . --checklist

監査方法

フェーズ 1:事前調査
  1. コントラクト情報を収集します:

    # Check balance
    cast balance <address> --rpc-url $ETH_RPC_URL
    
    # Get bytecode
    cast code <address> --rpc-url $ETH_RPC_URL
    
    # Check if verified on Etherscan
    curl "https://api.etherscan.io/api?module=contract&action=getsourcecode&address=<address>&apikey=$ETHERSCAN_API_KEY"
    
    # Check for proxy implementation
    cast storage <address> 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc --rpc-url $ETH_RPC_URL
    
  2. コントラクトの種類を特定します:

    • マルチシグウォレット(addOwner、execute、confirmTransaction)
    • トークンコントラクト(transfer、approve、balanceOf)
    • DeFi プロトコル(deposit、withdraw、swap、liquidate)
    • レンディング/借入(Compound/Aave スタイル)
    • AMM/DEX(流動性プールを備えた Uniswap v2/v3 スタイル)
    • プロキシパターン(EIP-1967、UUPS、Transparent、Beacon)
    • Vault/イールドアグリゲーター(ERC-4626)
    • クロスチェーンブリッジ(ロック/ミント、バーン/リリース)
    • NFT コントラクト(ERC-721、ERC-1155)
フェーズ 2:ソースコード分析(検証済みコントラクト)
  1. 高リスク関数を特定します:

    • selfdestruct/suicide - すべての ETH を引き出せます
    • delegatecall - 任意のコードを実行できます
    • ユーザーが制御できるデータを使った call - 任意の呼び出しが可能です
    • チェックなしの transfer/send - リエントランシーの危険があります
    • withdraw/claim/redeem - 資金を引き出せる箇所です
    • initialize/init - プロキシの初期化(二度呼び出せますか?)
    • permit/permitAll - オフチェーン承認の回避
    • flash/flashLoan - フラッシュローンのエントリーポイント
  2. アクセス制御パターンを確認します:

    // Weak patterns to look for:
    require(tx.origin == owner);     // tx.origin bypass
    require(msg.sender == owner);    // Check if owner is compromised
    // Missing modifier on sensitive function
    function withdraw() public {     // No onlyOwner!
        payable(msg.sender).transfer(address(this).balance);
    }
    // Proxy: unprotected initialize
    function initialize(address _owner) public {  // Missing initializer modifier!
        owner = _owner;
    }
    
  3. 既知の脆弱性パターン:

    • リエントランシー(外部呼び出し後の状態変更)
    • 整数のオーバーフロー/アンダーフロー(Solidity < 0.8.0)
    • 戻り値の未チェック
    • フロントランニングの可能性
    • フラッシュローン攻撃(単一の tx 内での価格操作)
    • 価格オラクルの操作(スポット価格と TWAP)
    • Permit/EIP-2612 署名のリプレイ
    • ERC777 コールバックによるリエントランシー
    • 読み取り専用リエントランシー(ロジック内での view 関数の誤用)
    • 寄付攻撃(トークン残高の水増し)
    • 初回預入者によるシェアの水増し(ERC-4626 Vault)
フェーズ 3:DeFi 固有の攻撃ベクトル

DeFi プロトコルでは、以下の攻撃ベクトルが特に価値が高く、悪用されやすいものです。

  1. 価格オラクルの操作:

    // Vulnerable: spot price used as oracle
    function getPrice() public view returns (uint256) {
        (uint112 reserve0, uint112 reserve1,) = IUniswapV2Pair(pool).getReserves();
        return reserve1 * 1e18 / reserve0;  // Manipulable in a single tx!
    }
    // Attack: flash loan → manipulate pool → call vulnerable function → repay
    
    • プロトコルがスポット価格を使用している箇所がないか確認します
    • TWAP オラクルは安全です。Chainlink フィードも(ハートビートの範囲内では)安全です
    • getReserves()、slot0()、AMM プールへの直接クエリを探します
  2. フラッシュローン攻撃の対象範囲:

    • 借りた資金を使って、状態を変更する関数を呼び出せますか?
    • 確認事項:大量に借りる → 何かを実行する → 同じ tx 内で返済する
    • 重要な問い:プロトコルは、ユーザーの預入前と後のどちらで価格/残高を測定しますか?
  3. リエントランシーの種類:

    // Cross-function reentrancy
    function withdraw() external {
        // State updated after transfer → reenter via deposit()
        IERC20(token).safeTransfer(msg.sender, amounts[msg.sender]);
        amounts[msg.sender] = 0;  // Too late!
    }
    
    // Read-only reentrancy (in Curve, Balancer)
    // Attack: during callback, totalSupply() returns old value
    // Another protocol reads it via getVirtualPrice() during the callback
    
  4. ERC-4626 Vault の水増し攻撃:

    • 初回預入者はトークンを寄付してシェア価格を水増しできます
    • 対象:シェアを (deposit * totalShares) / totalAssets で発行するプロトコル
    • totalShares = 0 の場合、初回預入者は deposit 分のシェアを受け取り、その後、寄付によって価格を水増しできます
  5. 署名/Permit の脆弱性:

    // EIP-2612 permit can be front-run
    // Front-runner takes the permit, uses it themselves before victim's tx
    // Safe if permit is used atomically in the same tx
    
    // Check: does permit use chainId? (cross-chain replay)
    // Check: does it use nonces? (replay protection)
    
  6. ガバナンス/Timelock 攻撃:

    • ガバナンスによって悪意のあるアップグレードを提案し、実行できますか?
    • Timelock はありますか?期間はどのくらいですか?
    • フラッシュローンによる投票権で定足数を回避できますか?
フェーズ 4:バイトコード分析(未検証コントラクト)
  1. バイトコードを逆アセンブルします:

    cast disassemble <bytecode> > contract.asm
    
  2. 関数セレクターを抽出します:

    # Look for PUSH4 followed by 4 bytes
    grep -oE '63[0-9a-f]{8}' contract.asm | cut -c3-10 | sort -u
    
  3. シグネチャを調べます:

    curl "https://www.4byte.directory/api/v1/signatures/?hex_signature=0x<selector>"
    # Also try openchain.xyz/signature-database
    
  4. 危険なオペコードを特定します:

    オペコード16 進数リスク
    SELFDESTRUCTff重大 - コントラクトを破棄します
    DELEGATECALLf4高 - 任意のコードを実行します
    CALLf1中 - 外部呼び出し
    CALLCODEf2高 - 非推奨で、危険です
    CREATE2f5中 - 決定論的なデプロイ
    TLOAD/TSTORE5c/5dEIP-1153 で追加された一時ストレージ
  5. 制御フローを分析します:

    • 関数のエントリーポイントとなる JUMPDEST の位置を特定します
    • アクセス制御のための CALLER/ORIGIN チェックを追跡します
    • 状態アクセスに関する SLOAD/SSTORE のパターンを探します
フェーズ 5:脆弱性の評価

現在のブロックチェーンの状態を踏まえ、各発見事項の悪用可能性を評価します。

評価基準対応
Critical今すぐ直接悪用可能で、価値が高い直ちに PoC を作成
High特定の条件が満たされれば悪用可能フォークテスト
Medium起こりそうにない条件が必要記録
Low理論上のもので、条件が非常に起こりにくいメモのみ

悪用可能性に影響する要因:

  • 現在のブロックチェーンの状態(所有者の鍵、タイムロック、残高)
  • 必要な事前条件(入金、承認、ブロック番号)
  • ガスコストと潜在的な利益の比較
  • MEV/フロントランニングのリスク(攻撃者がサンドイッチ攻撃を仕掛けられるか)
  • Flashbots のプライベートメンプールが利用可能か
フェーズ 6:フォークでの検証
  1. Foundry テストをセットアップ:

    // test/Exploit.t.sol
    pragma solidity ^0.8.20;
    import "forge-std/Test.sol";
    import "forge-std/interfaces/IERC20.sol";
    
    interface IFlashLoanProvider {
        function flashLoan(uint256 amount) external;
    }
    
    contract ExploitTest is Test {
        address target = 0x<TARGET_ADDRESS>;
        address attacker;
    
        function setUp() public {
            // Fork at specific block for determinism
            vm.createSelectFork(vm.envString("ETH_RPC_URL"), <BLOCK_NUMBER>);
            attacker = makeAddr("attacker");
            vm.deal(attacker, 1 ether);
        }
    
        function test_exploit() public {
            uint256 balanceBefore = attacker.balance;
    
            vm.prank(attacker);
            (bool success,) = target.call(abi.encodeWithSelector(0x<SELECTOR>));
    
            uint256 balanceAfter = attacker.balance;
    
            // CRITICAL: Verify actual fund extraction
            assertGt(balanceAfter, balanceBefore, "Exploit failed - no funds extracted");
        }
    
        // Flash loan exploit template
        function test_flashLoanExploit() public {
            uint256 targetBalanceBefore = IERC20(token).balanceOf(target);
    
            vm.prank(attacker);
            FlashLoanAttacker exploitContract = new FlashLoanAttacker(target);
            exploitContract.attack();
    
            assertLt(IERC20(token).balanceOf(target), targetBalanceBefore, "No drain");
            assertGt(IERC20(token).balanceOf(attacker), 0, "No profit");
        }
    }
    
  2. フォーク上で実行:

    forge test --fork-url $ETH_RPC_URL -vvvv --match-test "test_exploit"
    
  3. 資金の引き出しを検証(呼び出しの成功だけでは不十分です):

    • 攻撃者の残高が増加したことを確認します
    • 対象の残高が減少したことを検証します
    • コントラクトの状態が想定どおりに変化したことを確認します
    • 呼び出しの成功は、エクスプロイトの成功を意味しません
フェーズ 7:レポートの作成

確認された脆弱性について、レポートを作成します:

# Vulnerability Report: [Contract Address]

## Summary
- **Severity**: Critical/High/Medium/Low
- **Type**: [Reentrancy/Access Control/Oracle Manipulation/etc.]
- **Impact**: [Amount at risk, what attacker gains]
- **Exploitable**: Yes/No (with current blockchain state)
- **Block confirmed**: [Block number of fork test]

## Vulnerable Function
\`\`\`solidity
function vulnerableFunction() public {
    // Vulnerable code
}
\`\`\`

## Attack Vector
1. Attacker calls function X with parameter Y
2. Contract fails to check Z
3. Funds transferred to attacker

## Proof of Concept
\`\`\`solidity
// Foundry test that demonstrates the exploit
function test_exploit() public {
    // Setup and exploit code
}
\`\`\`

## Execution Script (if confirmed)
\`\`\`bash
cast send <target> "vulnerableFunction()" --rpc-url $ETH_RPC_URL --private-key $PRIVATE_KEY
\`\`\`

## Remediation
- Add access control modifier
- Implement checks-effects-interactions pattern
- Use SafeMath for arithmetic (or upgrade to Solidity >= 0.8.0)
- Replace spot price with TWAP oracle

よくある脆弱性のチェックリスト

アクセス制御
  • すべての機密関数に適切な修飾子が設定されている
  • owner/admin アドレスが侵害されていない
  • マルチシグで十分な数の承認が必要である
  • タイムロックが適用されている
  • tx.origin による認証がない
  • プロキシの初期化関数を二度呼び出せない
  • UUPS のアップグレード関数がアクセス制御されている
  • フラッシュローンでガバナンスの定足数を回避できない
再入可能性
  • 外部呼び出しの前に状態が変更されている(CEI パターン)
  • 資金移転に ReentrancyGuard が使用されている
  • 信頼できないコントラクトへのコールバックがない
  • ERC-777 の tokensReceived フックが考慮されている
  • 関数間の再入可能性が確認されている
  • 読み取り専用の再入可能性が確認されている(getVirtualPrice、交換レート)
算術演算(Solidity < 0.8.0)
  • すべての演算で SafeMath が使用されている
  • ユーザー入力を含む unchecked ブロックがない
  • 適切な境界チェックが行われている
  • 0.5.x~0.6.x のオーバーフロー脆弱性を確認する
オラクル/価格操作
  • スポット価格オラクルがない(フラッシュローンで操作可能)
  • 該当する場合は TWAP が使用されている
  • Chainlink のハートビートの鮮度が確認されている
  • 重要な処理経路で複数のオラクルを集約している
  • プールの残高を価格の取得元として使用していない
フラッシュローン
  • 同一トランザクション内で状態を操作してから読み取ることができない
  • 信頼できない外部呼び出しの後に価格/比率を確認していない
  • フラッシュローンから呼び出し可能なすべての関数に再入防止策がある
DeFi 固有の項目
  • ERC-4626 の初回預金者によるシェアのインフレが防止されている(仮想シェア/資産)
  • Permit/EIP-2612 のリプレイ攻撃が防止されている(nonce、chainId)
  • 残高ベースの会計処理における寄付攻撃が防止されている
  • 該当する場合は MEV のサンドイッチ攻撃が防止されている
  • クロスチェーンブリッジでメッセージのリプレイ攻撃が防止されている
外部呼び出し
  • 戻り値が確認されている
  • ガス制限が適切に設定されている
  • フォールバック/receive 関数が適切に処理されている
Solidity バージョン固有の問題
バージョン問題確認項目
< 0.8.0整数のオーバーフロー/アンダーフローSafeMath の使用
< 0.6.0コンストラクター名の混同constructor() キーワード
< 0.5.0初期化されていないストレージポインター変数宣言
すべてtx.origin による認証アクセス制御のパターン
すべてプロキシのストレージ衝突EIP-1967 スロットの使用

偽陽性の指標

悪用できそうに見えても、実際にはそうでないパターンに注意してください。

  1. マルチシグの保留中トランザクション:kill() は成功しますが、N-of-M の承認が必要です
  2. ユーザーごとの残高:withdraw() が返すのは呼び出し元の入金額のみです
  3. タイムロック付きの払い出し:資金は呼び出し元ではなく、ハードコードされたアドレスに送られます
  4. プロキシパターン:プロキシにチェックがなくても、実装にはチェックがあります
  5. 送金を伴わない呼び出しの成功:関数は完了しますが、ETH は移動しません
  6. 即時返済チェック付きフラッシュローン:最後に残高が検証される場合、悪用できません
  7. 一時停止可能なコントラクト:管理者は一時停止できますが、これは設計どおりです

悪用可能性を判断する前に、フォーク上で実際に資金が移動することを必ず確認してください。

ツールのリファレンス

ツール用途コマンド
castRPC 呼び出し、逆アセンブルcast code/call/send/disassemble
forgeフォークテストforge test --fork-url
anvilローカルフォークノードanvil --fork-url $RPC
slither静的解析slither . --checklist
4byte.directoryセレクターの検索API またはウェブ
openchain.xyzセレクターの検索API またはウェブ
Etherscanソースコード、ABIAPI またはウェブ
Mythrilシンボリック実行myth analyze
Tenderlyトランザクションのシミュレーションウェブ UI
Dedaubバイトコードの逆コンパイラーdedaub.com

環境のセットアップ

必須の環境変数:

export ETH_RPC_URL="https://eth-mainnet.g.alchemy.com/v2/<KEY>"
export ETHERSCAN_API_KEY="<KEY>"

必須のツール:

# Foundry (forge, cast, anvil)
curl -L https://foundry.paradigm.xyz | bash
foundryup

# Slither
pip3 install slither-analyzer

# Node.js (for Hardhat if needed)
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox

ワークフローの例

# 1. Check contract value and code
cast balance 0x<address> --rpc-url $ETH_RPC_URL
cast code 0x<address> --rpc-url $ETH_RPC_URL > bytecode.hex

# 2. Check for proxy (EIP-1967 slot)
cast storage 0x<address> 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc --rpc-url $ETH_RPC_URL

# 3. Disassemble if unverified
cast disassemble $(cat bytecode.hex) > contract.asm

# 4. Extract and lookup selectors
grep -oE '63[0-9a-f]{8}' contract.asm | cut -c3-10 | sort -u | while read sel; do
  sig=$(curl -s "https://www.4byte.directory/api/v1/signatures/?hex_signature=0x$sel" | jq -r '.results[0].text_signature // "unknown"')
  echo "0x$sel: $sig"
done

# 5. Run slither on source (if available)
slither . --checklist 2>&1 | head -100

# 6. Create and run fork test
forge test --fork-url $ETH_RPC_URL -vvvv

# 7. Verify fund extraction (not just call success!)

# 8. Generate report if confirmed exploitable

データベースとの統合

複数のコントラクトを監査する場合は、調査結果を SQLite で管理します。

CREATE TABLE contracts (
  address TEXT PRIMARY KEY,
  balance_usd REAL,
  is_verified INTEGER,
  exploitable INTEGER DEFAULT 0,
  attack_type TEXT,
  notes TEXT
);

-- Update after analysis
UPDATE contracts SET
  exploitable = 0,
  notes = 'Multi-sig wallet. kill() requires confirmations. NOT exploitable.'
WHERE address = '0x...';

セキュリティおよび法的な注意事項

  • テストはフォーク上でのみ行い、明示的な許可なくメインネットでは行わないでください
  • 偽陽性も含め、すべての調査結果を記録してください
  • 実際に存在する脆弱性については、責任ある開示を検討してください
  • エクスプロイトを実行することによる法的な影響に注意してください
  • このスキルは、許可を得たセキュリティ研究のみを対象としています
  • Immunefi、Code4rena、Sherlock — 公式のバグバウンティ窓口から報告してください

コメント