悪意のあるコードを正規表現に入れる方法はありますか?


138

公開Webページに正規表現検索機能を追加したい。出力をHTMLエンコードする以外に、悪意のあるユーザー入力を防ぐために何かする必要がありますか?

Googleの検索は、逆の問題を解決する人々-正規表現を使用して悪意のある入力を検出-には興味がありません。私のシナリオでは、ユーザー入力正規表現です。

.NET(C#)のRegexライブラリを使用します。


4
これは、使用する言語や正規表現ライブラリによって異なる場合があります。
aschepler

さらに読む資料:OWASPでのReDoS、Wikipedia
joeytwiddle '10 / 10/20

回答:


216

サービス拒否の懸念

正規表現に関する最も一般的な懸念は、指数関数的、または超指数関数的になる病理学的パターンによるサービス拒否攻撃です。—そして、解決するのに永遠にかかるようです。これらは特定の入力データでのみ表示される場合がありますが、一般的にはこれを問題としないデータを作成できます。

これらのどれがコンパイル時に検出される可能性があるため、これらがどれであるかは、使用している正規表現コンパイラがどれほど賢いかに依存します。再帰を実装するRegexコンパイラには通常、非進行をチェックするための組み込みの再帰深さカウンタがあります。

正規表現マッチングに関するRuss Coxの優れた2007年の論文は、単純で高速である可能性があります(ただし、Java、Perl、PHP、Python、Rubyなどでは遅い)は、ほとんどすべての最新のNFAがHenry Spencerのコードから派生しているように見える方法について述べています、パフォーマンスが大幅に低下しますが、トンプソンスタイルのNFAにはそのような問題はありません。

DFAで解決できるパターンのみを認める場合は、そのようにしてそれらをコンパイルすることができ、パターンはより高速に、場合によってはより高速に実行されます。ただし、これには時間がかかります。コックス紙はこのアプローチとそれに付随する問題について言及しています。それはすべて、古典的な時間と空間のトレードオフに帰着します。

DFAを使用すると、DFAの作成(およびより多くの状態の割り当て)に多くの時間を費やしますが、NFAを使用すると、DFAを同時に複数の状態にすることができるため、実行に多くの時間を費やします。

サービス拒否ソリューション

おそらく、宇宙の熱死でレースの敗北にあるこれらのパターンに対処する最も合理的な方法は、実行に許可される最大時間を効果的に配置するタイマーでそれらをラップすることです。通常、これはほとんどのHTTPサーバーが提供するデフォルトのタイムアウトよりもはるかに小さくなります。

これらの実装にはさまざまな方法がありalarm(N)、Cレベルでの単純なものから、何らかの種類のtry {}ブロックによるアラームタイプの例外のキャッチまで、タイミング制約が組み込まれた特別に作成された新しいスレッドを生成するすべての方法があります。

コードコールアウト

コードコールアウトを許可する正規表現言語では、コンパイルする文字列に対してこれらを許可または禁止するためのメカニズムを提供する必要があります。コードコールアウトが使用している言語のコードのみである場合でも、それらを制限する必要があります。外部コードを呼び出すことができる必要はありませんが、可能であれば、はるかに大きな問題が発生します。

たとえば、Perl use re "eval";では、現在のスコープでアクティブな特別な字句スコーププラグマがない限り、文字列補間から作成された正規表現にコードコールアウトを含めることはできません(実行時にコンパイルされるため)。

このようrm -rf *にして、たとえばのようなシステムプログラムを実行するためのコードコールアウトに誰も忍び込むことはできません。コードコールアウトはセキュリティに非常に敏感であるため、Perlはすべての補間された文字列でデフォルトでそれらを無効にし、それらを再度有効にするために邪魔をする必要があります。

ユーザー定義の\ P {roperties}

以下のような-そこのUnicodeスタイルのプロパティに関連する1つ以上のセキュリティに敏感な問題が残っている\pM\p{Pd}\p{Pattern_Syntax}、または\p{Script=Greek}その- サポートしていることを表記することを、いくつかの正規表現のコンパイラに存在します。

問題は、これらのいくつかでは、可能なプロパティのセットがユーザー拡張可能であることです。あなたには、いくつかの特定のnamepaceで名前の関数に実際のコードのコールアウトされているカスタムプロパティを持つことができる手段、のようなもの\p{GoodChars}\p{Class::Good_Characters}。あなたの言語がそれらをどのように扱うかは、一見の価値があるかもしれません。

サンドボックス化

Perlでは、Safeモジュールを介してサンドボックス化されたコンパートメントにより、名前空間の可視性を制御できます。他の言語も同様のサンドボックステクノロジーを提供しています。そのようなデバイスが利用可能な場合は、信頼できないコードの実行を制限するように特別に設計されているため、それらを調べることをお勧めします。


4
NFA-> DFA変換は、指数状態の爆発を引き起こし、時間DoSを空間DoSに変換するだけでなく、指数数の状態を生成する時間コストも発生します。
バリーケリー

しかし、おそらく彼は正規表現機能全体を必要としないでしょう。Googleの
systemsfault

1
@バリーかなり正しい。私は、NFAの部分をインクリメンタルにコンパイルして同等のDFAを作成するという彼の論文の1つに記載されているラスコックスの戦略を考えていましたが、大きすぎる場合は破棄します。しかし、トンプソンがNFAと同等であることを証明したとしても、DFAに特効薬はありません。それは、どこかでパイパーを支払う必要があるためです。より多くのスペースをオペレーティングシステムに頼むのに費やした時間と、それに付随するページテーブルのセットアップコストは、場合によってはバランススケールをさらに反対に動かし、時間からスペースへの変換を魅力的にすることができます。
tchrist

20

tchristの優れた答えに加えて、「正規表現」ページを書いた同じRuss Coxもコードをリリースしました!re2は、O(length_of_regex)ランタイムと構成可能なメモリ使用制限を保証するC ++ライブラリです。Google内で使用されるので、Googleコード検索に正規表現を入力できます。つまり、これは戦闘テスト済みです。


2
確かにそうです。モジュールを使用してre2をPerlのregexエンジンにスワップできます。可能な場合はre2を使用し、そうでない場合はPerlを使用します。かなりうまくいきます。
tchrist


6

あなたはこの論文を読みたくなるでしょう:

安全でないコンテキスト切り替え:生存可能性ための正規表現の接種このペーパーでは、正規表現エンジン(PCREなど)で問題が発生する可能性について詳しく説明していますが、問題の理解に役立つ場合があります。


1
これは、GNU libc regcomp(3)コードに関するセキュリティ勧告です:securityreason.com/achievement_securityalert/93 なんとタイムリーです!少なくともLinuxでは、この脆弱性は簡単に実証できます
。grep

5

あなたはマッチング自体についてだけでなく、どのようにマッチングを行うかについて心配する必要があります。たとえば、入力が正規表現エンジンに向かう途中で何らかの評価フェーズまたはコマンド置換を通過する場合、パターン内で実行されるコードが存在する可能性があります。または、正規表現構文で埋め込みコマンドが許可されている場合は、それにも注意する必要があります。質問で言語を指定しなかったので、すべてのセキュリティへの影響が何であるかを確認するのは難しいです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.