2021年8月24日 現場Rails Chapter6-7-3 インジェクションに注意する(その1)
インジェクション
インジェクションとは、Webアプリケーションに悪意のあるスクリプトやパラメータを入力し、それが評価される時の権限で実行させる攻撃です。ユーザーがデータを入力するところは注意が必要です。
- XXS(クロスサイトスクリプティング)
- SOLインジェクション
- rubyコードインジェクション
- コマンドラインインジェクション
XXS
XXSとは、ユーザーに表示するコンテンツに悪意のあるスクリプト(主にJavaScript)を仕掛け、悪意のある操作を行う攻撃方法です。
ブラウザ画面参考例: 実際にサンプルページで確認してみた!クロスサイトスクリプティング(XSS)の危険性!
情報漏洩の参考図: クロスサイトスクリプティングとは?仕組みと事例から考える対策
例:&
,"
,<
,>
→ &
,"
,<
,>
エスケープとは
HTML文の中では「<」「>」「&」「"」といった文字は特別な意味を持ちます。その為、HTMLタグを含む文字列をそのまま出力してしまうと違う意味になってしまいます。その為、特別の意味を持つ文字が含まれる文字列を文字列として出力されたい場合には、特別な意味を持つ文字をエスケープした上で出力する必要があります。
※Railsのビューではユーザーの入力した文字列を出力する際に自動的にHTMLをエスケープします。
※エスケープした場合が文字列で表示されます。
以下に、エスケープする場合としない場合の違いをまとめます。
【エスケープする】
htmlタグなどを特殊文字に置き換えます。特殊文字に置き換えることによって、画面上にhtmlタグを文字列として出力できます(画面上にはhtmlタグが見えてるけど、そのhtmlタグは文字列として認識されます。そのhtmlに意味はないです)。
【エスケープしない】
htmlをダイレクトに受け取ります。htmlとして受け取るので、画面上でhtmlが実行されます。
SQLインジェクション
SQLインジェクションとは、アプリケーションが想定しないSQL文を実行させることにより、データベースシステムを不正に操作する攻撃方法です。
Railsではクエリメソッドに対して、ハッシュ形式で条件指定をすることで安全に処理をしてくれます。
users = User.where(name: params[:name])
実行したい内容がハッシュ形式で記述できない場合(クエリメソッドにSQL文を直接記述したい場合)は文字列を直接埋め込むのではなくて、プレースホルダーを利用します。
users = User.where(`name = ?`, params[:name])
params[:name]が?
に代入されるイメージです。その際にエスケープ処理を行ってくれます。
SQL: WHERE 1 の意味
#SELECT * FROM table_name;と同じ意味になります。 #つまり、以下のWhere以降はTrueになる条件式です。 SELECT * FROM table_name WHERE 1 SELECT * FROM table_name WHERE 1 = 1
これは、
WHERE 1 →MySQLでは整数の1はTRUEと等価になります。
WHERE 1 = 1 →(1 = 1) を評価すると当然TRUEなので WHERE 1とWHERE 1 = 1は全く同じ結果になります。
つまり、WHEREで指定する条件が必ず真であるならば、すべての行が選択されるので、WHERE を指定しない、SELECT * FROM table_name;と結果は同じになります。
エスケープ処理を行わず(スキップして)出力する方法
Railsでは、HTML特殊文字は自動的にエスケープされます。自動でエスケープ処理が行われのは便利なのですが、エスケープ処理を行いたくない場合もあります。文字列ではなく、HTMLやJSタグとしてつまりコードとして認識させたい場合にエスケープをスキップする処理を行います。
例)エスケープされない→ htmlをダイレクトに受け取る。htmlとして受け取るので、htmlが実行される。
①Stringクラスで用意されているhtml_safeメソッドを用いる方法
ただし、nil には html_safe メソッドが存在しないため、例外が起きます。
文字列.html_safe
②ActionView::Helpers::OutputSafetyHelperクラスで用意されているrawメソッドを用いる方法
この方法では、nilの例外が起きません。また、raw ヘルパーを使うことで、エスケープ処理の回避が明確になるのも利点の一つです。
#rawメソッドを使うことで引数に指定された文字列はエスケープ処理がされずに出力されます。
raw(文字列)
③Slimの==を用いる方法
この方法だと、nil の例外は起きません。また、エスケープ処理の回避が明確になります。
#=(単一等号)はescape_htmlメソッドによるHTMLエスケープが行われます div = "<a href='https://google.com'>Google</a>" #==(二重等号)を用いて、HTMLエスケープを行いたくない場合 div == "<a href='https://google.com'>Google</a>"
まとめ
Slimの==を用いる方法が一番良いとされる方法です。
Sanitize
Sanitizeは、ある程度タグをそのまま出したいものの危険なタグは出力しないようにしたい場合に用います。ホワイトリスト形式で制限します。ホワイトリストフィルタでは特定の値のみが許可され、それ以外の値はすべて拒否されます。
サニタイズ(Sanitize)とは、危険なコードやデータを変換または除去して無力化する処理です。
sanitize(文字列 [, オプション])
オプション
:tags - 許可するHTMLタグ名
:attributes - 許可するHTML属性名
:scrubber - スクラブ指定
scrubberはより自由に許可するタグや属性をカスタマイズできます。
参照
HTML特殊文字のエスケープ
https://www.javadrive.jp/rails/template/index7.html
【Ruby】array.map(&:method)を理解する
https://qiita.com/k-penguin-sato/items/420d7487b28b5d58cac4
SQLデータ分析入門#3『WHERE句を理解する』 https://qiita.com/piyoSakai/items/44bc21178349103e2d45
エラーの向こうへ SQL:WHERE 1 の意味
https://tech.mktime.com/entry/32
大ちゃんの駆け出し技術ブログ
https://sakitadaiki.hatenablog.com/entry/2021/02/04/082402
Pikawaka 【Rails】 whereメソッドを使って欲しいデータの取得をしよう!
https://pikawaka.com/rails/where
クロスサイトスクリプティング
https://www.tohoho-web.com/ex/xss.html
rawヘルパー
https://railsdoc.com/page/raw
ビューについて -Rails ドキュメント-の結果をエスケープしないで出力
https://railsdoc.com/view
RailsのHTMLテンプレートエンジン、Slimの基本的な記法
https://qiita.com/mom0tomo/items/999f806d083569529f81
サニタイズ
https://railsdoc.com/page/sanitize
html_safe、raw、「<%==」の比較
https://qiita.com/iwamot/items/74c2bd9ebd3ac6458837
おもしろwebサービス開発日記 -h以外のサニタイズ系メソッド-
https://blog.willnet.in/entry/20080826/1219760222
Sanitize
https://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html