Document ID: /fineweb-2-swissfilter-quality_10-filterrobots/filtered/03116.jsonl.gz/80

WebSockets
Michael Schneider
Die Schwachstelle Command Injection, beschrieben im OWASP Testing Guide unter OTG-INPVAL-013, ist ein seltener, aber gerne gesehener “Gast” – zumindest aus der Sicht des Angreifers. Hierbei ist der Angreifer in der Lage, Befehle der jeweiligen Programmiersprache über eine Eingabevariable einzuschleusen.
Ein praktisches Beispiel dafür ist ein Netzwerk-Tool wie eine Ping-Funktion, die es ermöglicht, ICMP-Echo Pakete an eine beliebige IP-Adresse zu senden. Wenn nun der Angreifer anstelle einer IP-Adresse die Eingabe erweitert, beispielsweise durch
<ip-pii>; whoami, und keine Validierung stattfindet, ist eine Command Injection möglich.
In diesem Fall kann der Angreifer seine Befehle direkt über die vorgesehene Funktion einschleusen.
Nun gibt es aber auch die Situation, bei welcher der Angreifer die Möglichkeit hat, eigenen Programm-Code auf dem Zielsystem zu platzieren und dies ausnutzen will, um Befehle auf Betriebssystemebene auszuführen. Das kann beispielsweise in Form eines PHP-Skripts sein.
Die Skriptsprache PHP kennt mehrere Funktionen, um Befehle auf Betriebssystemebene auszuführen. Weit verbreitet sind dabei die Funktionen
system() oder
exec(), welche auch in anderen Programmiersprachen wie C anzutreffen sind. Die Funktionen nehmen ein Kommando entgegen, führen dies aus und geben das Resultat der Ausführung zurück.
Auf einem gut gehärteten Webserver werden solche Funktionen, die über ein solches Schadenpotential verfügen, deaktiviert. Dazu muss in der Konfigurationsdatei php.ini die Einstellung
disable_functions entsprechend gepflegt werden. Ein Schwachpunkt des Blacklist-Ansatzes ist, dass nur die Funktionen deaktiviert werden, die dem Verwalter auch bekannt sind.
Wenn ein Angreifer nun eigene PHP-Skripte auf einem Server ausführen kann, versucht dieser herauszufinden, welche Funktion er nutzen kann, um Befehle auf Betriebssystemebene auszuführen. Dies kann am einfachsten über die Funktion
phpinfo() bewerkstelligt werden. Ein Verteidiger wird jedoch wiederum diese Funktion in die Liste der deaktivierten Funktion aufnehmen, um eine Preisgabe der Konfigurationseinstellungen zu verhindern. Dementsprechend muss der Angreifer andere Wege finden, um funktionierende Funktion zu identifizieren.
Wir haben dazu ein PHP-Skript shell_test.php (GitHub) geschrieben, das alle möglichen Funktionen zur Ausführung von Befehlen durchprobiert und eine entsprechende Rückmeldung gibt, ob die jeweilige Funktion auf dem Webserver genutzt werden kann. Das Skript ist für Linux-Systeme geschrieben, sollte aber auch auf Windows-Systemen grösstenteils funktionieren.
Das Skript selbst bietet jedoch keine Interaktivität; der auszuführbare Befehl muss mittels einer Variablen definiert werden. Daher haben wir dieses Skript weiter ausgebaut und ein einfaches Eingabeformular hinzugefügt: shell.php (GitHub). Das Formular ermöglicht es Befehle mit der Funktion, die auch vom Webserver unterstützt werden, ausführen zu lassen. Falls mehrere Funktionen verfügbar sind, kann die gewünschte Funktion in einer Dropdown-Liste ausgewählt werden. Bei der ersten Ausführung, respektive wenn keine Befehle angegeben werden, führt das Skript einige Basis-Abfragen durch wie das Auslesen der Linux-Kernelversion, des Benutzernamens, Verfügbarkeit von Netcat, Auflistung des aktuellen Verzeichnisses, Auflistung der laufenden Prozesse sowie der aktiven Netzwerkverbindungen.
Beim Testen des Skripts haben wir festgestellt, dass es auf Windows Systemen vorkommen kann, dass die Funktion
system() keinen Rückgabewert ausgibt und so wichtige Informationen nicht angezeigt werden. Die Ursache dafür ist, dass es Befehle/Programme gibt, welche die Rückgabe von erweiterten Information in den Standard-Error-Stream (stderr) zurückgeben. Dies ist unter anderem bei einigen PowerShell Cmdlets der Fall. Durch das Hinzufügen von
2>&1 ans Ende des Kommandos wird der Stream stderr an den Standard-Output-Stream (stdout) weitergeleitet. Damit können auch erweitere Informationen angezeigt werden. Der Aufruf von
system() sieht dann so aus:
system("command 2>&1", $return).
Die Skripte sind hier im Labs verlinkt und zusätzlich auf unserem GitHub Repository verfügbar. Wir freuen uns über jede Art von Feedback, ob die Skripts irgendwo zum Einsatz gekommen sind, für Änderungsvorschläge oder Feature Requests.
Unsere Spezialisten kontaktieren Sie gern!
Michael Schneider
Michael Schneider
Michael Schneider
Unsere Spezialisten kontaktieren Sie gern!
Weitere Artikel im Archiv