Verschiedene Formen von Pufferüberläufen sind keine seltenen Schwachstellen, diesmal wurden sie in Methoden der PHP-Zip-Klasse entdeckt.
Die PHP-Zip-Archive-Klasse stellt einem Entwickler verschiedene Funktionen zum Umgang mit Zip-Dateien bereit. Der kann so beispielsweise sehr einfach im Zip-Archiv enthaltene Dateien lesen:
<?php
$zip = new ZipArchive;
if ($zip->open('test1.zip') === TRUE) {
echo $zip->getFromName('testfromfile.php');
$zip->close();
} else {
echo 'Fehler';
}
?>
In den »ZipArchive::getFromName()« – und »ZipArchive::getFromIndex()« -Methoden wurden nun kürzlich Schwachstellen entdeckt [1], die es einem entfernten Angreifer erlauben, Befehle mit höheren Rechten auf dem System auszuführen. Hierzu muss er eine speziell konstruierte Zip-Datei erzeugen und sie an sein Opfer weiterleiten. Das lässt sich beispielsweise über eine Web-Upload-Funktion erreichen. Die von dem Angreifer gewünschten Befehle führt der Host dann mit den Rechten der PHP-Applikation aus.
Der verantwortliche Programmierfehler befindet sich in einer Speicherallokation in der »php_zip_get_from()« -Funktion. Die ruft unter anderem folgende Befehle auf:
PHP_ZIP_STAT_PATH(intern, ZSTR_VAL(filename), ZSTR_LEN(filename), flags, sb); PHP_ZIP_STAT_INDEX(intern, index, 0, sb); len = sb.size; buffer = zend_string_alloc(len, 0); n = zip_fread(zf, ZSTR_VAL(buffer), ZSTR_LEN(buffer));
Entscheidend ist dabei, dass die »zend_string_alloc()« -Funktion einen Puffer auf dem Heap alloziert. Die Größe dieses Puffers richtet sich nach dem Wert der Variable »len« , der auf »sb.size« gesetzt wird. Bei »sb.size« handelt es sich um eine nicht mit Vorzeichen behaftete 64-Bit-Integer-Variable, die aus dem Zip-Archiv gelesen wird. Das Problem besteht nun darin, dass die »len« -Variable als vorzeichenbehafteter Integer deklariert ist. Hinzu kommt noch, dass seine Länge je nach System entweder 32 oder 64 Bit beträgt.
Der Angreifer hat dadurch die Möglichkeit, in der Zip-Datei eine Länge zu spezifizieren, die zu einem Überlauf der »len« -Variablen führt. Kritisch ist, dass der Programmcode keine Kontrolle eingebaut hat, um diesen Fall abzufangen. Da somit eventuell zu wenig Speicher auf dem Heap alloziert wird, kann der Angreifer damit einen Heap-Overflow-Fehler auslösen. Der Overflow tritt demnach auf, sobald das Programm aus der Zip-Datei liest.
Fehler dieser Art lassen sich ausnutzen, um den Programmablauf zu ändern, da der Angreifer dadurch Zugriff auf kritische Speicherbereiche des Programms hat, die es ihm erlauben, eigene Befehle auszuführen. Das Problem besteht hier immer darin, dass der allozierte Speicher nicht der eigentlichen Länge der Daten entspricht. Ein in Python geschriebener entsprechender Exploit [2] ist bereits entwickelt:
python exploit.py --bind-port 5555 http://1.2.3.4/upload.php
Betroffen von dieser Schwachstelle ist die Version 7.0.5, wobei möglicherweise auch ältere Versionen bereits anfällig gewesen sein könnten.
Infos
- Zip-Schwachstelle: https://bugs.php.net/bug.php?id=71923
- Exploit: https://github.com/dyntopia/exploits/tree/master/CVE-2016-3078






