Ausführbarer Regulärer-Ausdruck-Fehler
Beschreibung
Ausführbarer Regulärer-Ausdruck-Fehler tritt auf, wenn Anwendungen Regex-Engines verwenden, die ausführbaren Code innerhalb von Mustern erlauben. Einige Regex-Implementierungen (wie Perls /e-Modifikator oder Rubys gsub mit Evaluation) können beliebigen Code während des Musterabgleichs oder der Substitution ausführen. Wenn Benutzereingaben diese Regex-Operationen beeinflussen, können Angreifer bösartigen Code injizieren und ausführen.
Risiko
Angreifer können beliebigen Code auf dem Server durch manipulierte Regex-Muster oder Ersetzungsstrings ausführen. Dies führt zu vollständiger Systemkompromittierung, Datendiebstahl und lateraler Bewegung. Die Schwachstelle ist besonders gefährlich, weil Regex-Muster oft als potenzielle Code-Injection-Vektoren übersehen werden. Die Angriffsfläche umfasst sowohl Musterkonstruktion als auch Ersetzungsstring-Behandlung.
Lösung
Vermeiden Sie Regex-Engines mit Code-Ausführungsfunktionen bei der Verarbeitung von Benutzereingaben. Deaktivieren Sie Evaluationsmodifikatoren (/e in Perl, Verwendung von \e in der Ersetzung). Verwenden Sie nicht-evaluierende Substitutionsmethoden. Escapen Sie Benutzereingaben vor dem Einbeziehen in Regex. Erwägen Sie die Verwendung einfacherer String-Operationen anstelle von Regex. Implementieren Sie strikte Eingabevalidierung vor der Regex-Verarbeitung.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Integrität | Bereich: Code-Ausführung Beliebiger Code läuft mit Anwendungsprivilegien. |
| Vertraulichkeit | Bereich: Datendiebstahl Angreifer können auf alle Anwendungsdaten zugreifen. |
| Verfügbarkeit | Bereich: Systemkompromittierung Vollständige Kontrolle über das System. |
Beispielcode + Lösungscode
Verwundbarer Code
#!/usr/bin/perl
# VERWUNDBAR: Perl-Regex mit /e-Modifikator
# Benutzereingabe in Ersetzung mit Evaluation verwendet
sub transform_vulnerable {
my ($text, $pattern, $replacement) = @_;
# Der /e-Modifikator evaluiert $replacement als Code!
$text =~ s/$pattern/$replacement/ee;
return $text;
}
# Angriff: $replacement = 'system("rm -rf /")'
my $user_text = "Hello World";
my $user_pattern = "World";
my $user_replacement = $ARGV[0]; # Angreifer-kontrolliert!
# Wenn user_replacement ist: system('cat /etc/passwd')
# Führt es den system-Befehl aus!
my $result = transform_vulnerable($user_text, $user_pattern, $user_replacement);
# VERWUNDBAR: Doppelte Evaluation
sub process_vulnerable {
my $input = shift;
my $template = shift;
# Doppeltes /e erlaubt komplexe Angriffe
$input =~ s/\{\{(\w+)\}\}/$template->{$1}/eeg;
}
# VERWUNDBAR: Muster selbst ist benutzerkontrolliert
sub search_vulnerable {
my ($haystack, $user_pattern) = @_;
# Benutzer kontrolliert Regex-Muster
# Angriff: (?{system('whoami')})
if ($haystack =~ /$user_pattern/) {
return 1;
}
return 0;
}
# VERWUNDBAR: Ruby gsub mit Block-Evaluation
def transform_vulnerable(text, pattern, replacement)
# Wenn replacement benutzerkontrolliert und evaluiert
text.gsub(/#{pattern}/) { eval(replacement) }
end
# VERWUNDBAR: String-Interpolation in Ersetzung
def replace_vulnerable(text, user_input)
# Benutzereingabe in Ersetzungsstring
text.gsub(/pattern/, "#{eval(user_input)}")
end
# VERWUNDBAR: Dynamischer Regex mit Benutzereingabe
def match_vulnerable(text, user_pattern)
# Benutzer kontrolliert Regex - Code-Injection möglich
regex = Regexp.new(user_pattern)
text.match(regex)
end
<?php
// VERWUNDBAR: preg_replace mit /e-Modifikator (veraltet in PHP 5.5, entfernt in PHP 7)
function transformVulnerable($text, $pattern, $replacement) {
// Der /e-Modifikator evaluiert Ersetzung als PHP-Code!
return preg_replace("/$pattern/e", $replacement, $text);
}
// Angriffbeispiel:
// $pattern = ".*"
// $replacement = "system('id')"
// VERWUNDBAR: preg_replace_callback unsicher verwenden
function processVulnerable($text, $user_code) {
return preg_replace_callback(
'/\{\{(\w+)\}\}/',
function($matches) use ($user_code) {
// Evaluiert Benutzercode!
return eval("return $user_code;");
},
$text
);
}
// VERWUNDBAR: create_function (veraltet, entfernt in PHP 8)
function filterVulnerable($array, $user_condition) {
$func = create_function('$x', "return $user_condition;");
return array_filter($array, $func);
}
?>
Lösungscode
#!/usr/bin/perl
use strict;
use warnings;
# SICHER: Kein /e-Modifikator - einfache String-Ersetzung
sub transform_safe {
my ($text, $pattern, $replacement) = @_;
# Spezielle Regex-Zeichen in Benutzereingabe escapen
$pattern = quotemeta($pattern);
$replacement = quotemeta($replacement);
# Kein /e-Modifikator - literale Ersetzung
$text =~ s/$pattern/$replacement/g;
return $text;
}
# SICHER: Hash-Lookup statt eval verwenden
sub process_safe {
my ($input, $variables) = @_;
$input =~ s/\{\{(\w+)\}\}/$variables->{$1} \/\/ ''/g;
return $input;
}
# SICHER: Erlaubte Muster mit Whitelist
sub search_safe {
my ($haystack, $user_pattern) = @_;
# Nur alphanumerische Muster erlauben
unless ($user_pattern =~ /^[\w\s]+$/) {
die "Ungültiges Muster";
}
# Für literalen Abgleich escapen
my $safe_pattern = quotemeta($user_pattern);
if ($haystack =~ /$safe_pattern/) {
return 1;
}
return 0;
}
# SICHER: index() statt Regex für einfache Suchen verwenden
sub find_safe {
my ($haystack, $needle) = @_;
return index($haystack, $needle) != -1;
}
# SICHER: Keine Evaluation in Ersetzung
def transform_safe(text, pattern, replacement)
# Muster für literalen Abgleich escapen
safe_pattern = Regexp.escape(pattern)
# Literale Ersetzung, keine Evaluation
text.gsub(/#{safe_pattern}/, replacement)
end
# SICHER: Hash-Substitution verwenden
def template_safe(text, variables)
text.gsub(/\{\{(\w+)\}\}/) do |match|
key = $1
# Lookup in Hash, kein eval
variables[key] || ''
end
end
# SICHER: Muster validieren und einschränken
def match_safe(text, user_pattern)
# Sichere Zeichen mit Whitelist
unless user_pattern.match?(/^[\w\s.*?+]+$/)
raise "Ungültige Musterzeichen"
end
# Musterkomplexität begrenzen
if user_pattern.length > 100
raise "Muster zu lang"
end
# Timeout für Regex-Ausführung verwenden
Timeout.timeout(1) do
text.match(Regexp.new(user_pattern))
end
rescue Timeout::Error
raise "Muster dauerte zu lange"
end
# SICHER: Einfache String-Methoden wenn möglich verwenden
def find_safe(text, search)
text.include?(search)
end
<?php
// SICHER: preg_replace_callback mit sicherer Behandlung verwenden
function transformSafe($text, $pattern, $variables) {
// Benutzermuster escapen
$safePattern = preg_quote($pattern, '/');
return preg_replace_callback(
"/$safePattern/",
function($matches) use ($variables) {
// Lookup, niemals eval
return $variables[$matches[0]] ?? $matches[0];
},
$text
);
}
// SICHER: Template mit explizitem Variablen-Lookup
function templateSafe($text, array $variables) {
return preg_replace_callback(
'/\{\{(\w+)\}\}/',
function($matches) use ($variables) {
$key = $matches[1];
// Nur Lookup von vordefinierten Variablen
return array_key_exists($key, $variables)
? htmlspecialchars($variables[$key])
: '';
},
$text
);
}
// SICHER: Regex-Muster vor Verwendung validieren
function searchSafe($text, $userPattern) {
// Erlaubte Zeichen mit Whitelist
if (!preg_match('/^[\w\s.*?+\[\]()]+$/', $userPattern)) {
throw new InvalidArgumentException('Ungültiges Muster');
}
// Länge begrenzen
if (strlen($userPattern) > 100) {
throw new InvalidArgumentException('Muster zu lang');
}
// Spezielle Regex-Zeichen escapen bei literaler Suche
$safePattern = preg_quote($userPattern, '/');
return preg_match("/$safePattern/", $text);
}
// SICHER: str_replace für einfache Fälle verwenden
function replaceSafe($text, $search, $replace) {
return str_replace($search, $replace, $text);
}
// SICHER: Modernes PHP - anonyme Funktionen statt create_function
function filterSafe($array, callable $predicate) {
return array_filter($array, $predicate);
}
// Verwendung
$filtered = filterSafe([1, 2, 3, 4], fn($x) => $x > 2);
?>
Ausgenutzt in der Praxis
Server-Kompromittierung
Perl-Webanwendungen mit /e-Modifikator für RCE ausgenutzt.
CMS-Schwachstellen
Content-Management-Systeme mit Regex-Verarbeitung kompromittiert.
Template-Injection
Template-Engines mit Regex-Evaluation kompromittiert.
Tools zum Testen/Ausnutzen
- Burp Suite — Regex-Injection testen.
- Benutzerdefinierte Skripte zum Testen der Regex-Evaluation.
- Statische Analysatoren, die /e-Modifikator-Verwendung erkennen.
CVE-Beispiele
- CVEs von Perl-Anwendungen mit /e-Modifikator.
- PHP-Anwendungen mit preg_replace und /e.
Referenzen
- MITRE. "CWE-624: Executable Regular Expression Error." https://cwe.mitre.org/data/definitions/624.html
- Perl-Sicherheitsdokumentation zu /e-Modifikator-Gefahren.