Magento Security + Magento Coding Standard:
Disallow Insecure Functions exec(), shell_exec(), system() etc.


Mit dem Magento Coding Standard und Code Sniffer Update auf v3 werden unsichere Funktionen wie exec(), shell_exec(), system() usw. nicht mehr zugelassen sein. Das bedeutet, dass jede Erweiterung, die eine dieser Funktionen verwendet, nicht im Magento Marketplace gelistet werden wird. Da diese Funktionen ein großes Sicherheitsproblem darstellen können, ist es sicherlich eine gute Entscheidung von Magento, diesen Schritt zur Verbesserung der Magento-Sicherheit zu gehen.
Was bedeutet dies für Magento-Entwickler? Welche Alternativen zu diesen unsicheren Funktionen stehen zur Verfügung, um bestimmte Funktionen zu implementieren, bei denen Systembefehle auf Serverebene ausgeführt werden müssen?

Und wie gut sind diese Alternativen in Bezug auf die Sicherheit?
Was muss beachtet werden, um sicherzustellen, dass Funktionen zur Ausführung von Systembefehlen auf sichere und nicht ausnutzbare Weise realisiert werden?

Warum sind PHP exec(), shell_exec(), system() etc. unsicher und sollten vermieden werden,
nicht nur in Magento?


Werfen wir einen Blick auf die PHP-Dokumentation für exec():

exec() führt einen angegebenen Befehl (command) aus.

Ja, kurz und einfach, das ist jeder Befehl, der per CLI auf dem Server verfügbar ist. Ein ziemlich mächtiges Tool, das einer PHP-Anwendung den vollen Umfang der CLI-Möglichkeiten zur Verfügung stellt!
Grundsätzlich ist die Verwendung von exec() nicht unbedingt problematisch, z. B. wenn ein fixer Befehl ausgeführt wird, der von der Anwendung benötigt wird, und ein Hacker diesen Befehl nicht manipulieren kann.

Sobald exec() aber verwendet wird, um einen Befehl abhängig von Benutzereingaben auszuführen oder die Möglichkeit besteht den auszuführenden Befehl auf irgendeine Weise zu manipulieren, wird für jeden Hacker ein Traum wahr. Damit öffnet man potentiell die Tür sehr weit für Angriffe bzw. zur Kompromittierung einer Anwendung bzw. des Servers. Es ist also Vorsicht geboten, wenn man diese Funktion im Programm-Code oder einer Magento-Erweiterung verwendet. Man sollte also Folgendes beachten:
Mit großer Macht kommt große Verantwortung.

Denken Sie voraus, auch wenn eine Funktion zum Zeitpunkt der Entwicklung sicher zu sein scheint, wird der Sicherheitsalptraum möglicherweise erst später kreiert, wenn eine Funktion von jemandem geändert oder erweitert wird, der die mit exec() verbundenen Risiken nicht kennt oder übersieht.
Als Daumenregehl sollte gelten: Eine Funktion mit exec() sollte nie als sicher angesehen werden. Schon bei der Entwicklung sollte man stets das Thema Sicherheit bedenken und nach Alternativen suchen, mit denen mögliche Angriffsvektoren vermieden werden können, indem die mit exec() verbundenen Risiken adressiert oder eingeschränkt werden.

Welche sicheren Alternativen gibt es für PHP exec(), shell_exec(), system()?

Unter Sicherheitsaspekten ist es natürlich der beste Weg, eine Lösung zu finden, die die Anforderungen erfüllt, ohne dass durch die PHP-Anwendung Befehle auf System- / Serverebene ausgeführt werden. Aber das ist nicht in jedem Fall gewollt / machbar. Welche Möglichkeiten haben wir also, um Systembefehle auszuführen und gleichzeitig sicherzustellen, dass sie auf sichere Weise ausgeführt werden?

Sicherere Alternativen zu exec(): escapeshellarg () + escapeshellcmd()


Ein Blick in die PHP-Dokumentation für exec() gibt uns bereits einen Hinweis:

Warnung:
Falls Sie es erlauben, dass Daten von Usereingaben an diese Funktion weitergereicht werden, sollten Sie escapeshellarg() oder escapeshellcmd() verwenden. Bei Verwendung dieser Funktionen stellen Sie sicher, dass kein Benutzer Ihr System überlisten kann, beliebige Kommandos auszuführen

Oh, perfekt, einfach durch ersetzen der kritischen Funktion durch eine dieser Alternativen wird alles gut und sicher, da verhindert wird, dass beliebige Befehle ausgeführt werden?
Nein, leider ist es nicht ganz so einfach ...

Was diese Funktionen anders machen als exec(), besteht darin, folgende Zeichen zu maskieren, wenn sie im auszuführenden Befehl gefunden werden:

&#;`|*?~<>^()[]{}$\, \x0A and \xFF. ' and "

Bzw. hinzufügen von einfachen Anführungszeichen um Strings um ein Argument eines auszuführenden Befehls bzw. von einfachen Anführungszeichen um ein Argument eines auszuführenden Befehls.

