コンテンツにスキップ

Index

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

説明

正規表現によるサービス拒否 (ReDoS) は、ユーザー入力が正規表現の構築に利用される場合に発生するセキュリティ脆弱性です。注意深く細工された正規表現パターンが存在する場合、アプリケーションは膨大な量のリソースを消費し、結果としてサービス拒否を引き起こす可能性があります。

悪意のあるパターンの例を以下に示します:

  • (a+)+
  • ([a-zA-Z]+)*
  • (a|aa)+
  • (a|a?)+
  • (.*a){x} for x > 10

そして、以下のコード例は不適切な実装の例です:

```java import java.util.regex.*;

public class RegexVulnerabilityExample { public static void main(String[] args) { // Function to read user input, potentially malicious String userInput = getUserInput();

   // Constructing a regular expression using user input
   Pattern pattern = Pattern.compile(userInput);

   // Using the regular expression
   Matcher matcher = pattern.matcher("input_string");
   boolean matchFound = matcher.find();

   if (matchFound) {
       System.out.println("Match found!");
   } else {
       System.out.println("No match found!");
   }

} ```

```swift import Foundation

func checkRegex(input: String, regex: String) {

 // Constructing a regular expression using user input
 do {
     let regex = try NSRegularExpression(pattern: userInput)
     let range = NSRange(location: 0, length: input.utf16.count)
     let matchRange = regex.rangeOfFirstMatch(in: input, options: [], range: range)

     if matchRange.location != NSNotFound {
         print("Match found!")
     } else {
         print("No match found!")
     }
 } catch {
     print("Error: Invalid regular expression")
 }

}

// Call the function with user input checkRegex(input: "input_string",regex: "redos") ```

```dart import 'package:flutter/material.dart'; import 'package:flutter/services.dart';

void main() { runApp(MyApp()); }

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Regex Vulnerability Example'), ), body: Center( child: ElevatedButton( onPressed: () { // Function to read user input, potentially malicious String userInput = getUserInput();

           // Constructing a regular expression using user input
           RegExp regex = RegExp(userInput);

           // Using the regular expression
           String inputString = "input_string";
           bool matchFound = regex.hasMatch(inputString);

           if (matchFound) {
             print("Match found!");
           } else {
             print("No match found!");
           }
         },
         child: Text('Test Regex'),
       ),
     ),
   ),
 );

} ```

推奨事項

正規表現によるサービス拒否 (ReDoS) の脆弱性を軽減するには、以下の推奨事項を考慮してください:

  • ユーザー入力への依存を最小限に抑える: 可能であれば、正規表現(regex)を構築するためのユーザー入力への依存を最小限に抑えてください。ユーザー入力に基づく動的な正規表現生成の必要性を減らす代替アプローチやデザインパターンを検討してください。潜在的に悪意のあるパターンへの露出を制限することで、ReDoS 脆弱性のリスクを大幅に減少させることができます。

  • ユーザー入力を検証する: 正規表現の構築にユーザーが提供する入力が、事前定義された基準に準拠していることを確認するための堅牢な検証メカニズムを実装してください。入力パターンの長さ、複雑さ、および構造を検証して、悪意を持って作成された表現のリスクを軽減します。最初に設定を検証することで、潜在的に有害なパターンを事前かつ予防的に特定し、拒否することができます。

  • レート制限とタイムアウトメカニズムを実装する: 正規表現の評価に関連する実行時間とリソース消費を制限するために、レート制限とタイムアウトメカニズムを適用してください。過度の計算負荷を防ぐために、正規表現の照合操作の複雑さと期間に適切な制限を設定します。正規表現の処理に合理的な制約を課すことで、ReDoS 攻撃のリスクを軽減し、さまざまな入力条件下でもアプリケーションの安定性を確保することができます。

```java import java.util.Scanner; import java.util.concurrent.*;

public class TimeoutDatabaseCheckExample { public static void main(String[] args) { // Create a Scanner object to read user input Scanner scanner = new Scanner(System.in);

     // Prompt the user to enter a regex pattern
     System.out.print("Enter a regex pattern: ");
     String regexPattern = scanner.nextLine();

     // Set the timeout duration in milliseconds
     long timeoutDuration = 1000; // 1 second

     // Create an ExecutorService with a single thread
     ExecutorService executor = Executors.newSingleThreadExecutor();

     // Submit the database check task to the executor
     Future<Boolean> future = executor.submit(() -> {
         // Perform the database check operation
         return checkDatabase(regexPattern);
     });

     try {
         // Wait for the result with timeout
         boolean recordExists = future.get(timeoutDuration, TimeUnit.MILLISECONDS);

         // Check if the record exists in the database
         if (recordExists) {
             System.out.println("Record exists in the database!");
         } else {
             System.out.println("Record not found in the database.");
         }
     } catch (TimeoutException e) {
         // Handle timeout
         System.out.println("Database operation timed out.");
     } catch (InterruptedException | ExecutionException e) {
         // Handle other exceptions
         e.printStackTrace();
     } finally {
         // Shutdown the executor
         executor.shutdown();
     }

     // Close the scanner
     scanner.close();
 }

 // Hypothetical database check function
 public static boolean checkDatabase(String regexPattern) {
     // Perform the database check operation here
     // For demonstration purposes, assume the record exists if the regex pattern matches
     return Pattern.compile(regexPattern).matcher("record_from_database").find();
 }

}

```

```swift import Foundation

// Function to perform database check func checkDatabase(forRegexPattern regexPattern: String) -> Bool { // Perform the database check operation here // For demonstration purposes, assume the record exists if the regex pattern matches let inputString = "record_from_database" return inputString.range(of: regexPattern, options: .regularExpression) != nil }

// Function to perform database check with timeout func checkDatabaseWithTimeout(forRegexPattern regexPattern: String, timeout: TimeInterval) -> Bool? { var result: Bool?

 // Create a dispatch group
 let group = DispatchGroup()

 // Create a dispatch queue
 let queue = DispatchQueue.global()

 // Enter the dispatch group
 group.enter()

 // Asynchronously perform the database check operation
 queue.async {
     result = checkDatabase(forRegexPattern: regexPattern)
     // Leave the dispatch group when the operation is complete
     group.leave()
 }

 // Wait for the operation to complete with timeout
 let dispatchResult = group.wait(timeout: .now() + timeout)

 // Check if the operation timed out
 if dispatchResult == .timedOut {
     // Return nil indicating timeout
     return nil
 }

 // Return the result of the database check operation
 return result

}

// Function to get regex pattern from user input func getRegexPatternFromUser() -> String { print("Enter the regex pattern:") guard let input = readLine() else { return "" } return input }

// Example usage let regexPattern = getRegexPatternFromUser() let timeoutDuration = 1.0 // Timeout duration in seconds

if !regexPattern.isEmpty { if let recordExists = checkDatabaseWithTimeout(forRegexPattern: regexPattern, timeout: timeoutDuration) { if recordExists { print("Record exists in the database!") } else { print("Record not found in the database.") } } else { print("Database operation timed out.") } } else { print("Invalid regex pattern.") }

```

リンク

標準

  • PCI_STANDARDS:
    • REQ_6_2
    • REQ_6_4
  • OWASP_MASVS_L1:
    • MSTG_PLATFORM_2
  • OWASP_MASVS_L2:
    • MSTG_PLATFORM_2
  • OWASP_MASVS_v2_1:
    • MASVS_CODE_4
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_4_1
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
    • CC_9_1
  • HIPAA_CONTROLS:
    • SECURITY212
    • SECURITY213
    • SECURITY255