5

mod セキュリティ ルールhttps://github.com/SpiderLabs/owasp-modsecurity-crsを使用して、ユーザー入力データをサニタイズしています。ユーザー入力と mod セキュリティ ルールの正規表現との照合で、CPU が急上昇し、遅延が発生しています。全体として、さまざまなタイプの攻撃 (xss、badrobots、generic、および sql) をチェックするための 500 以上の正規表現が含まれています。request ごとに、すべてのパラメーターを調べて、これら 500 の正規表現すべてと照合します。Matcher.findパラメータを確認するために使用しています。この場合、一部のパラメーターが無限ループに陥ります。以下の手法を使用してこれに取り組みました。

長時間実行されている正規表現の一致をキャンセルしますか? .

ユーザーリクエストをサニタイズすると、約 500 ミリ秒かかり、CPU % が急上昇します。テスト スイート ランナーで visualvm.java.net を使用して分析しました。

CPU プロファイル出力

ここに画像の説明を入力

CPU使用率と負荷平均を減らすのを手伝ってください。

4

6 に答える 6

3

次の論文をご覧になることをお勧めします

あなたが説明したマッチングを行うためのより良い方法があります。基本的に、照合したい 500 のパターンを取得し、それを 1 つのサフィックス ツリーにコンパイルします。これにより、一度にすべてのルールに対して非常に効率的に入力を照合できます。

この論文は、このアプローチが、Dan Gusfield によって「Boyer-Moore Approach to Exact Set Matching」として説明されたと説明しています。

Boyer-Moore は、文字列マッチングのアルゴリズムとしてよく知られています。この論文では、セット マッチングのための Boyer-Moore のバリエーションについて説明しています。

于 2013-09-19T17:59:38.453 に答える
3

これが正規表現のパフォーマンス自体ではなく、問題の根本だと思います。

リクエストごとに、すべてのパラメーターを調べて、これら 500 の正規表現すべてと照合します

正規表現がどんなに高速であっても、これにはまだ多くの作業が必要です。あなたが持っているパラメーターの数はわかりませんが、ほんの少ししかない場合でも、リクエストごとに何千もの正規表現をチェックしています. それはあなたのCPUを殺す可能性があります。

正規表現をプリコンパイルおよび/または単純化してパフォーマンスを向上させるなどの明らかなこととは別に、正規表現チェックの量を減らすために次のことを行うことができます。

  1. パラメーターの型に基づいて、ユーザー入力の肯定的な検証を使用します。たとえば、一部のパラメーターが単純な数値でなければならない場合、悪意のある XML スクリプトが含まれているかどうかをチェックする時間を無駄にしないでください。[0-9]+ (または同様の単​​純なもの) と一致するかどうかを確認するだけです。存在する場合は問題ありません - 500 個の正規表現すべてのチェックをスキップします。

  2. 攻撃のクラス全体を排除できる単純な正規表現を見つけるようにしてください - 正規表現で共通のものを見つけてください。たとえば、特定の HTML タグの存在をチェックする正規表現が 100 個ある場合は、最初にコンテンツに少なくとも 1 つの HTML タグが含まれているかどうかをチェックします。そうでない場合は、すぐに 100 個の正規表現のチェックを節約できます。

  3. 結果をキャッシュします。Web アプリケーションで生成された多くのパラメーターは、繰り返し使用されます。同じ内容を何度も確認するのではなく、最終的な検証結果だけを覚えておいてください。DOS 攻撃を避けるために、キャッシュの最大サイズを制限するように注意してください。

また、通常、否定的な検証は簡単に回避できることに注意してください。誰かが悪意のあるコードの数文字を変更しただけで、正規表現が一致しなくなります。新しい攻撃から保護するために、正規表現の「データベース」を拡張する必要があります。肯定的な検証 (ホワイトリスト登録) にはこの欠点がなく、はるかに効果的です。

于 2013-09-23T11:31:11.793 に答える
3

可能であれば、(特にループ内で) 繰り返し (暗黙的に) コンパイルするのではなく、正規表現を一度コンパイルして保持しますjava.util.regex - Pattern.compile() の重要性を
参照してください 。詳細については。

于 2013-09-18T23:06:58.130 に答える
2

次のような表現は避けてください。

  • マルチライン
  • 大文字小文字を区別しません

おそらく、正規表現をグループ化することを検討し、ユーザー入力に応じて正規表現の特定のグループを適用することができます。

于 2013-08-31T21:14:47.240 に答える
1

正規表現が非常に多い場合は、トライ アルゴリズム ( http://en.wikipedia.org/wiki/Trie )を使用して (少なくとも一部を) グループ化できます。たとえば、 、、、およびの
ような正規表現がある場合、それらを単一の正規表現に組み合わせることができるという考えです。/abc[0-9-]//abde//another example//.something else//.I run out of ideas/

 /a(?:b(?:c[0-9-]|de)|nother example)|.(?:I run out of ideas|something else)/

この方法では、マッチャーは 4 回ではなく 1 回だけ実行する必要があり、上記の正規表現で共通の開始部分がどのように記述されているかにより、多くのバックトラックを回避できます。

于 2013-09-19T14:05:54.163 に答える
1

これらの 500 の中には、問題のある正規表現のサブセットが存在する必要があります。つまり、そのような正規表現

    String s = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB";

    Pattern.compile("(A+)+").matcher(s).matches();

完了するまでに何年もかかります。

したがって、あなたの場合、問題のあるすべての正規表現を問題のある入力とともにログに記録します。これらが見つかったら、これらの問題のあるいくつかの正規表現を手動で書き直して、元の正規表現と比較してテストできます。正規表現は、より単純で読みやすい Java 関数でいつでも書き直すことができます。

上記の問題を解決することはできませんが、別のオプションとして、高速 (場合によっては x20) でより制限された正規表現ライブラリを利用することもできます。Maven Centralで利用できます。

于 2013-09-20T14:37:24.027 に答える