Es ist auf jeden Fall eine gute Idee, diese Funktionen anstelle von exec() zu verwenden, um die Sicherheit zu verbessern.

ABER:
Vorsicht, beide hier genannten Funktionen können die thematisierten Risiken nicht vollständig mitigieren!
Werden einfach nur diese Funktionen verwendet, bleibt eine Anwendung möglicherweise weiterhin anfällig für Command Injection Attacken. Es gibt auch damit noch Möglichkeiten, die zusätzlichen Schutzmaßnahmen zu umgehen. Das heißt, es ist immer noch möglich, dass beliebige Befehle ausgeführt werden können, auch wenn escapeshellarg() und escapeshellcmd() verwendet werden.
Eine gute Übersicht an Command Injection Exploits und Schwachstellen inklusive Beispielen gibt es hier.
(Bitte nur zum Verständis des Themas verwenden, nicht um, ähh, Dummheiten anzustellen ;-) )

Man sollte weiterhin beachten, dass diese beiden Funktionen möglicherweise die Ausführung von legitimen Befehle verhindern, z. B. falls Zeichen benötigt werden, die von diesen Funktionen maskiert werden.

Symfony Process Komponente als Alternative für unsichere PHP Funktionen

Da Magento das Symfony Framework verwendet, ist eine weitere Alternative verfügbar, die als Ersatz für unsichere PHP-Funktionen wie exec(), passthru(), shell_exec() und system() vorgesehen ist, die sogenannte Process Komponente. Wie man in der Dokumentation sehen kann, bietet die Symfony Process Component einige zusätzliche Funktionalitäten um Commands auf Systemebene zu handlen und wendet ebenfalls escaping an.

Leider wurde die Process Komponente nicht als vollständiger Schutz gegen Command Injection Angriffe konzipiert. Auch bei dieser Alternative ist es möglich, dass böswillige / willkürliche Befehle von einem Angreifer der den Befehl manipulieren kann ausgeführt werden. Escapezeichen werden nur für Argumente verwendet, die als Array übergeben wurden. Nicht für Befehle, die als einzelne Zeichenfolge übergeben werden und unverändert ausgeführt werden.

Der Heilige Gral der sicheren Anwendungsentwicklung: Eingabevalidierung


Wie oben beschrieben, bietet uns keine der Alternativen ein ausreichendes Schutzniveau, das in jedem Szenario als schlüsselfertige Lösung gegen Command Injection Angriffe fungiert und die Ausführung von Systembefehlen durch PHP ermöglicht.
Es ist dennoch empfehlenswert, mindestens eine oder eine Kombination der oben genannten Funktionen als Ersatz für exec() oder andere unsichere Funktionen zu verwenden. Jedoch sollte man sich niemals vollständig auf sie verlassen, wenn es darum geht, das Risiko der Ausführung von Systembefehlen zu verringern. Man sollte nicht davon ausgehen, dass diese Funktionen für die Sicherheit einer Anwendung ausreichen.
Stattdessen sollte man die Brille eines Angreifers aufsetzen und sich immer fragen, ob ein Befehl, den eine Anwendung an den Server weiterleitet, manipuliert werden kann. Und falls ja, eigenen Schutzmaßnahmen einbauen um den Angriffsvektor zu schließen. Es gilt wie immer bei der Entwicklung sicherer Anwendungen: Benutzereingaben sind als "dirty" und nicht vertrauenswürdig einzustufen!

Eingabevalidierungen sollten für alle Benutzereingaben ergänzt werden, die in einem System-Befehl verwendet werden. Und zwar stets so strikt wie möglich. Damit nur der benötigte Befehl und wirklich nur der tatsächlich benötigte Befehl durch die Anwendung ausgeführt werden kann.

Nur zur Vollständigkeit:
Eine Eingabevalidierung aus Sicherheitsgründen muss immer serverseitig erfolgen.
Eine clientseitige Validierung durch JavaScript kann ebenfalls hilfreich sein. Dies dient jedoch der Benutzerfreundlichkeit und nicht als Sicherheitsmaßnahme, da es auch selbst von einem nicht allzu erfahrenen Hacker leicht umgangen werden kann.

Fazit

Die Entscheidung von Magento, unsichere Funktionen wie exec() im Magento Marketplace zu verbieten, ist definitiv eine gute Entscheidung. Das bloße Erzwingen der Nichtnutzung dieser Funktionen reicht jedoch nicht aus, um eine Sicherheitsstufe zu gewährleisten, die für eine E-Commerce-Seite die vertrauliche Daten verarbeitet erforderlich ist.
Dies ist jedoch nicht das Ziel von Coding Standards. Coding Standards können keine 100% ige Sicherheit garantieren oder Sicherheitslücken schließen.
Mit dem aktualisierten Magento Coding Standard wird die Aufmerksamkeit der Entwickler jedoch zumindest auf einige potenziell große Sicherheitslücken gelenkt. Letztendlich ist es aber immer Sache des Entwicklers, ein angemessenes Maß an Sicherheit zu gewährleisten, wobei eine geeignete und sichere Implementierung von der jeweiligen Situation abhängt.