Railsで学ぶSQLインジェクション防止完全ガイド|バインドパラメータと安全な書き方
生徒
「Railsでデータベースを使うとき、勝手に情報を盗まれたりしませんか?」
先生
「とても大事な視点ですね。RailsではSQLインジェクションという攻撃を防ぐ仕組みがあります」
生徒
「SQLインジェクションって何ですか?難しそうです…」
先生
「大丈夫ですよ。まずは仕組みを身近なたとえで説明していきましょう」
1. SQLインジェクションとは何か
SQLインジェクションとは、データベースに送る命令文(SQL)に、悪意のある文字を混ぜて不正操作を行う攻撃です。Railsアプリでは、ユーザー登録やログインなどでデータベースを使いますが、入力欄にそのまま命令を渡してしまうと危険です。
たとえるなら、注文用紙に「カレー1つ」と書くはずが、「カレー1つ+レジの中身を全部ください」と書かれてしまうようなものです。コンピュータは命令を区別できないため、そのまま実行してしまいます。
Railsの仕組みを根本から理解し、現場で通用する 「設計のセオリー」を身につけたいならこの一冊。 MVC、テスト、Docker対応など、実践的な内容が凝縮されています。
パーフェクト Ruby on RailsをAmazonで見る※ Amazon広告リンク
2. RailsとActive Recordが持つ安全設計
Railsでは、モデルとデータベース操作をActive Recordという仕組みで行います。これはORMと呼ばれ、SQLを直接書かなくてもRubyのコードで安全に操作できるのが特徴です。
Active Recordを正しく使えば、SQLインジェクションはほとんど防げます。逆に、文字列を無理やりつなげる書き方をすると危険になります。
3. 危険な文字列結合の例
まずは、やってはいけない例を見てみましょう。文字列を直接つなげてSQLを作ると危険です。
name = params[:name]
User.where("name = '#{name}'")
この書き方では、入力内容にSQLの命令が混ざる可能性があります。初心者のうちは「動いたからOK」と思いがちですが、セキュリティ面では非常に危険です。
4. バインドパラメータで安全に書く方法
Railsで最も基本的なSQLインジェクション対策がバインドパラメータです。これは「ここは値ですよ」とRailsに伝える安全な書き方です。
User.where("name = ?", params[:name])
この方法では、Railsが自動で危険な文字を無害化します。たとえ変な文字が入っても、命令として扱われません。
5. ハッシュ形式のwhereを使う
さらにおすすめなのが、ハッシュ形式で条件を書く方法です。SQLを書く必要がなく、初心者にも分かりやすいです。
User.where(name: params[:name])
この書き方はRailsが内部で安全なSQLを生成するため、SQLインジェクション対策として非常に優秀です。
6. Arelを使った柔軟で安全な条件指定
Arelは、Active Recordの内部で使われているSQL生成ライブラリです。少し難しく感じますが、安全性は高いです。
users = User.arel_table
User.where(users[:age].gt(20))
Arelを使うことで、複雑な条件でもSQLインジェクションを防ぎながら書けます。
7. Strong Parametersと組み合わせた防御
コントローラではStrong Parametersを使い、受け取る値を制限します。これにより、想定外の値がモデルに渡るのを防げます。
params.require(:user).permit(:name, :email)
入力を制限し、モデルでは安全なクエリを書く。この二重の対策がRailsの基本的なセキュリティ設計です。