対象者
webサービスに対してどんな攻撃手法があるのか知りたい方。
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にすべき。