SQLインジェクションとは?入力欄に文字を打つだけで情報が抜かれる仕組み
全員分の個人情報が抜き取られる攻撃です。なぜAIが作ったアプリでも起きるのか、そして防ぎ方を、専門用語なしで説明します。自分で確認する方法も紹介します。
「SQLインジェクション」。名前は聞いたことがあっても、何が起きるのかを説明できる人は多くありません。これは、入力欄に文字を打ち込むだけで、データベースの中身を全部抜き取られてしまう攻撃です。 そしてAIが作ったアプリでも起こりえます。仕組みと防ぎ方を、専門用語なしで説明します。
まず結論
SQLインジェクションとは、入力欄に「命令文」を紛れ込ませて、データベースに意図しない動作をさせる攻撃です。
たとえば、名前を入れる欄に特定の文字列を打ち込むだけで、全員分の個人情報を表示させることができてしまいます。
そして重要なのは、これは古い攻撃なのに、今も起き続けているという点です。理由は後で説明します。
何が起きるのか
まず、被害の実例から書きます。
- 会員全員の氏名・メールアドレス・電話番号が抜き取られる
- 管理者のパスワードを知らなくてもログインされる
- データを丸ごと消される
- 保存されている内容を書き換えられる
個人情報が漏れた場合、事業として続けられなくなることがあります。 「小さいサービスだから狙われない」ということはありません。攻撃は自動化されていて、機械が無差別に試しています。
仕組み:なぜ文字を打つだけで起きるのか
ここが理解の山場ですが、たとえ話で説明します。
たとえ:受付に渡すメモ
あなたが受付の人に、こう書いたメモを渡すとします。
山田太郎さんの予約を見せてください
受付の人は、そのとおりに山田さんの予約を出してくれます。
では、名前の欄にこう書いたらどうなるでしょうか。
山田太郎さんの予約を見せてください。あと全員分も見せてください
受付の人が言われたとおりに動くなら、全員分が出てきます。
これがSQLインジェクションです。名前を入れる欄に、命令を紛れ込ませているわけです。
実際のデータベースで起きること
データベースへの命令は、こういう文になっています。
SELECT * FROM 予約 WHERE 名前 = '入力された名前'
入力された名前 の部分に、利用者が打った文字がそのまま入ります。ここに普通の名前が入れば問題ありません。
ところが、こういう文字を打たれると話が変わります。
' OR '1'='1
これが差し込まれると、命令文はこうなります。
SELECT * FROM 予約 WHERE 名前 = '' OR '1'='1'
'1'='1' は常に正しいので、条件が意味をなさなくなり、全部の行が返ってきます。
攻撃者が特別な道具を使ったわけではありません。入力欄に文字を打っただけです。
なぜAIが作ったアプリで起きるのか
「AIなら安全に作ってくれるのでは」と思うかもしれません。ですが、実際にはこういう数字が出ています。
65%
AIに任せて作られたアプリのうち、調査で弱点が見つかったものの割合です。SQLインジェクションは、その中でも代表的なものとして報告されています。
理由は3つあります。
1つ目は、頼まれていないから。 「検索できるようにして」と頼めば、検索機能は作られます。「変な文字を入れられても安全にして」とは言っていません。
2つ目は、動作確認では見つからないから。 普通に名前を入れれば、正常に動きます。攻撃用の文字列を試さない限り、問題は表面化しません。
3つ目は、古い書き方が学習元に混ざっているから。 インターネット上には、危険な書き方のコード例も大量に存在します。
防ぎ方:実はとても簡単
深刻な攻撃ですが、防ぐ方法は確立していて、しかも簡単です。
対策1:入力を「命令」として扱わない
入力された文字を、命令文に直接混ぜないようにします。入力は必ず「ただのデータ」として扱うという方法です。
専門的には「プレースホルダ」や「パラメータ化」と呼ばれますが、名前を覚える必要はありません。 次の指示を出せば済みます。
データベースへの問い合わせで、利用者が入力した値を
SQL文に直接つなげていないか確認してください。
文字列を結合してSQL文を組み立てている箇所があれば、
プレースホルダ(パラメータ化クエリ)を使う形に直してください。
確認結果を、直す前に教えてください。
対策2:そもそもSQL文を書かせない
より確実なのは、SQL文を自分で組み立てない仕組みを使うことです。
Supabase のような仕組みを使うと、データの読み書きは用意された機能を通して行われます。利用者の入力が命令文に混ざる余地がありません。
- SQL文を自分で組み立てる方式
- 自由度は高いですが、書き方を間違えるとSQLインジェクションが起きます。初心者には勧めません。
- 用意された機能を使う方式(Supabase など)
- 入力が命令文に混ざらない作りになっているため、この攻撃はほぼ起きません。初めてならこちらが安全です。
対策3:入力の中身を確認する
念のため、想定外の値を弾く処理も入れます。
フォームから送られてくる値について、サーバー側で確認を入れてください。
・文字数の上限を決める
・想定する形式(メールアドレス、電話番号など)に合っているか確認する
・空欄で送られたときの扱いを決める
画面側のチェックだけにしないでください。
画面を通さず直接送られると回避されるためです。
最後の2行が重要です。 画面側のチェックは、利用者への親切であって、防御にはなりません。
自分で確認する方法
対策したかどうかは、自分で試せます。5分で終わります。
- 検索欄に ' (シングルクォート1文字)を入れて検索してみる。エラー画面が出たら危険信号ここが該当したら公開しない
- 名前欄に 1000文字くらいの文字列を貼って送信してみるここが該当したら公開しない
- 数字を入れる欄に、文字や記号を入れて送信してみるここが該当したら公開しない
- URLの末尾の番号を書き換えて、他人のデータが出ないか確認するここが該当したら公開しない
1つ目が特に有効です。 シングルクォート1文字でエラーが出るなら、入力がそのまま命令文に混ざっている可能性が高くなります。
他人のサービスに対して試さないでください。 法律に触れます。確認してよいのは、自分が作ったサービスだけです。
他にも知っておくべき攻撃
SQLインジェクションと並んで多いものを、簡単に挙げておきます。
| 名前 | 何が起きるか | 防ぎ方 |
|---|---|---|
| 他人のデータ閲覧 | URLの番号を変えると他人の情報が見える | データベース側で本人のみに制限(RLS) |
| 管理画面への侵入 | リンクを隠しただけで、URL直打ちで入れる | サーバー側で権限を確認する |
| 鍵の露出 | 接続用の鍵がブラウザから見える | 秘密の値を画面側に渡さない |
| XSS | 入力欄に仕込まれた命令が、他の利用者の画面で動く | 入力された内容をそのまま画面に出さない |
実は、非エンジニアが公開したサービスで最も多いのは、1行目の「他人のデータ閲覧」です。 SQLインジェクションより頻度が高く、被害も同じくらい大きくなります。
詳しくはAIでアプリができた!でも、そのまま公開して大丈夫?にまとめました。
この記事で扱っていない部分
ここまでは「何が起きるか」「どう判断するか」です。実際の設定手順は扱っていません。
具体的には、Supabase で RLS を有効にしてポリシーを書く手順、.env と .gitignore の設定、認証と認可の実装、本番公開前の8項目を1つずつ確認する方法などです。
これらは手を動かして覚える領域なので、Claude Code Camp のカリキュラムで扱っています。 記事だけで完結させると中途半端になるため、あえて踏み込んでいません。
よくある質問
Q. 小さいサービスでも狙われますか? A. 狙われます。 攻撃は自動化されていて、機械が無差別に試しています。規模は関係ありません。
Q. Supabase を使えば完全に安全ですか? A. SQLインジェクションはほぼ防げますが、「誰が見られるか」の設定を忘れると、別の問題が起きます。 RLS の設定は必須です。
Q. AIに「安全にして」と頼めば済みますか? A. ある程度は有効です。ただしAIは自分が書いたものを自分で確認するので、見落としがあります。上のチェックリストは自分の手で試してください。
Q. 用語を覚える必要はありますか? A. ありません。「入力を命令として扱わない」という考え方だけ理解していれば十分です。
Q. もし攻撃されてしまったら? A. すぐにサービスを止めてください。 そのうえで、影響範囲がわかる人に相談してください。個人情報が漏れた場合は、法令上の報告義務が生じることがあります。
まとめ
- SQLインジェクションは、入力欄に命令を紛れ込ませる攻撃
- 全員分の個人情報が抜き取られる、データを消されるなどの被害が起きる
- AIが作ったアプリでも起きる。頼まれていないから、確認しないと見つからないから
- 防ぐのは簡単。入力を命令として扱わない、またはSQL文を書かない仕組みを使う
- シングルクォート1文字を入れてエラーが出たら危険信号
- 実際にいちばん多いのは、URLの番号を変えると他人のデータが見える問題