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の新しいSafeBufferother_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ヘルパー、またはテンプレート内の<% %>以外の連結を使用した場合でも影響を受けます。

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

Source: https://habr.com/ru/post/J82726/


All Articles