Command Injection in Python: Beispiele und Prävention
Rubaiat Hossain
21. Dezember 2023
0 Min. LesezeitObwohl Python für seine Einfachheit und Vielseitigkeit bekannt ist, kann es schwierig sein, Python-Programme sicher zu halten, wenn Sie oder andere Teammitglieder während der Entwicklung Sicherheits-Best Practices vernachlässigen.
Außerdem verwenden Sie beim Entwickeln einer Python-Anwendung wahrscheinlich Bibliotheken oder andere Open-Source-Projekte. Diese Ressourcen können jedoch zusätzliche Sicherheitsprobleme verursachen, durch die Ihr Programm für Exploits wie Command Injection anfällig wird. Diese kritische Sicherheitslücke kann für Ihre Python-Anwendungen verheerende Folgen haben. Durch Command Injection können Angreifer in Ihren Anwendungen unbefugt Befehle ausführen, was zu Datenschutzverletzungen, einer Kompromittierung des Systems und anderen böswilligen Aktivitäten führen kann.
In diesem Artikel erfahren Sie alles über Command Injection und darüber, wie sich diese Schwachstelle in Ihren Programmen äußern kann. Außerdem lernen Sie gängige Sicherheits-Best Practices kennen, mit denen Sie Ihre Python-Apps vor Command-Injection-Angriffen schützen.
Was ist Command Injection?
Bei einer Command Injection kann ein Angreifer beliebige Systembefehle ausführen, indem er sie in ein anfälliges Programm einschleust. Die Schwachstelle entsteht in der Regel, wenn eine Anwendung nicht vertrauenswürdige Nutzerdaten (z. B. aus Formularen, Cookies und HTTP-Headern) an eine System-Shell übergibt.
Verschiedene Szenarien können zu Command-Injection-Schwachstellen führen, etwa wenn ungeprüfte Nutzereingaben an Systembefehle übergeben werden. Angreifer können schädliche Argumente einschleusen, wenn eine Anwendung Nutzereingaben direkt an die Befehlszeile übergibt. Ein Beispiel dafür ist die Command-Injection-Schwachstelle in bestimmten Versionen von MLflow (einer Plattform für den Lebenszyklus von Machine Learning). Ursache dieser Schwachstelle sind unzureichende Prüfungen der Methode predict() in der Datei backend.py.
Außerdem können Anwendungen Befehlszeichenfolgen dynamisch anhand verschiedener Parameter, darunter auch Nutzereingaben, zusammensetzen. Fehlen bei diesem Vorgang angemessene Prüfungen und Validierungen, lassen sich diese Befehle ausnutzen.
Leider werden die Auswirkungen von Systembefehlen leicht missverstanden. Der falsche Einsatz oder die fehlerhafte Konfiguration von Systembefehlen kann schnell zu Command-Injection-Schwachstellen führen. So sind beispielsweise betroffene Versionen von PaddlePaddle, einer Plattform für paralleles, verteiltes Deep Learning, über die Methode os.system in fs.py anfällig für Command Injection.
Die Folgen von Command Injection sind schwerwiegend. Angreifer können sich unbefugten Zugriff verschaffen, sensible Daten entwenden oder das System beschädigen. Solche Sicherheitsverletzungen können für Unternehmen finanzielle Verluste, einen Reputationsschaden und rechtliche Konsequenzen nach sich ziehen. Auch Nutzern, deren vertrauliche Informationen gestohlen werden, kann erheblicher Schaden entstehen.
Command Injection in Python verstehen und beheben
Command Injection zählt weiterhin zu den schwerwiegendsten Bedrohungen für die Anwendungssicherheit. Um Python-Anwendungen vor Command Injection zu schützen, müssen Sie diese Schwachstellen genau verstehen und proaktive Maßnahmen ergreifen, um potenzielle Exploits abzuwehren.
Häufige Schwachstellen, die zu Command Injection führen
Im folgenden Abschnitt werden einige häufige Schwachstellen beschrieben, die in Python zu Command Injection führen.
Vom Nutzer kontrollierte Eingaben ausnutzen
Vom Nutzer kontrollierte Eingaben sind Daten oder Werte, die Nutzer direkt bereitstellen, etwa Formulardaten, URL-Parameter oder Eingaben über die Befehlszeile. Verarbeitet eine Anwendung solche Eingaben ohne angemessene Validierung und verwendet sie direkt zur Ausführung von Systembefehlen, ist sie anfällig für Command-Injection-Angriffe.
Sehen Sie sich dazu dieses Python-Beispiel an:
Dieser Code fordert den Nutzer über die input-Methode zur Eingabe eines Befehls auf. Die so vom Nutzer kontrollierte Eingabe wird anschließend ohne Validierung oder Prüfung direkt an die Methode os.system zur Ausführung übergeben. Die Nutzereingabe wird also unmittelbar vom Befehlsinterpreter des Systems verarbeitet und ausgeführt:

