【セキュリティ入門】SQLインジェクションとは?Webサイトを破壊する魔法の呪文
公開日: 2025年9月23日
エンジニアになりたての頃、僕が作った社内ツールを先輩にコードレビューしてもらった時のことです。 先輩はニヤリと笑って、ログイン画面のパスワード欄に変な記号を入力しました。
' OR '1'='1
「これでログインできちゃったらどうする?」 そう言われてエンターキーを押すと...なんと、パスワードが間違っているはずなのに、管理者としてログインできてしまったのです。
「えっ!?なんで!?」とパニックになる僕に、先輩は一言「これがSQLインジェクションだよ」と教えてくれました。 もしこれが本番の顧客サービスだったらと思うと、今でもゾッとします。
今日は、Webサイトを一撃で破壊しかねないこの「魔法の呪文」の仕組みと、絶対にやってはいけないコードの書き方について、僕の失敗を元に解説します。
普通のログイン処理
まず、一般的なログインフォームの裏側で動いているSQL文を見てみましょう。
# ユーザーが入力した username と password を変数に入れる
username = "Taro"
password = "pass123"
# 【危険!】文字列結合でSQLを作っている
sql = "SELECT * FROM users WHERE name = '" + username + "' AND password = '" + password + "'"
このコードは、name がTaroで、かつ password がpass123ならログイン成功、という処理です。
一見、何も問題ないように見えますよね? 僕も当時は「これの何がいけないの?」と思っていました。
悪意のある攻撃者は、どうやって攻撃するのか?
攻撃者は、パスワード入力欄に、以下のような**「魔法の呪文」**を入力します。
' OR '1'='1
これを先ほどの危険なコードに入れると、完成するSQL文はこうなります。
SELECT * FROM users WHERE name = 'Taro' AND password = '' OR '1'='1'
「魔法の呪文」が意味するもの
このSQL文を日本語に翻訳すると、こうなります。
- ユーザー名が「Taro」で、パスワードが「空」の人を探してね。
- または (OR)
- 「1」と「1」が同じなら、全員OKにしてね。
「1」と「1」は絶対に同じ(TRUE)ですよね。
つまり、パスワードが何であろうと、この OR '1'='1' という条件のおかげで、強制的に「条件クリア!」と判定されてしまうのです。
その結果、攻撃者はパスワードを一文字も知らなくても、堂々とログインできてしまいます。さらに怖いことに、この手口を応用すれば、DROP TABLE users;(ユーザーデータを全削除)といった命令も実行できてしまいます。
どうすれば防げるのか?:「プレースホルダ」を使おう
対策はたった一つ。 「ユーザーからの入力を、絶対にSQL文として直接組み立てない」ことです。
そのための仕組みが、「プレースホルダ(Prepared Statements)」です。
# 【安全!】プレースホルダを使う
# SQL文の「テンプレート」を用意する(:name, :password はただの「穴」)
sql = "SELECT * FROM users WHERE name = :name AND password = :password"
# 後から値を「安全なデータとして」当てはめる
result = db.session.execute(sql, {name: username, password: password})
この書き方なら、たとえ攻撃者が ' OR '1'='1 を入力しても、データベースはそれを「そういう変なパスワードなんだな」とただの文字として扱います。呪文は無効化され、攻撃は失敗します。
まとめ
SQLインジェクションは、エンジニアなら「知らなかった」では済まされない、基本にして最悪の脆弱性です。
あなたが将来コードを書くときは、必ず「ユーザーからの入力は、常に『毒』が含まれているかもしれない」と疑ってください。そして、面倒くさがらずに必ずプレースホルダを使ってください。
それが、あなた自身の信用と、サービスを使ってくれる大切なユーザーを守るための、エンジニアとしての責任です。
プログラミング学習に必須ツール!
記事で紹介したコードがよく分からなかったり、ご自身のコードについてもっと知りたい場合は、AIコード解説ツールが便利です。コードを貼り付けるだけで、AIが日本語で分かりやすく解説します。
AIコード解説ツールを使ってみる →