この記事はRuby on Rails Advent Calendar 2022の20日目の記事です。
はじめに
ransackは検索機能を楽に実装することができるgemです。
https://github.com/activerecord-hackery/ransack
スター数は執筆時現在5.3kで、今なお開発が続けられており、人気のgemと言って差し支えないでしょう。
しかし、そのセキュリティ上の問題点についてはあまり注目されていないように感じます。
実際、執筆時現在Googleで「ransack」と検索するとセキュリティについて触れられていない記事が散見されます。
この記事ではransackのセキュリティ上の問題点とその対策について紹介します。
セキュリティ上の問題点
デフォルトで任意のカラムに対して検索ができてしまいます。1
後述の手順によってカラムの中身を特定可能です。
具体例
usersテーブルにはカラムsecret_tokenが存在するとします。
以下のような実装で、後述する対策をしていない場合に情報漏洩が起きます。
class UsersController
# GET /users
def index
@records = User.ransack(params[:q]).result
end
end
攻撃
ransackは多様なマッチャーを用意しており2、[カラム名]_startというパラメータで前方一致検索が可能です。それを利用して以下のように検索を繰り返します。
GET /users?secret_token_start=a
GET /users?secret_token_start=b
GET /users?secret_token_start=c
…
レコードが取得できたならばパターンに合致していたということです。
あとはこの手順を繰り返します。
ここでは先頭の文字がaだったことにして続く手順を見ていきましょう。
GET /users?secret_token_start=aa
GET /users?secret_token_start=ab
GET /users?secret_token_start=ac
…
2文字目以降も全く同じ工程を繰り返します。
このように非常に単純な方法で、ユーザーに公開してはいけないはずのカラムの値を特定できます。
対策
下記のようにモデルに対して検索可能なカラムのリストを設定します。
class User
def self.ransackable_attributes(auth_object)
%w(first_name last_name)
end
end
こうすることで指定したカラム以外の検索を拒むことができます。
まとめ
以上のように許可リストを設定しなければ、使い方によっては情報漏洩につながることを見ていきました。ransackをお使いの方は一度実装を見直してみるといかがでしょうか。
余談
上記で述べた脆弱性について手を動かして検証できるRailsアプリを作りました。良かったら遊んでみてください。
https://github.com/wonda-tea-coffee/vulnerable_ransack_app