In diesem einfachen Beispiel werden grundlegende Shell-Befehle verwendet, um den Code zu testen. Angreifer würden jedoch wahrscheinlich gefährliche Befehle einsetzen, die eine Rechteausweitung, Datenverlust und andere unerwünschte Folgen verursachen.
Unsichere Verwendung von Systembefehlen und des subprocess-Moduls
Systembefehle und das subprocess-Modul in Python ermöglichen die Ausführung von Shell-Befehlen und bieten leistungsstarke Möglichkeiten zur Interaktion mit dem zugrunde liegenden Betriebssystem. Bei unsachgemäßer Verwendung können sie jedoch Command-Injection-Schwachstellen verursachen, insbesondere in Verbindung mit vom Nutzer kontrollierten Eingaben.
Sehen Sie sich zur Veranschaulichung diese Schwachstelle an:
Hier werden Nutzereingaben direkt mit der Methode subprocess.run ausgeführt, wobei shell=True aktiviert ist. Das Argument shell=True bedeutet, dass die System-Shell den Befehl ausführt. Dadurch sind das Verketten von Befehlen und andere potenziell schädliche Aktionen möglich:

Da die Nutzereingabe weder validiert noch bereinigt wird, ist das Skript Command-Injection-Angriffen ausgesetzt. Potenziellen Angreifern wird damit im Grunde die Kontrolle über die System-Shell überlassen.
Risiken durch dynamische Befehlserstellung
Python-Programme erstellen und führen häufig dynamisch Systembefehle aus, insbesondere wenn variable Daten wie Nutzereingaben eingebunden werden müssen. Fehlen bei dieser dynamischen Erstellung jedoch angemessene Sicherheitsmaßnahmen, entstehen dadurch Command-Injection-Schwachstellen.
Sehen Sie sich das folgende Python-Codebeispiel an:
Dieser Code fordert den Nutzer zur Eingabe eines Parameters auf und erstellt anschließend eine Befehlszeichenfolge, in die diese Eingabe direkt übernommen wird. Der Befehl soll die Nutzereingabe ausgeben. Da die Eingabe jedoch vor ihrer Einbindung in den Befehl weder validiert noch bereinigt wird, ist der Code anfällig für Command Injection:

Ein Angreifer kann diese Schwachstelle ausnutzen, indem er eine Nutzlast mit Befehlstrennern oder Steueroperatoren eingibt. Ein Nutzer könnte beispielsweise Hello; ls -l eingeben. Dadurch würde zuerst "Hello" ausgegeben und anschließend aufgrund des Semikolons als Befehlstrenner der Inhalt des aktuellen Verzeichnisses aufgelistet. Das ist ein einfaches Beispiel, doch Angreifer können auch schädlichere Befehle eingeben, etwa rm -rf / oder cat /etc/shadow.
Unsichere Verwendung von eval()
Die Python-Funktion eval() wertet eine Zeichenfolge dynamisch als Python-Ausdruck aus und gibt das Ergebnis zurück. Sie ist zwar ein leistungsstarkes Werkzeug, kann aber auch erhebliche Risiken mit sich bringen. Sehen Sie sich das folgende Python-Codebeispiel an:
Die Verwendung von eval() in diesem Code ist gefährlich, da die Funktion nicht nur mathematische oder einfache Python-Ausdrücke, sondern beliebigen Python-Code auswertet. Hinzu kommt, dass Python über Module wie os mit dem zugrunde liegenden System interagieren kann.
Ein Angreifer kann beispielsweise Folgendes eingeben:
Die obige Beispieleingabe importiert das Modul os und führt anschließend auf Unix-basierten Systemen den Befehl ls aus, der den Verzeichnisinhalt auflistet. Das ist eine einfache Demonstration. Böswillige Akteure können jedoch schädlichere Befehle eingeben, um Dateien zu manipulieren, Daten zu entwenden oder sich sogar unbefugten Zugriff auf das System zu verschaffen:

