【セキュリティ入門】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コード解説ツールを使ってみる →