##はじめに
前回、sanitizeについて書きましたね。そしたら、「ActiveRecordのsanitizeも書くのじゃ」という神のお告げがあったので書きます。
## SQLインジェクションとは
前回はXSSでしたが今回はSQLインジェクションです。こちらも悪意ある攻撃です。パラメータを操作してデータベースクエリに影響を与える攻撃です。
find
,find_by
などは自動的に対策がされてますが、where
やsqlを生で書く場合がある時、パラメータはちゃんとサニタイズする必要があります。
##sanitize_sql_array
sql = ActiveRecord::Base.send(
:sanitize_sql_array,
['SELECT * from users WHERE name=?', "tarou"]
)
Rails5.1系ではsanitize_sql_array
はパブリックではないので、上記のようにsendを使ってサニタイズします。(Rails5.2系ではパブリックになったらしいです。→https://techracho.bpsinc.jp/hachi8833/2018_08_13/60583)
また他にも、where句用のsanitize_sql_for_conditions
、order句用のsanitize_sql_for_order
,like用のsanitize_sql_like
があります。
irb(main):010:0> sql = ActiveRecord::Base.send(
irb(main):011:1* :sanitize_sql_array,
irb(main):012:1* ['name=?', 'tarou']
irb(main):013:1> )
=> "name='tarou'"
irb(main):014:0> User.where(sql)
User Load (0.5ms) SELECT "users".* FROM "users" WHERE (name='tarou') LIMIT ? [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 10, created_at: "2018-12-19 13:42:23", updated_at: "2018-12-19 13:42:23", name: "tarou">]>
##まとめ
セキュリティ系調べてるとSQL力の足りなさを痛感....
とりあえずユーザーが入力するパラメータを使ったsql文を使うときはサニタイズを意識しておきましょう。
##参考にしたの
ActiveRecord::Sanitization::ClassMethods
https://api.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html
Rails セキュリティガイド
https://railsguides.jp/security.html#sql%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3