Railsでのセキュリティリスクとその対策
代表的なセキュリティ攻撃とRailsでの対策を復習
CRSF(クロスサイトリクエストフォージェリ)
ログインした状態(セッションIDを維持した状態)を悪用してリクエストすること
ログイン後の利用者のみが利用可能なサービスを悪用したり(不正送金や商品購入、退会)、編集可能な情報を改竄できてしまう。
ログインした状態で不正なリンクをクリック。Webサイトを移り(クロス)、ユーザーの要求を偽って(フォージェリ)、悪意のあるリクエストが送信される
対策
GET/POSTを正しく使うこと
GETは情報読み出し、POSTは状態変化や何らかの作用を伴う操作GET以外のリクエストにはセキュリティトークンを使う
リクエストがユーザーの意図にあるものかを確認するために、同じWebアプリから生じたリクエストであることを証明するためのセキュリティトークンを発行、照合する
config.action_controller.default_protect_from_forgery
をtrueに設定すると自動的に実行(Rails5.2からデフォルトの設定)
form_with
などを使ったリクエストは自動でセキュリティトークン(authenticity_token
)が埋め込まれる
Ajaxリクエストへのセキュリティトークンの埋め込み
Ajaxリクエストでセキュリティトークンを送るには、JavaScriptが動く画面内にあらかじめセキュリティトークンを出力しておき、そのトークンを使ってX-CSRF-TokenというHTTPヘッダーで送る必要がある
出力はアプリのviewにある<%= csrf_meta_tags %>
fetch APIでAjaxリクエストを送信する場合は自分でトークンを埋め込む必要がある
fetch('/posts', { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content') } })
※XSS脆弱性があると、あらゆるCSRF保護が迂回されるので注意
XSS(クロスサイトスクリプティング)
テキストフォームなどの出力処理に問題がある場合に、スクリプトなどを埋め込まれてしまう
フィッシング詐欺(別サイトへ誘導)、セッションハイジャック(cookieを取得しなりすましができる)
対策
- RailsはXSS対策が標準で組み込まれていて、view処理を実行した際にHTMLタグに対してエスケープ処理が行われる。
&
,"
,<
,>
は、&
,"
,<
,>
にそれぞれ置き換えられる - HTMLのエスケープ回避したいときのメソッド(html_safe/raw(
<%==
))を使う場合は、脆弱性が発生することになるので注意。html_escapeを使ってエスケープ。 - ある程度タグをそのまま出したいが、危険なタグを出力したくない場合はSanitize Helperでホワイトリスト方式で制限。
SQLインジェクション
パラメーター操作でDBをさわれてしまう
RailではSQL文字をフィルタする仕組みがあり'
, "
, NULL, 改行をエスケープされるので、滅多に起こらなくなった。
Model.find(id)
やModel.find_by()
といったクエリでは自動的にこの対策が適用されるが、
where("...")
、connection.execute()
、Model.find_by_sql()
については手動でエスケープする必要あり
対策
- 文字列をサニタイズ(無害化)する安全な書き方を使う
# クエリメソッドに対してハッシュで条件を指定 users = User.where(name: params[:name]) # プレースホルダを利用 users = User.where('name = ?', params[:name])
LIKEは演算子は自動的にサニタイズされないので注意。sanitize_sql_likeを使う必要がある
参考
- Rails セキュリティガイド - Railsガイド
- 安全なウェブサイトの作り方:IPA 独立行政法人 情報処理推進機構
- [ActiveRecord] SQLインジェクションを防ぐ|Railsの練習帳
学んだことがあれば都度追加していく。