Rails 3のXSS保護

ほとんどの場合、Rails 3ではデフォルトでXSS攻撃に対する保護が追加されていることを既にご存じでしょう。 これは、これからは、レールが常にこれを行うため、 h



ヘルパーを使用してユーザー入力を手動でフィルタリングする必要がないことを意味します。



それにもかかわらず、すべてが最初の外観のように単純ではありません。 次のコードを検討してください。

<strong></strong>!



<%= tag(:p, some_text) %>

<%= some_text %>







上記の例では、HTMLタグの使用を含むいくつかの異なるケースがあります。 最初のケースでは、Railsは



という単語を囲む<strong>



タグをフィルタリングしないでください。 結果は明らかにユーザーが入力したものではありません。 2番目のケースでは、Railsは<p>



内のsome_text



必要があります(ただし<p>



全体ではありません)。 最後に、3番目のケースでは、親タグのsome_text



をフィルターする必要があります。



some_text



の結果が次のようになる場合:
<strong></strong>!



<p>&lt;script&gt;evil_js&lt;/script&gt;</p>

&lt;script&gt;evil_js&lt;/script&gt;




これがRailsアプリケーションのどこでも機能するように、 html_safe



と呼ばれる新しいアプローチを実装しました。 そのため、文字列がhtml_safe



である場合(文字列でhtml_safe



html_safe?



を呼び出すことで決定されます)、ERBはそのままにします。 行がhtml_safe



でないhtml_safe



、ERBはページに挿入する前にフィルタリングします。



def tag(name, options = nil, open = false, escape = true)

"<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe

end




ここで、Railsはタグを作成し、 teg_options



コンテンツteg_options



フィルタリングするteg_options



、タグの本文全体を安全としてマークします。 その結果、ユーザーが挿入したコンテンツはフィルターされますが、 <p>



</p>



は変更されません。



Koz プラグイン rails-xssの最初の実装ではすべての行に特別なフラグを追加することにより、指定された条件が満たされました。 Railsアプリケーションは必要な行を安全であるとマークしましたが、Rails自体は+



および<<



メソッドを再定義したため、行が変更された場合、結果の行はそれに応じてマークされます。



ただし、レールのパフォーマンスを最後にテストしたときに、各文字列の連結をオーバーライドすると、パフォーマンスがかなり低下することに気付きました。 さらに、このドロップは、テンプレート内の挿入数<%= %>



に直線的に依存していました。 大きなテンプレートはコストを吸収しませんでした(テンプレートごとに1つの呼び出し<%= %>



かのように)が、増加するだけでした。



この問題についてさらに考えた後、Ruby APIへの影響をさらに少なくして、まったく同じ機能をより生産的な方法で実装できることが明らかになりました(後にRubuniusのKoz、Jeremy、Evan Phoenixによって確認されました)。 問題自体は非常に複雑なので、古い実装の詳細については説明しませんが、新しいXSS保護の使用方法について説明します。 以前にKozプラグインを使用したことがあるか、Railsの予備リリースを既に使用している場合、今日のコミットはそれほど変わりません。



安全なバッファー



Rails 3では、ERBバッファーはActiveSupport::SafeBuffer



インスタンスです。 SafeBufferはString



継承し、 +



concat



<<



オーバーライドします。

単純な行でhtml_safe



を呼び出すと、 SafeBuffer



ラッパーが返されます。 SafeBuffer



タイムラインから継承されるため、Rubyはラッパーを非常に効率的に作成します(共有char*



内部ストレージを作成することによってのみ)。



この実装の結果、私はこの記録方法を見始めました:

buffer << other_string.html_safe



ここでRailsはSafeBuffer



の新しいSafeBuffer



other_string



、それを元のSafeBuffer



<<



メソッドにSafeBuffer



。このメソッドは(メソッド)新しいSafeBuffer



安全かどうかを確認します。 そのような場合、 safe_concat



が作成されました。元のconcatメソッドを使用するバッファーの新しいメソッドで、新しいSafeBuffer



を作成してセキュリティをチェックする必要がなくなりました。



同様に、 ActionView



concatおよびsafe_buffer



は、バッファーに対するconcatおよびsafe_buffer



プロキシメソッドです。そのため、チェックおよびフィルタリングを行わずにバッファーと組み合わせる必要があるHTMLテキストがある場合、ヘルパーでsafe_concatを使用できます。



ERBは、テンプレートの<% %>



safe_concat



<% %>



タグ以外のsafe_concat



場所でsafe_concat



内部的に使用します。 これは、今日の私のコミットでは、XSS保護コードがそのような場合のパフォーマンスに影響しないことを意味します(つまり、実際にはすべてのプレーンテキストをスキャンします)。



最後に、ERBはraw



ヘルパーを認識できるようになったため、 <%= raw some_stuff %>



ように記述すると、ERBはsafe_concat



に使用し、 safe_concat



の作成とhtml_safety



チェックをhtml_safety



ます。



結論



つまり、「XSS保護」とは次のことを意味します。

これに対して、元の実装では、XSSは各連結または文字列の+



影響しました。 アプリケーションがraw



ヘルパー、またはテンプレート内の<% %>



以外の連結を使用した場合でも影響を受けます。



それにもかかわらず、私はマイケル・コジアスキーに個人的な感謝を表明したいと思います。マイケル・コジアスキーは彼のアイデアの大まかなドラフトを提供してくれました。 彼女は働き、コンセプトを実証し、コミュニティはそれを十分にテストしました。 最後に、彼女は良いスタートを切った。



All Articles