Command-Injection-Schwachstellen entschärfen
Angesichts der potenziell schwerwiegenden Auswirkungen von Command Injection auf Ihre Python-Anwendungen ist es entscheidend, dieses Problem wirksam anzugehen. Glücklicherweise können Sie zahlreiche Command-Injection-Schwachstellen früh im Softwareentwicklungszyklus (SDLC) proaktiv entschärfen, indem Sie die folgenden Richtlinien befolgen.
Eingaben angemessen validieren und bereinigen
Eingaben von Nutzern oder externen Quellen dürfen niemals als vertrauenswürdig gelten. Validieren Sie Eingaben stets anhand erwarteter Muster und bereinigen Sie sie:
Beachten Sie, dass das obige Beispiel lediglich nicht alphanumerische Zeichen aus der Eingabe entfernt. Dadurch wird zwar verhindert, dass Angreifer Befehle verketten können, in einer echten Anwendung benötigen Sie jedoch wahrscheinlich deutlich strengere Bereinigungsregeln, zum Beispiel die Zulassung nur bestimmter bekannter Antworten.
Parametrisierte Abfragen und vorbereitete Anweisungen verwenden
Bei einer parametrisierten Abfrage wird ein Befehl zunächst mit seiner Struktur definiert. Anschließend werden die einzusetzenden Parameter separat übergeben. So werden Befehl und Daten niemals zu Zeichenfolgen verkettet. Stattdessen bleiben sie getrennt, und das System behandelt die Daten ausschließlich als Daten, nicht als ausführbaren Code.
Eine vorbereitete Anweisung geht noch einen Schritt weiter. Zunächst wird die Struktur des Befehls vorbereitet, anschließend werden nur noch die Parameter zum Ausfüllen der Platzhalter übergeben. Das subprocess-Modul von Python ermöglicht beispielsweise die Befehlsausführung, indem der Befehl von seinen Argumenten getrennt wird – ähnlich wie bei parametrisierten Abfragen:
shell=True mit Vorsicht verwenden
Vermeiden Sie bei der Verwendung des subprocess-Moduls von Python das Argument shell=True, insbesondere bei Nutzereingaben. Wird ein Befehl mit shell=True ausgeführt, interpretiert die System-Shell jede übergebene Zeichenfolge. Enthält diese Zeichenfolge Nutzereingaben oder wurde sie ohne angemessene Bereinigung aus mehreren Quellen zusammengesetzt, kann ein Angreifer schädliche Befehle einschleusen:
Das kann verheerende Folgen haben: unbefugter Systemzugriff, Datendiebstahl, die Installation von Malware, eine Rechteausweitung und die Ausführung beliebiger Befehle. Vermeiden Sie nach Möglichkeit shell=True oder bereinigen Sie zuerst die Eingabe, falls sich die Verwendung nicht vermeiden lässt.
Nutzereingaben nicht an os-Methoden übergeben
Wenn Sie Nutzereingaben direkt an os-Methoden wie os.spawn oder ähnliche übergeben, ist Ihre Python-Anwendung anfällig für Command Injection. Verwenden Sie deshalb alternative Python-APIs, sofern solche für Ihren Anwendungsfall verfügbar sind. Wenn Sie eine os-Methode benötigen, verwenden Sie sie möglichst ohne Nutzereingaben. Falls sich Nutzereingaben nicht vermeiden lassen, bereinigen Sie alle Eingaben und setzen Sie kontextbezogene Kodierungstechniken ein.
Berechtigungen beschränken und starke Zugriffskontrollen umsetzen
Führen Sie Ihre Anwendung immer mit den geringstmöglichen Berechtigungen aus. Wird eine Schwachstelle ausgenutzt, begrenzt dies den möglichen Schaden. Ziehen Sie außerdem in Betracht, Ihre Anwendung mithilfe von Tools oder Techniken wie chroot, Containern oder User-Namespaces zu isolieren.
Sichere Programmierkonventionen in Python
In den folgenden Abschnitten werden sichere Programmierkonventionen vorgestellt, die Ihre Python-Anwendungen bei korrekter Umsetzung vor Command-Injection-Schwachstellen schützen können.
Eingaben ordnungsgemäß validieren und bereinigen
Die Validierung und Bereinigung von Eingaben sind wesentliche Maßnahmen, um Ihre Python-Anwendungen vor Command Injection zu schützen. Indem Sie Nutzereingaben sorgfältig validieren und angemessen bereinigen, reduzieren Sie die Angriffsfläche, verhindern die unbefugte Ausführung von Befehlen und erhöhen die allgemeine Sicherheit Ihrer Software.
Sehen Sie sich den folgenden Code an:
Diese Funktion stellt vor der Verarbeitung sicher, dass die Eingabe eine festgelegte Länge hat und ausschließlich alphanumerische Zeichen enthält. Beachten Sie, dass Sie in einer realen Anwendung wahrscheinlich strengere Validierungsregeln benötigen als in diesem einfachen Beispiel.
Das subprocess-Modul und ähnliche Funktionen mit Bedacht verwenden
Das subprocess-Modul kann neue Prozesse starten, eine Verbindung zu deren Eingabe-, Ausgabe- und Fehlerdatenströmen herstellen und ihre Rückgabecodes abrufen. Daher muss dieses Modul unbedingt sicher verwendet werden.
Vermeiden Sie beim subprocess-Modul die Verwendung von shell=True, sofern sie nicht erforderlich ist. Andernfalls können Befehle in einer Shell ausgeführt werden, was Command-Injection-Angriffe ermöglicht:
Nutzereingaben und externe Befehle sicher verarbeiten
Verketten oder interpolieren Sie Nutzereingaben niemals direkt in Ihre Befehlszeichenfolgen. Verwenden Sie immer Argumentlisten:
Sicherheitsprobleme mit SAST- und SCA-Tools finden und beheben
Tools für statische Anwendungssicherheitstests (SAST) und Software Composition Analysis (SCA) helfen Ihnen dabei, sowohl Ihren eigenen Code als auch die Open-Source-Komponenten Ihrer Software zu analysieren und Schwachstellen früh im Entwicklungszyklus zu erkennen.
Die Snyk-Plattform macht das Auffinden und Beheben von Sicherheitsproblemen dank unseres hybriden KI-Ansatzes so einfach wie möglich. Dieser findet und behebt Schwachstellen in Ihrem Code und liefert Ihnen Echtzeit-Feedback zu potenziellen Sicherheitsrisiken sowie Empfehlungen zur Behebung. Mit SAST- und SCA-Tools wie Snyk (mit einem dauerhaft kostenlosen Tarif) können Sie Ihre Codebasis kontinuierlich auf Sicherheitsprobleme überwachen und diese frühzeitig beheben, bevor sie in die Produktion gelangen. So helfen wir Ihnen, Folgendes zu verhindern:
Kontakt mit schädlichen Paketen, die Ihr System oder Ihre Daten gefährden können
Angriffe auf die Software-Lieferkette, bei denen eine vertrauenswürdige Komponente kompromittiert wird und sich dies auf alle Softwareprodukte auswirkt, die von ihr abhängen
Veraltete Abhängigkeiten, die ungepatchte Schwachstellen enthalten können
Wenn Sie SAST- und SCA-Tools wie Snyk in Ihren Entwicklungsprozess integrieren, stellen Sie sicher, dass Sie nicht nur funktionsfähige Software entwickeln, sondern sie auch vor der sich ständig wandelnden Bedrohungslandschaft schützen.
Best Practices für die sichere Python-Entwicklung
In diesem Abschnitt lernen Sie grundlegende Programmiergewohnheiten und Workflows kennen, mit denen Sie eine sichere Python-Entwicklung teamübergreifend fördern können.
Regelmäßige Code-Reviews und Sicherheitsaudits durchführen
Regelmäßige Code-Reviews, bei denen Eingabevalidierung, Authentifizierungsmechanismen und der Umgang mit sensiblen Daten gründlich geprüft werden, helfen dabei, potenzielle Schwachstellen früh im Entwicklungszyklus zu erkennen. Wenn Sie Teammitglieder mit Sicherheitsexpertise einbeziehen, können Sie Probleme entdecken, die bei der ersten Entwicklung möglicherweise übersehen wurden, etwa unsichere Programmierpraktiken, fehlerhafte Konfigurationen und nicht bereinigte Eingaben.
Regelmäßige Sicherheitsaudits sind entscheidend, damit Ihre Codebasis auch angesichts neuer Bedrohungen robust bleibt. Mit Tools wie OpenVAS, ZAP und Metasploit können Sie Ihr Programm auf Schwachstellen testen.
Software und Bibliotheken auf dem neuesten Stand halten
Veraltete Software und Bibliotheken enthalten häufig bekannte Sicherheitslücken. Aktualisieren Sie Ihren Python-Interpreter, Ihre Frameworks und Drittanbieterbibliotheken kontinuierlich auf die neuesten Versionen. Nutzen Sie Paketmanager wie pip und Konfigurationsdateien wie requirements.txt, um Abhängigkeiten effizient zu verwalten und zu aktualisieren.
Sicherheitstools und Frameworks einsetzen
Sie können speziell für Python entwickelte Sicherheitstools und Frameworks nutzen, um die Erkennung von Schwachstellen zu automatisieren. Tools wie Snyk helfen dabei, Probleme auf Codeebene, fehlerhafte Sicherheitskonfigurationen und Schwachstellen in Paketen von Drittanbietern zu erkennen.
Python-Schwachstellen finden und beheben
Schützen Sie Ihre Anwendungen mit der Schwachstellensuche und den Behebungsempfehlungen von Snyk.
Keine Kreditkarte erforderlich.
Oder registrieren Sie sich mit Azure AD Docker ID Bitbucket
Mit der Nutzung von Snyk erklären Sie sich mit unseren Richtlinien einverstanden, einschließlich unserer Nutzungsbedingungen und Datenschutzerklärung.
Eine sicherheitsorientierte Denkweise fördern
Es ist wichtig, bei Entwicklerinnen und Entwicklern ein Bewusstsein für Sicherheit zu fördern. Bieten Sie Schulungen, Workshops und Ressourcen zu Sicherheitsthemen an, um sie zu unterstützen. Wenn Sicherheit von Anfang an Priorität hat, verbessert sich die Qualität der gesamten Software und das Risiko von Schwachstellen sinkt.
Eine wertvolle Ressource, um mehr über den Aufbau einer sicherheitsorientierten Unternehmenskultur zu erfahren, ist der Secure Developer Podcast. Er enthält zahlreiche Interviews mit Sicherheitsverantwortlichen aus Unternehmen und geht ausführlich darauf ein, wie sie ihre Entwicklungsprogramme gestalten.
IDE-Erweiterungen zur Erkennung von Schwachstellen in Echtzeit sind wertvolle Tools, um anfälligen Code bereits beim Schreiben zu erkennen. Diese Erweiterungen sind direkt in Ihre Entwicklungsumgebung integriert und weisen Sie in Echtzeit auf potenzielle Sicherheitsprobleme hin:

