Ruby Security

【セキュアコーディング】Ruby on Railsはデフォルト(初期状態)でセキュア故に脆弱になる|脆弱性を産まないためのポイント解説

投稿日: カテゴリー: セキュアコーディング
Pocket

Ruby on Railsはデフォルト(初期状態)でセキュア故に脆弱になる

Ruby on Railsはデフォルト(初期状態)でもXSSやCSRFの対策などある程度セキュアな状態となっています。
さらに、公式が出している「Rails セキュリティガイド」という記事でしっかり書かれているので、基本的な対策に関してはここをみれば一定のセキュリティ水準まで持っていくことは難しくありません。

それ故、Ruby on Railsを利用したサービスの脆弱性は、デフォルトのセキュリティ対策を信じすぎた結果、対策の例外となっている部分によく発生します。
個別テーマごとに見ていきましょう。

XSSの対策の注意

<>系はデフォルトで無害化されます。もちろんテンプレートに<%= raw @result %>のように意図的に脆弱に書いたらXSSは発生しますが、例外となってしまうパターンがあります。

javascript:alert()のようなjavascriptスキーマを利用したパターンが例外となっておりjavascriptが実行されてしまいます。

href=javascript:alert()

CSRFの対策の注意

POST以外全てのメソッドでトークンが要求されるため、トークンを検証させている限り脆弱にならないようになっています。
しかし、Ajaxは保証されていないためAjaxを介して更新処理を走らせる場合脆弱になる可能性があります。
また、スマホなどうまく通信ができずに処理がこけるのを避けるためにこのCSRF対策を外してしまい脆弱になるケースもありました。
対外的なサービスにおいては特に対策を外し無策にするのではなく、他の繊維元制御の施策を行うなど一定のリスク低減策を講じるべきと考えます。

SQL Injection対策の注意

SQL文をそのまま書くようなことないし心配いらないなんてことにはなりません。’) OR 1=1–‘のような割と平凡なSQL Injectionに脆弱となる場合があります。

脆弱なコード

User.where("name='#{params[:id]}'")

対策されたコード

User.where(name: params[:id]) 
User.where("name = ?", params[:id])

他にもdelete_allメソッド、destroy_allメソッドなどの削除系のメソッド、update_all メソッドは全くエスケープされないので注意しましょう。

見逃されやすい例として、lockメソッドも全くエスケープされないので注意しましょう。

User.where(id: params[:id]).lock(parmas[:lock])

 

HTTPSの強制化

config/environments/production.rb

Rails.application.configure do
  config.force_ssl = true 
end

セッション・フィクセーション

セッション・フィクセーションは認証のタイミングで使わせてログイン後も同じIDを利用している場合、攻撃者が知っているログイン前のセッションの値を使わせることができればその値で攻撃者もログインできてしまう脆弱性です。
対策はシンプルに1行でできます。要するにログインのタイミングでログイン前に知ることのできない新しい値に認証の状態を引き継いで仕舞えば良いのです。

reset_session

認証・認可の正統性や不正利得への防御は自分で考える必要性がある

どのリソースに対して誰がアクセス・操作していいかは開発する側・運用する側で適切な制限をかける必要性があります。フレームワークの発展により、XSSやSQLIのような脆弱性は減少傾向にありますがこの手の脆弱性はむしろ増加傾向にあるため、設計(テストを含む)は複雑化する顧客要求に対して体系的に漏れのなく行う必要があります。

send_fileによる機密ファイルのダウンロード

ファイル指定文字が有効なため「../../../etc/passwd」などを指定して機微情報が漏洩する可能性があります。

send_file(params[:filepath])

CVE-2019-16255 コマンド・インジェクション

Shell#test実装が、FileTestによって直接実装されたメソッドだけでなく、親クラスから継承されたメソッドの呼び出しを許可していることから、 Shell#[] および Shell#test にコード挿入の可能性があるという脆弱性です。

パスパラメータインジェクション Ruby 2.6未満

Pathnameに渡された値が “|”の最初の文字であるときにFile.readではIOのクラスを継承されるため、コマンドが実行されるという脆弱性がありますFile.read(“|echo hello”) はhelloが表示されます。

 

などなど以外と調べてみると、デフォルトのセキュリティはあくまで開発の手助けであって「セキュリティ対策どこまでやっているか、どこまでやらなければならないかを考える責任」と捉える必要があると考えるべきであることがわかります。

以上です。参考になれば幸いです。