Aller au contenu

Index

Déni de service par expression régulière

Description

Le déni de service par expression régulière (ReDoS) est une vulnérabilité de sécurité qui se produit lorsque l'entrée de l'utilisateur est utilisée pour construire une expression régulière. En présence d'un motif d'expression régulière soigneusement conçu, l'application peut dépenser une quantité substantielle de ressources, ce qui peut entraîner un déni de service.

Voici quelques exemples de motifs malveillants :

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

Et les exemples de code suivants illustrent des implémentations incorrectes :

```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'),
       ),
     ),
   ),
 );

} ```

Recommandation

Pour atténuer les vulnérabilités de déni de service par expression régulière (ReDoS), prenez en compte les recommandations suivantes :

  • Minimiser la dépendance aux entrées utilisateur : Chaque fois que possible, minimisez le recours aux entrées fournies par l'utilisateur pour construire des expressions régulières (regex). Envisagez des approches alternatives ou des modèles de conception qui réduisent le besoin de générer dynamiquement des regex en fonction des entrées de l'utilisateur. En limitant l'exposition à des modèles potentiellement malveillants, vous pouvez réduire considérablement le risque de vulnérabilités ReDoS.

  • Valider les entrées utilisateur : Mettez en œuvre des mécanismes de validation robustes pour vous assurer que les entrées fournies par les utilisateurs pour la construction de regex respectent des critères prédéfinis. Validez la longueur, la complexité et la structure des modèles d'entrée pour atténuer le risque d'expressions créées de manière malveillante. En validant les entrées dès le départ, vous pouvez identifier et rejeter de manière préventive les modèles potentiellement dangereux.

  • Mettre en œuvre des mécanismes de limitation de débit et de délai d'attente : Appliquez des mécanismes de limitation de débit et de délai d'attente (timeout) pour restreindre le temps d'exécution et la consommation de ressources associés à l'évaluation des regex. Fixez des limites appropriées sur la complexité et la durée des opérations de correspondance regex afin d'éviter une surcharge de calcul excessive. En imposant des contraintes raisonnables sur le traitement des regex, vous pouvez atténuer le risque d'attaques ReDoS et assurer la stabilité de votre application dans diverses conditions d'entrée.

```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.") }

```

Liens

Normes

  • 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