totonoe

セキュリティを整える

専門

SQLインジェクションのしくみを整える

= 入力欄の細工でデータが抜ける“あの脆弱性”を、手元の練習DBで安全に体験

「入力欄に変な文字を入れると、なぜ全部のデータが抜けるのか?」──ログイン想定のクエリに攻撃文字列を入れ、文字列連結の“脆弱版”とプレースホルダの“安全版”を並べて比べます。手元のサンドボックスDBだけで完結し、実在サービスには一切触れません。攻撃の練習ではなく、防ぐ仕組みを掴むためのツールです。

🔰 かんたんに言うと

入力欄の細工でデータベースが乗っ取られる不具合(SQLインジェクション)を、練習用のDBで安全に体験します。

i

TLDR — 30秒で分かる

`' OR '1'='1' --` を入れると、なぜ全件抜けるのか。脆弱版と安全版を並べて、プレースホルダがそれを無力化する様子を生SQLで確かめる。

主な機能を見る
  • 手元のsql.jsサンドボックスDB(ダミー3件)で完結・送信ゼロ
  • 脆弱版(文字列連結)の実行された生SQLをそのまま表示
  • 安全版(プレースホルダ ? バインド)と同一入力で同時対比
  • 「入力→混入→DBが命令と解釈」をStepDiagramで図解
  • 攻撃文字列サンプル+正規ログインのワンクリック検証
  • 防御解説(プレースホルダ/入力検証/最小権限/ORM)

DISCLAIMER — 防御・教育目的

このツールは「なぜ脆弱なコードは破られ、正しいコードは破られないのか」を理解するための 防御教育です。動かしているのはあなたのブラウザ内のダミー DB だけ(送信ゼロ・実在のサービスやデータベースには一切アクセスしません)。 実在するサービスや他人のシステムへの SQL インジェクションは、不正アクセス禁止法に触れる犯罪行為です。絶対に行わないでください。

アニメで見る — SQL インジェクションのしくみ ▶ 再生で1ステップずつ動きます
⌨️

入力欄

name / password

⌨️ ' OR '1'='1' --
🧩

アプリ

クエリ組み立て

📝 …name='[ここに連結]'
💥 …name='' OR '1'='1'
🗄️

データベース

SQLite

🔓 全ユーザーが返る
⌨️

入力欄

name / password

⌨️ ' OR '1'='1' --
🧩

アプリ

プリペアド文

📝 …name = ? (形は固定)
📦 値=入力まるごと1個
🗄️

データベース

SQLite

✅ 該当なし(0件)

STEP 1

※ これはイメージ図です。下の「手元のサンドボックスで試す」で、同じ入力が脆弱版と安全版でどう変わるかを実際に比べられます。

手元のサンドボックスで試す

同じ入力を、脆弱版と安全版に同時に流し込む。

ログイン想定のクエリ SELECT * FROM users WHERE name='…' AND password='…' を、 2 通りの実装で実行します。name 欄に攻撃文字列を入れて「実行」を押すと、左(文字列連結)は認証バイパスで全件返り、右(プレースホルダ)は 0 件になることを見比べられます。

攻撃文字列サンプル(クリックで name 欄に挿入)

VULNERABLE

文字列連結(危険な実装)

入力をそのまま + で連結している

実行された生 SQL

 
SAFE

プレースホルダ(安全な実装)

クエリの形は固定し、入力は ? に値として渡す

テンプレート+バインド値

 

サンドボックス users テーブル(ダミー・機密でない学習用データ)

taro / hunter2hanako / sakura88admin / s3cr3t-admin の 3 行。すべて作り物で、リセットでいつでも戻せます。

どう防ぐか

「入力を命令にしない」ための 4 つの基本。

① プレースホルダ/プリペアドステートメント(最重要)

クエリの「形」を先に固定し、入力は ? や名前付きパラメータに値として渡す。入力はどんな文字でも「データ」にしかならず、命令として解釈されません。これだけで本デモの攻撃は無力化されます。

② 入力検証(バリデーション)

「数値のはずの欄は数値だけ」「メールは形式チェック」など、期待する形以外を弾く。ただし連結をやめる代わりにはならない補強策。検証だけに頼るのは危険です。

③ 最小権限(least privilege)

アプリが使う DB ユーザーに、必要な権限だけを与える。読み取りしかしないなら更新・削除権限を持たせない。万一抜かれても被害範囲を小さくできます。

④ ORM / クエリビルダ

多くの ORM(Prisma / Active Record / SQLAlchemy など)は内部でパラメータ化を行うため、素の文字列連結を避けやすい。ただし生 SQL を書く箇所では結局①が必要です。

使い方

  1. 1
    攻撃文字列サンプルを押す、または name 欄に直接入力する(初期値は ' OR '1'='1' --)。
  2. 2
    「▶ 両方で実行」を押す。左(脆弱)と右(安全)に同じ入力が流れます。
  3. 3
    左は生 SQL に攻撃文字列が混入して全件返り、右は0 件になるのを見比べる。「なぜ通るか」が生 SQL で見えます。
  4. 4
    taro / hunter2 など正規の入力では両方とも 1 件返る=安全版でも普通のログインは壊れない、を確認する。

よくある質問

Q. 実在のサービスに試せますか?
A. いいえ。動くのはブラウザ内のダミーDBだけで、実在サービス・DBには一切接続しません。他人のシステムへのSQLインジェクションは不正アクセス禁止法に触れる犯罪です。
Q. ' OR '1'='1' -- を入れると何が起きますか?
A. 脆弱版では入力の ' がクエリの引用符を閉じ、OR '1'='1' が常に真の条件として混入し、-- 以降(パスワード判定)が無効化されて全ユーザーが返ります(認証バイパス)。
Q. プレースホルダはなぜ安全なのですか?
A. クエリの「形」を先に固定し、入力は ? に値として渡すためです。引用符やSQL断片も「ただの文字データ」として扱われ、命令には変わりません。
Q. 入力検証(バリデーション)だけでは防げませんか?
A. 補強にはなりますが不十分です。抜け道が残りやすく、根本対策はプレースホルダ(プリペアドステートメント)です。検証は併用する補助策と考えてください。
Q. ORMを使えば自動的に安全ですか?
A. 多くのORMは内部でパラメータ化するため安全寄りですが、生SQLを書く箇所では結局プレースホルダが必要です。
Q. データは送信されますか?
A. されません。sql.js(WASM)がブラウザ内で完結し、入力もDBも端末から出ません(送信ゼロ)。

入力値はURLの「#」以降に入るためサーバーには送信されません。リンクを開くと同じ状態を復元します。

RELATED TOOLS

続けて整える

KOINOBORI ECOSYSTEM

私たちが運営するサイト