Zum Inhalt springen
Bringen Sie Ihre Internet-Intelligenz zum Blühen | Sichern Sie sich 20 % Rabatt auf Censys Search Teams oder Solo-Jahrespläne mit dem Code Spring24 bis 31.5.2009 | Jetzt sparen
Blogs

CVE-2021-41773: Apache Path Traversal

Einführung

Am 22. Juli 2021 fusionierte der beliebte Apache HTTPD-Webserver in einer übergeben. die die Funktion ap_getparents() mit einer neuen Funktion namens ap_normalize_path(). Diese neue Funktion wurde als effizientere und standardisierte Methode für die Normalisierung von Rohpfaden im URI einer HTTP-Anfrage angepriesen. Am 15. September wurden diese Änderungen in den Stamm verschmolzen und mit der Version 2.4.49 gekennzeichnet.

Was ist das Problem?

Am 29. September, vierzehn Tage nach der Veröffentlichung von Version 2.4.49, meldete ein cPanel-Ingenieur namens Ash Daulton, dass ein Angreifer diese neue Logik nutzen könnte, um einen Path-Traversal-Exploit auszuführen, der bei Erfüllung bestimmter Konfigurationsbedingungen zur Remotecodeausführung (RCE) führen könnte.

Der Apache v2.4.49 aus der Vogelperspektive

Censys fand 75.085 eindeutige Hosts mit 136.469 Diensten, die sich mit dieser einfachen Suchabfrage als Apache HTTPD Version 2.4.49 identifizierten. Und obwohl die meisten Installationen dieses Dienstes nicht von Haus aus anfällig sind, hat Censys einige Anbieter identifiziert, die eine laxe Konfiguration ausliefern, die den Fehler ermöglicht. Einer dieser Anbieter, Control Webpanel, mit über 22.000 Hosts unter CentOS, scheint aufgrund seiner Konfiguration ein wahrscheinliches Ziel für diesen Angriff zu sein.

Einige Forscher haben festgestellt, dass nach dieser Sicherheitslücke aktiv gescannt wird, obwohl keine endgültige Aussage darüber gemacht wurde, ob die Scans zu einer aktiven Ausnutzung führen.

Standardmäßig wird die folgende Zugangskontrollkonfiguration eingerichtet:

DocumentRoot "/usr/local/apache2/htdocs"
<Directory />
    AllowOverride none
    Require all denied
</Directory>
<Directory "/usr/local/apache2/htdocs">
    AllowOverride None
    Require all granted
</Directory>

Wenn ein Nutzer Folgendes anfordert "/index.html"würde der Server das DocumentRoot (/usr/local/apache2/htdocs) und anhängen "/index.html" zu, was zu der Datei "/usr/local/apache2/htdocs/index.html". Da eine Regel den Zugriff auf alle Dateien innerhalb des "/usr/local/apache2/htdocs" würde der Antrag genehmigt werden.

Würde hingegen ein Nutzer eine Anfrage stellen "/../../../../foobar"würde der Server die "/../../../.." über ap_normalize_path() und fügen das Ergebnis an die DocumentRoot, was zu "/usr/local/apache2/htdocs/foobar"; eine Datei, die im Dateisystem nicht existieren sollte.

Da aber ap_normalize_path() prüft nicht korrekt auf Doppelpunkte, wenn es als ascii-hex kodiert ist, z.B., "%2e%2e"wird diese Normalisierungsfunktion die Punkte darstellen und den Pfad nicht entfernen. Aber auch nach dem Rendern der Doppelpunkte sollten die Standard-Zugriffskontrollen die Ausführung der meisten Pfadübergänge verhindern. Nur wenn ein Administrator explizit die Konfiguration "Require all granted" auf einem geschützten Verzeichnis, dass die Dinge aus dem Ruder laufen können; d.h.,

<Directory />
    AllowOverride none
    Require all granted
</Directory>

Diese fehlerhafte Konfiguration, kombiniert mit Apache's mod_cgi Modul, hat das Potenzial, diese einfache Pfadumgehungsschwachstelle in einen vollwertigen RCE-Angriff (Remote Command Execution) zu verwandeln.

Ein tieferer Blick

