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

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

説明

ユーザーが指定したパターンから正規表現を直接生成すると、攻撃者が処理に時間のかかる非効率な式を選べる場合があります。処理が長時間リソースを消費し、サービスの停止につながるおそれがあります。

想定される影響

  • 非効率なパターンによるサーバーの遅延や停止
  • 応答の悪化や不安定化による、正規ユーザーの利用への支障

対処方法

  • 実行コストを検討したパターンをコードに定義し、ユーザー入力をそのままパターンにしないでください。
  • 動的な選択が必要な場合は、検討済みのパターンの許可リストから選び、検査対象の文字列長も制限してください。
  • recheckなどの解析ツールは、確認を補助するために使ってください。パターンを定数にするだけでは、実行コストは制限できません。

例

変更前

javascript
// 変更前
function search(text, pattern) {
  // ユーザー入力をそのまま正規表現パターンに使います。
  const regex = new RegExp(pattern);
  return regex.test(text);
}

// 使用例
search("username", userInputPattern);

変更後

javascript
// 変更後
function search(text) {
  // 固定の正規表現を使います。
  const regex = /^\w+$/;
  return regex.test(text);
}

// 動的に選ぶ場合は、選択できるパターンを制限します。
function searchSafe(text, pattern) {
  // あらかじめ定義したリストのパターンだけを使います。
  const allowedPatterns = ["^\\w+$", "^\\d{4,8}$"];
  if (!allowedPatterns.includes(pattern)) {
    throw new Error("허용되지 않은 패턴입니다.");
  }
  const regex = new RegExp(pattern);
  return regex.test(text);
}

説明:

  • 変更前: ユーザー入力でパターンを直接決めています。複雑なパターンは処理に時間がかかり、サービス拒否につながるおそれがあります。
  • 変更後: 検討済みの固定パターンや許可リストを使い、攻撃者が負荷の高いパターンを直接指定できないようにします。

参考資料