ume

SQLインジェクションと対策

対象者

SQLインジェクションとは?

⇨不正なSQL文を発行しデータベース内の情報を抜き取ったりする攻撃手法

例えば ログインの状況を想定しみる emailとパスワードでログインするフォームがある

仮にEmailに:""OR '1'='1".
Passwordに""OR '2'>'1" ように入力しLoginをクリックすると

User.find_by("login = '#{params[:email]}' AND password = '#{params[:password]}'")

このようにデータベースに問い合わせを行います.

一見何の問題もなさそうですが.
もしparamsの中身を覗いてみると↓のようになっています

params = { email:     "' OR '1'='1",
           password: "' OR '2'>'1" }

上記のような感じだと最終的に

SELECT * FROM users WHERE login = '' OR '1'='1' AND password = '' OR '2'>'1' LIMIT 1

要約すると1=1, 2>1が成り立つ時usersから1人取り出してくださいということです。結果emailもpasswordも知らなくてもログインできてしまいます。

対策

⇨ユーザーからの情報をそのまま使ってsqlを作成させない.
どうやって?
エスケープ処理する. エスケープ処理とは一言で言うと「ユーザーから送られてきたparamsの中身に悪意のある値をはじいて無くしてくれる機能」.
? = エスケープ処理

User.find_by("login = '#{params[:email]}' AND password = '#{params[:password]}'")

Model.where("login = ? AND password = ?", 任意の変数名, 任意の変数名).first

第2引数の変数名と第3引数の任意の変数名がそれぞれ?に代入される。 この任意の変数にparams[:email]とparams[:password]が代入される

Model.where("login = ? AND password = ?", email, password).first

params[:email] と任意の変数名は同じ名前にするとわかりやすい。 paramsの中身がemailなら任意の変数名もemailにすべき。

参考

Rails セキュリティガイド - Railsガイド

https://api.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html#method-i-sanitize_sql_for_conditions