Während diese neue ap_normalize_path() Funktion hier eine Rolle spielt, ist sie nicht gerade die verursachen der Schwachstelle. Es ist eher so, dass diese Funktion dazu beigetragen hat, ein bereits bestehendes Problem ans Licht zu bringen. Ich meine, der Beweis liegt im Namen: Es heißt "normalize", nicht "sanitize". Aber diese Änderung hatte unbeabsichtigte Nebeneffekte für andere Funktionen, die sich auf diese frühere Iteration, die die Daten bereinigte, verlassen haben.

Das eigentliche Problem ist in einer abstrahierten Funktion des Betriebssystems versteckt, die apr_filepath_merge()und genauer gesagt, wie diese Funktion aufgerufen wird. Doch bevor wir darüber sprechen wie diese Funktion ist genannt.müssen wir verstehen was diese Funktion tut. In der Dokumentation heißt es, dass diese Funktion funktioniert:

"Zusätzlichen Dateipfad in den zuvor bearbeiteten Wurzelpfad einfügen"

Das Hauptziel dieser Funktion ist es, einen Basispfad (wie eine apache DocumentRoot) und einen Pfad, der in der URI einer Anfrage übergeben wird, und fügen sie zusammen, um die Eingabe-URI auf einen voll qualifizierten Pfad auf dem Server abzubilden.

Hier ist eine sehr einfache Übersetzung dessen, was diese Funktion tut:

final_path = split("/usr/local/apache2/htdocs", "/") // result: ["usr", "local", "apache2", "htdocs"]
tokens     = split("usr/bin/..", "/")  // result: ["usr", "bin", ".."]
​
for each path_part in tokens:
    if path_part == "..":
        // remove the last segment in the final_path array
        final_path[length(final_path)] = null
    else:
        final_path.append(path_part)
​
return final_path.Join("/") // returns /usr/local/apache2/htdocs/usr 

Wenn diese Funktion vom Standard-Apache-Handler aufgerufen wird (ap_core_translate()), wird zuerst der Pfad der Eingabeanforderung genommen und der erste Schrägstrich übersprungen, um zu zeigen, dass es sich um einen relativen Pfad von der DocumentRoot. Wenn der Server zum Beispiel mit DocumentRoot "/usr/local/apache2/htdocs"und die eingehende Anfrage lautet:

GET /foo/bar HTTP/1.0

Die apr_filename_merge() wird folgendermaßen aufgerufen:

char * path = "/foo/bar";
char * root = "/usr/local/apache2/htdocs";
char * output;
​
while (*path == '/') {
    ++path;
}
​
int rv = apr_filepath_merge(&output, root, path, APR_FILEPATH_SECUREROOT, r->pool));

Dies würde dazu führen, dass die output Puffer enthalten: /usr/local/apache2/htdocs/foo/bar. Der Grund dafür, dass diese Aufforderung an apr_filepath_merge ist nicht anfällig für den Path-Traversal-Angriff ist hauptsächlich auf die Flagge APR_FILEPATH_SECUREROOT gesetzt wird. Dies führt dazu, dass die Funktion fehlschlägt, wenn der Pfad, den wir versuchen hinzuzufügen, außerhalb des Verzeichnisses "/usr/local/apache2/htdocs" liegt.

Aber nicht jede Anfrage wird vom Standard-Handler bearbeitet, einige werden von Modulen bearbeitet. Zum Beispiel kann der mod_alias Modul muss zunächst den Eingabepfad mit einem Basispfad abgleichen, und dieser Basispfad muss zu einem echten Pfad erweitert werden. Nehmen Sie die folgende Konfiguration:

<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/"
</IfModule>

Dies besagt, dass jeder eingehende URI-Pfad, der mit "/cgi-bin/" beginnt, eigentlich in das Verzeichnis "/usr/local/apache2/cgi-bin/" gehen sollte. Die Art und Weise, wie der URI in eine Datei übersetzt wird, unterscheidet sich also von dem, was in ap_core_translate(). Erstens, mod_alias iteriert über eine Liste von alias_entrymit dem folgenden Format:

alias_entry entry = {
    .real = "/usr/local/apache2/cgi-bin/",
    .fake = "/cgi-bin/",
};

