動的な正規表現によるサービス拒否(ReDoS)

正規表現によるサービス拒否(ReDoS)

説明

TypeScriptやJavaScriptで外部入力に正規表現のパターンを決めさせると、攻撃者が実行に長い時間のかかるパターンを渡し、サービス拒否を引き起こすおそれがあります。

想定される影響

  • イベントループを長時間占有し、正規のリクエスト処理が遅れる可能性があります。
  • CPU使用量の増加により、アプリケーションのインスタンスが不安定になるおそれがあります。

対処方法

  • 可能なら、検討済みの正規表現リテラルや定数を使ってください。
  • 動的に選ぶ必要がある場合は、許可リストを使い、ユーザー入力をパターンの構文として直接解釈しないでください。
  • 実行時間が増大する可能性のある、入れ子の繰り返しや曖昧な選択肢を避けてください。

例

変更前

typescript
function search(value: string, pattern: string) {
  return new RegExp(pattern).test(value);
}

変更後

typescript
const allowedPatterns = new Map([
  ["username", /^[a-z0-9_]{3,32}$/i],
  ["ticket", /^TICKET-\d{4,10}$/],
]);

function search(value: string, patternName: string) {
  const pattern = allowedPatterns.get(patternName);
  if (!pattern) {
    throw new Error("Unsupported pattern");
  }
  return pattern.test(value);
}

説明:

  • 変更前: 呼び出し元が渡した文字列を、正規表現パターンとして直接解釈します。
  • 変更後: 名前で検討済みの固定パターンを選び、未登録の名前は拒否します。

参考資料