Wenn Sie Schwachstellen bereits während der Entwicklung erkennen, sparen Sie Zeit und Aufwand, die Sie sonst später im Entwicklungszyklus investieren müssten – dann wäre ihre Behebung deutlich kostspieliger.
Fazit
Command Injection ist ein schwerwiegendes Problem, das viele Python-Anwendungen betrifft. In diesem Leitfaden haben Sie erfahren, wie diese Schwachstelle auftreten kann und welche Risiken damit verbunden sind. Wenn Sie anfällige Code-Muster erkennen, gewinnen Sie wertvolle Einblicke in potenzielle Bedrohungen und die erforderlichen Gegenmaßnahmen.
Außerdem haben Sie sichere Programmierkonventionen kennengelernt, etwa die Validierung von Eingaben und den sorgfältigen Einsatz integrierter Systemmodule zum Ausführen von Befehlen. Mit diesen Strategien können Sie die Sicherheit Ihrer Python-Anwendungen stärken, potenzielle Angriffe abwehren und zur allgemeinen Widerstandsfähigkeit Ihrer Software beitragen.
Um Ihren Entwicklungsprozess weiter zu stärken, sollten Sie Tools wie Snyk nutzen. Die IDE-Erweiterungen von Snyk liefern Ihnen Echtzeit-Feedback zur Sicherheitk, scannen Ihren Code während des Schreibens und schlagen sofortige Korrekturen vor. Es ist, als würde Ihnen eine Sicherheitsexpertin oder ein Sicherheitsexperte über die Schulter schauen und dafür sorgen, dass Sie von Anfang an sicheren und robusten Code schreiben.
Sichern Sie Ihre Python-Apps ab
Finden und beheben Sie Python-Schwachstellen – kostenlos mit Snyk.
Keine Kreditkarte erforderlich.
Oder registrieren Sie sich mit Azure AD Docker ID Bitbucket
Mit der Nutzung von Snyk erklären Sie sich mit unseren Richtlinien einverstanden, einschließlich unserer Nutzungsbedingungen und Datenschutzerklärung.