Er schaut sich das Präfix des eingehenden Anforderungspfads an, und wenn es mit dem fake Element, d. h. "/cgi-bin/", wird der Inhalt des eingehenden URI an das real Element, das seinerseits zum Aufruf von apr_filepath_merge:

char * output_path = NULL;
​
prefix_len = alias_matches(request->uri, alias->fake);
​
if (prefix_len > 0) {
    // Append the contents of the request URI after the prefix to the end of the "real" element
    output_path = apr_pstrcat(request->pool, alias->real, request->uri + prefix_len, NULL);
    // if alias->real  IS "/usr/local/apache2/cgi-bin/"
    // AND
    // if request->uri IS "/cgi-bin/../../../etc"
    // THEN
    // output_path     IS "/usr/local/apache2/cgi-bin/../../../etc"
}
​
if (output_path != NULL) {
    char * newpath = NULL;
    int ret = apr_filepath_merge(&newpath, "/usr/local/apache2", output_path, 0, p);
    
    if (newpath != NULL && ret == APR_SUCCESS) {
        return newpath; // newpath IS /usr/etc
    }
}

Wie Sie vielleicht schon bemerkt haben, ist die APR_FILEPATH_SECUREROOT Flagge wurde nicht an apr_filepath_merge wie es in ap_core_translate(), was bedeutet, dass der Aufruf nicht fehlschlägt, selbst wenn der URI Doppelpunkte enthält - also mod_alias ist anfällig für den Path-Traversal-Angriff.

Aber um es ganz klar zu sagen: Nur weil diese Funktion das Traversal ermöglicht, muss der Server so konfiguriert sein, dass er den Zugriff auf das durchsuchte Verzeichnis erlaubt. Mit dem obigen Beispiel von "/usr/etc"muss ein Administrator dem Server ausdrücklich den Zugriff auf das Verzeichnis "/usr/etc" mit der Einstellung "Require all granted" erlauben. Andernfalls scheitert die Anfrage an einer zweiten Prüfung in der Funktion ap_run_access_checker_ex().

Warum ist das wichtig?

Wenn die Bedingungen stimmen, kann ein Angreifer diese Pfadumgehungsschwachstelle ausnutzen, um einen beliebigen Befehl mit denselben Berechtigungen wie der Benutzer, der den Dienst ausführt, auszuführen. Ein Angreifer kann dann diesen Zugriff nutzen, um erweiterte administrative Rechte zu erlangen, wenn auf dem System nicht gepatchte lokale Sicherheitslücken vorhanden sind.

Da diese Sicherheitslücke leicht auszuführen ist und Proof-of-Concept-Exploits in den sozialen Medien und auf anderen Plattformen leicht zu finden sind, müssen wir davon ausgehen, dass böswillige Akteure bereits damit begonnen haben, anfällige Server in freier Wildbahn auszunutzen.

Was kann ich dagegen tun?

  • Administratoren sollten sofort auf HTTPD Version 2.4.51 aktualisieren.
  • Überprüfen Sie, ob Ihr Host in der Liste der potenziell gefährdeten Server aufgeführt ist.
  • Censys ASM-Kunden wurden per E-Mail über alle Hosts benachrichtigt, die als anfällig identifiziert wurden. Darüber hinaus können ASM-Kunden verwundbare Anlagen über den folgenden Link finden.

Aktualisierung 10-07-2021 (7:30 PM EST): Die Entwickler des CentOS Webpanel haben eine Aktualisierung vorgenommen. Manuelles Ausführen /scripts/update_cwp wird der Apache-HTTPD-Server auf die Version 2.4.48 zurückgesetzt.

Über den Autor

Mark Ellzey
Senior Security Researcher Alle Beiträge von Mark Ellzey
Mark Ellzey ist ein leitender Sicherheitsforscher bei Censys. Vor seiner jetzigen Tätigkeit war Mark Ellzey über 22 Jahre lang als Netzwerksicherheitsingenieur und Softwareentwickler für verschiedene Internetdienstleister und Finanzinstitute tätig.
Lösungen für das Management von Angriffsflächen
Mehr erfahren