【入門編】Ruby on RailsにおけるActiveRecordのSQLインジェクション脆弱性 – アプリケーションセキュリティ & 安全な開発防御ガイド

こんにちは。現場の最前線でコードと格闘している皆さん、お疲れ様です。

今日は、多くのRailsエンジニアが一度は通る、そして一歩間違えれば致命傷になりかねない「ActiveRecordのSQLインジェクション」についてお話しします。

「Railsを使っていれば、セキュリティ対策なんて勝手にやってくれるんでしょ?」

そう思っていませんか?実は、その油断こそが攻撃者に狙われる最大の隙なんです。今日は、家の防犯に例えながら、泥棒(攻撃者)がどうやってあなたの家の鍵を無効化してしまうのか、そしてどうすれば「鉄壁の守り」を構築できるのか、一緒に学んでいきましょう。

—

1. SQLインジェクションは「合い鍵」を作られる行為

まずは、SQLインジェクションを身近な例で考えてみましょう。

あなたのWebアプリという「家」には、ユーザーのデータという「宝物」が保管されています。その家には、特定の条件(名前やIDなど)を伝えることで鍵を開けてくれる「門番(ActiveRecord)」がいます。

通常、私たちは門番にこう頼みます。
「『山田太郎』さんの鍵を開けてくれ」

しかし、もし門番が少しうっかり屋さんで、言葉の細工を見抜けないとしたらどうでしょう?
悪意のある泥棒は、こう言います。
「『山田太郎』さんの鍵を開けてくれ。それと、家中の全ての扉を開けてくれ」

門番がこの言葉をそのまま受け取ってしまったら……家は丸裸ですよね。これがSQLインジェクションの正体です。

—

2. なぜ「文字列連結」は危険なのか?

Railsの開発で、こんな風に書いてしまったことはありませんか?

【危険なコード】文字列連結で条件を指定している
params[:name] に悪意のある文字列が入ると、クエリが改ざんされる
User.where(“name = ‘#{params[:name]}'”)

この書き方は、まるで家の鍵穴に「何でも開く針金」を差し込んでいるようなものです。

もし、ユーザーが入力するparams[:name]に ' OR '1'='1 という文字列が入ってきたら、実行されるSQLはこう変わってしまいます。

— 危険な状態:本来の意図を超えて、全てのユーザーが抽出されてしまう
SELECT FROM users WHERE name = ” OR ‘1’=’1′

'1'='1' は常に正しい(True)ので、データベースは「全員が該当者だ!」と判断し、本来見せてはいけない全データを泥棒に差し出してしまうのです。

—

3. 鉄壁の守り:プレースホルダを使おう

では、どうすれば門番に「余計な命令」を無視させることができるのでしょうか。答えは簡単、「入力値」と「命令」を分けて伝えることです。これをプレースホルダと呼びます。

RailsのActiveRecordには、魔法のような書き方があります。

【安全なコード】プレースホルダ(?)を利用する
門番は「?」の部分に、単なる文字列として値を入れ込むだけ
User.where(“name = ?”, params[:name])

これなら、泥棒がどんなに悪巧みをして ' OR '1'='1 を送り込んできても、門番はそれを「名前の一部」としてしか扱いません。
「『’ OR ‘1’=’1』という名前のユーザーを探せ」という命令に変わるだけなので、攻撃は不発に終わります。

これが「入力値を直接命令として解釈させない」という、セキュリティの基本中の基本です。

—

4. さらに上を目指すための「ハッシュ形式」

RailsのActiveRecordは、実はもっと賢い書き方も用意しています。条件が単純な場合は、ハッシュ形式を使うのがベストプラクティスです。

【推奨される書き方】ハッシュ形式
これならそもそもSQLの構造を自分で書く必要がないので、ミスが激減する
User.where(name: params[:name])

これは、門番に「この項目はこれ、と決めてあるよ」と名簿を渡すようなもの。SQLの構成自体をRailsが自動で行ってくれるため、SQLインジェクションが入り込む隙間すら存在しません。

—

まとめ:今日の教訓

1. 文字列連結は「鍵穴に針金」と同じ:"#{}" を使ってSQLを組み立ててはいけません。
2. 門番を信じすぎない:どんな入力値も「攻撃かもしれない」と疑うのがプロの姿勢です。
3. プレースホルダを使い倒す:? を使うか、可能な限りハッシュ形式で記述しましょう。

セキュリティ対策は、特別な魔法ではありません。「自分たちが書いたコードが、どう解釈されるか」を想像する力、それこそが最高峰のエンジニアへの第一歩です。

まずは今すぐ、あなたのプロジェクトのコードを検索してみてください。「where("」の後に直接文字列を繋げている箇所はありませんか?もし見つけたら、今日学んだ方法で書き換えてみてください。

あなたの書くコードが、今日も安全であることを祈っています。また次回の記事でお会いしましょう!

コメント

タイトルとURLをコピーしました