1. ホーム
  2. スクリプト・コラム
  3. ルビートピックス

rubyのダブルイコール==問題

2022-02-01 12:27:46

2日前、コードを書くときに、突然、プロジェクトのコードにXSSの脆弱性があるという警告を受けたので、すぐにページのコードをチェックするために報告されたURLによると、すぐに修正されたが、同じ問題は、2年前に議論し、一般的に言えば、比較的経験豊富な学生もこの点を知っておくべきですが、まだ書き出す必要性を感じる、もう一度ピットを踏む避けるために、他のパートナーを思い出させるために。

問題の根源

発見された脆弱性が現れる場所には、以下のようなスリムなコードがあります。

input class='xxx' value==params[:account]


問題は二重等号==で、slimとERBテンプレートでは(HAMLなど他のテンプレートは不明)、二重等号は実はRailsのrawヘルパーメソッドの略称なのです。

To insert something verbatim use the raw helper rather than calling html_safe:
<%= raw @cms.current_template %> <%# inserts @cms.current_template as is %>
or, equivalently, use <%==:
<%== @cms.current_template %> <%# inserts @cms.current_template as is %>


つまり、上記のコードは等価である。

input class='xxx' value=raw(params[:account])


Railsのドキュメントでrawメソッドがこのように説明されているところ。

This method outputs without escaping a string. Since escaping tags is now default, this can be used when you don't want Rails to automatically escape tags. This is not recommended if the data is coming from the user's input.


おそらく、このメソッドは、入力された文字列のタグフィルタリングやその他の処理をスキップして、文字列を直接HTMLに出力するのだろう。
つまり、この原因は、コードに誤って余分な等号が追加され、二重の等号になってしまい、ユーザーの入力を直接レンダリングするHTMLに出力してしまい、知らないうちにXSS脆弱性を残していたことにあることが明らかになったのです。そこで、修正方法は、単純に等号を削除することでした。

input class='xxx' value=params[:account]


これにより、Railsは引き続き:accountの入力パラメータを自動的にフィルタリングし、悪意のあるコンテンツを自動的にフィルタリングすることができます。

raw、String#html_safe、<%== %>
rawメソッドのドキュメントを見ながら、そのソースコードを一通り見てみたが、1行で構成された極めてシンプルなものであった。

# File actionview/lib/action_view/helpers/output_safety_helper.rb, line 16
def raw(stringish)
 stringish.to_s.html_safe
end


rawは、まず文字列的な引数を必ず文字列に変換してから、String#html_safeメソッドを呼び出しているだけです。そしてまた、String#html_safeのドキュメントでは、この2つのメソッドを注意深く使うことが繰り返し強調されています。

It is your responsibilty to ensure that the string contains no malicious content. This method is equivalent to the raw helper in views.


つまり、要約すると、以下の3つのコードの書き方は、すべて等価であり、すべて安全ではありません。

input class='xxx' value==params[:account]
input class='xxx' value=raw(params[:account])
input class='xxx' value=params[:account].html_safe


では、実際にリッチテキストエディタで編集したようなHTMLコンテンツを含むコンテンツを出力する必要がある場合、どのように安全性を確保するのでしょうか。
解決方法は簡単で、ドキュメントで推奨されているsanitizeヘルパーメソッドを使用するだけです。

It is recommended that you use sanitize instead of this method (html_safe).
(#sanitize)Sanitizes HTML input, stripping all tags and attributes that aren't whitelisted.


または、他のサードパーティのgemを使用してフィルタリングを行います。

概要

  1. 二重引用符の略語を理解できない他の人 (プロジェクトで Rails を使い始めたばかりの人など) による乱用を避けるため、二重引用符は使用しないでください。
  2. 生ヘルパーやString#html_safeメソッドは可能な限り使用せず、#sanitizeを使用する。
  3. XSS脆弱性を含む幅広いセキュリティ脆弱性を迅速かつ効率的に検出できるbrakemanなどのツールを用いて、スキャンを自動化する。