Cheat Sheet: Best Practices für Python-Sicherheit
Frank Fischer
27. September 2021
0 Min. Lesezeit
2019 veröffentlichte Snyk sein erstes Python-Cheat-Sheet. Seitdem haben sich viele Aspekte der Python-Sicherheit verändert. Auf Grundlage unserer Erfahrungen als Unternehmen für Entwicklersicherheit und der Best Practices speziell für Python haben wir dieses aktualisierte Cheat Sheet zusammengestellt, damit Ihr Python-Code sicher bleibt. Bevor wir fortfahren, möchte ich Chibo und Daniel ganz besonders für ihre Unterstützung bei diesem Cheat Sheet danken!
Laden Sie das Cheat Sheet zu Best Practices für Python-Sicherheit von 2021 herunter
Diese Tipps zur Python-Sicherheit sehen wir uns an:
Bereinigen Sie externe Daten immer
Scannen Sie Ihren Code
Seien Sie beim Herunterladen von Paketen vorsichtig
Prüfen Sie die Lizenzen Ihrer Abhängigkeiten
Verwenden Sie nicht die systemweite Standardversion von Python
Nutzen Sie die Unterstützung von Python für virtuelle Umgebungen
Setzen Sie
DEBUG = Falsein der ProduktionsumgebungSeien Sie bei der Zeichenkettenformatierung vorsichtig
(De-)Serialisieren Sie äußerst vorsichtig
Verwenden Sie Python-Typannotationen
Ein kurzer Hinweis, bevor wir beginnen: Die Daten von Snyk zum Python-Ökosystem sowie akademische Studien zeigen, dass Python nicht mehr oder weniger sicher ist als andere weit verbreitete Programmiersprachen. Dieses Cheat Sheet richtet sich speziell an Pythonistas. Wir empfehlen Ihnen, sich auch alle unsere anderen Cheat Sheets zur Sicherheit anzusehen, um zu erfahren, wie Sie in anderen Ökosystemen sicher bleiben.
1. Bereinigen Sie externe Daten immer
Externe Daten sind ein möglicher Angriffsvektor für jede Anwendung. Sie können für Injection-, XSS- oder Denial-of-Service-Angriffe (DOS) missbraucht werden. Eine allgemeine Regel für die Python-Sicherheit lautet daher, Daten aus externen Quellen immer zu bereinigen (also vertrauliche Informationen zu entfernen) – unabhängig davon, ob sie aus einem Benutzereingabeformular, dem Scraping einer Website oder einer Datenbankabfrage stammen. Bereinigen Sie die Daten außerdem sofort, wenn sie in die Anwendung gelangen, um eine unsichere Verarbeitung zu verhindern. So verringern Sie das Risiko, dass Ihre Anwendung versehentlich nicht bereinigte vertrauliche Daten verarbeitet.
Bei der Bereinigung ist es immer sinnvoller, zu prüfen, welche Eingaben zulässig sind, als zu versuchen, Ausnahmen abzufangen. Außerdem empfehlen wir gut gepflegte Bibliotheken zur Bereinigung. Hier sind zwei Beispiele:
schema ist „eine Bibliothek zur Validierung von Python-Datenstrukturen, etwa aus Konfigurationsdateien, Formularen, externen Diensten oder der Befehlszeilenverarbeitung, die aus JSON/YAML (oder anderen Formaten) in Python-Datentypen umgewandelt wurden.“
bleach ist „eine HTML-Bereinigungsbibliothek mit Allowlist, die Markup und Attribute maskiert oder entfernt.“
Wichtige Frameworks bieten eigene Bereinigungsfunktionen, etwa flask.escape() von Flask oder django.utils.html.escape() von Django. Ziel dieser Funktionen ist es, potenziell bösartige HTML-Eingaben wie die folgende abzusichern:
Dieser Ansatz hat jedoch eine Einschränkung: Bibliotheken eignen sich nicht für alle Fälle, sondern sind auf ihren jeweiligen Bereich spezialisiert. Lesen Sie unbedingt bis zum Ende dieses Beitrags weiter, um mehr über den Umgang mit anderen Datenformaten wie XML zu erfahren, die ebenfalls schädliche Daten enthalten können.
Eine weitere häufig genutzte Möglichkeit ist, das Rendern von HTML Template-Engines wie Jinja zu überlassen. Sie bieten zahlreiche Funktionen, darunter automatisches Escaping zum Schutz vor XSS mithilfe von MarkupSafe.
Bei der Bereinigung geht es auch darum, zu verhindern, dass Daten als Befehl ausgeführt werden. Ein typisches Beispiel ist eine SQL-Injection. Statt Zeichenketten und Variablen zu einer SQL-Abfrage zusammenzufügen, empfiehlt es sich, benannte Parameter zu verwenden. So können Sie der Datenbank mitteilen, was als Befehl und was als Daten zu behandeln ist.
Noch besser ist es, ein Object-Relational Mapping (ORM) wie sqlalchemy zu verwenden. Damit könnte die Beispielabfrage so aussehen:
Das Ergebnis: besser lesbarer Code und ORM-Optimierungen wie Caching sowie mehr Sicherheit und Performance!
Weitere Informationen finden Sie in unserem Cheat Sheet zu SQL-Injections.
2. Scannen Sie Ihren Code
Entwicklern steht eine große Auswahl an Tools für die statische Codeanalyse zur Verfügung, mit denen sie die Python-Sicherheit verbessern können. Sehen wir uns drei verschiedene Tool-Kategorien an.
Zunächst die Kategorie der Linter. PEP8 dient seit Jahrzehnten als Styleguide für Python. Verschiedene Tools (auch in IDEs integriert) prüfen Code anhand dieses Styleguides, darunter pep8, pylint, flake8 und weitere.
Tools wie bandit wandeln Code in einen abstrakten Syntaxbaum (AST) um und führen Abfragen darauf aus, um typische Sicherheitsprobleme zu finden. Damit gehen sie über die üblichen Linter hinaus, die auf syntaktischer Ebene arbeiten. bandit ist jedoch durch seine Zwischendarstellung und Performance eingeschränkt. So kann bandit beispielsweise keine Probleme im Datenfluss erkennen (bekannt als Taint-Analyse), die schwerwiegende Schwachstellen verursachen können – etwa Injections wie SQL-Injections oder XSS.
Schließlich führen Tools für Static Application Security Testing (SAST) wie Snyk Code eine semantische Analyse durch und berücksichtigen dabei auch komplexe Probleme über mehrere Dateien hinweg. Anders als andere Tools dieser Kategorie ist Snyk Code entwicklerfreundlich: Der Scan ist schnell und das Tool lässt sich in die IDE integrieren (oder direkt über die Befehlszeile nutzen). Snyk Code erklärt seine äußerst präzisen Ergebnisse und bietet Unterstützung, einschließlich Beispielen zur Behebung von Python-Sicherheitsproblemen. Darüber hinaus ist der Einstieg einfach und die Nutzung für Open Source kostenlos (mit einer begrenzten Anzahl zusätzlicher Tests für Nicht-OSS-Projekte).
3. Seien Sie beim Herunterladen von Paketen vorsichtig
Pakete lassen sich einfach installieren, können aber auch leicht Python-Sicherheitslücken einführen. Entwickler verwenden üblicherweise den Standardpaketmanager für Python (pip), der den Python Package Index (PyPI) nutzt. Daher ist es wichtig zu verstehen, wie Pakete zu PyPI hinzugefügt werden.
PyPI verfügt über ein Verfahren, um Sicherheitsbedenken zu melden. Wird ein schädliches Paket oder ein Problem bei PyPI gemeldet, wird es bearbeitet. Pakete, die zu PyPI hinzugefügt werden, werden jedoch nicht überprüft – eine solche Erwartung wäre gegenüber den Freiwilligen, die PyPI pflegen, unrealistisch.
Gehen Sie daher davon aus, dass PyPI schädliche Pakete enthalten kann, und handeln Sie entsprechend. Recherchieren Sie das Paket, das Sie installieren möchten, und achten Sie genau auf die Schreibweise des Paketnamens (ein Paket, dessen Name einem häufigen Schreibfehler bei einem beliebten Paket entspricht, könnte schädlichen Code ausführen). Prüfen Sie ein Paket vor dem Herunterladen mit Snyk Advisor.

Eine kurze Suche nach einem Paket in Snyk Advisor liefert zahlreiche Informationen zum Paket, seiner Unterstützung durch die Community, seiner Fehler- und Fehlerbehebungshistorie und vielem mehr. Snyk Advisor zeigt außerdem den Installationsbefehl oben auf der Ergebnisseite an. Kopieren Sie am besten diese Schreibweise, um Typosquatting zu vermeiden. Snyk Advisor zeigt Ihnen, ob Sie einem Paket vertrauen sollten. Sie können den Verlauf der Sicherheitsprobleme und die Zeit bis zu ihrer Behebung einsehen.
Eine weitere Best Practice ist die Verwendung virtueller Umgebungen, um Projekte voneinander zu isolieren. Verwenden Sie außerdem pip freeze oder einen vergleichbaren Befehl, um Änderungen in der Umgebung in der Liste der Anforderungen festzuhalten.
Mit stets aktuellen Referenzen basiert Snyk Open Source auf einer branchenführenden Schwachstellendatenbank, die Sicherheitsprobleme und mögliche Behebungen erfasst. Snyk Open Source scannt anhand der Anforderungen und liefert konkrete Informationen zu gefundenen Schwachstellen in direkten und transitiven Abhängigkeiten. Außerdem unterstützt es Sie dabei, diese umgehend zu beheben.
4. Prüfen Sie die Lizenzen Ihrer Abhängigkeiten
Wenn Sie ein Open-Source-Projekt verwenden möchten, sollten Sie sich mit dessen Lizenz vertraut machen. Open-Source-Projekte sind kostenlos verfügbar und nutzbar, können aber dennoch an Bedingungen geknüpft sein. Diese betreffen üblicherweise die Nutzung der Software, die Pflicht, Änderungen an der Software öffentlich zugänglich zu machen, und ähnliche Anforderungen. Machen Sie sich mit den erforderlichen Open-Source-Lizenzen der von Ihnen verwendeten Projekte vertraut, damit Sie keine rechtlichen Risiken eingehen.
Entscheiden Sie sich für eine restriktivere Lizenz als erwartet (GPL, SSPL usw.), können Sie sich in eine schwierige Lage bringen: Sie müssen dann entweder die Lizenzbedingungen einhalten oder das Projekt nicht mehr verwenden. Wenn Sie außerdem Änderungen an einem Projekt ohne Lizenz vornehmen müssen, könnten Sie gegen das Urheberrecht verstoßen.
Damit Ihr Projekt nachhaltig ist und Sie sich keinen unnötigen Sicherheits- und Rechtsrisiken im Zusammenhang mit Python aussetzen, sollten Sie die Lizenzen und Schwachstellen in den Abhängigkeiten Ihres Projekts scannen und Probleme beheben.
Snyk Open Source unterstützt Sie beim Management der Compliance mit Open-Source-Lizenzen. Die Lösung bietet Entwicklern einen unkomplizierten Weg zu umfassender Transparenz und ermöglicht zugleich eine flexible Governance.
5. Verwenden Sie nicht die systemweite Standardversion von Python
Auf den meisten POSIX-Systemen ist bereits eine Python-Version installiert. Das Problem bei den meisten vorinstallierten Python-Distributionen: Sie sind nicht aktuell.
Verwenden Sie daher die neueste für Ihr System verfügbare Python-Version sowie die offiziellen Container für die Ausführung von Python und halten Sie beides aktuell. Snyk unterstützt Sie dabei: Scannen Sie Ihre Container mit Snyk Container auf erforderliche Updates und prüfen Sie Ihre Abhängigkeiten mit Snyk Open Source.
6. Verwenden Sie virtuelle Python-Umgebungen
Python ermöglicht es, die Anwendungsentwicklung in virtuelle Umgebungen aufzuteilen. Eine virtuelle Umgebung isoliert den Python-Interpreter sowie die darin installierten Bibliotheken und Skripte. Das bedeutet: Statt für alle Projekte dieselbe globale Python-Version und dieselben globalen Python-Abhängigkeiten zu verwenden, können Sie projektspezifische virtuelle Umgebungen mit jeweils eigenen Python- und Python-Abhängigkeitsversionen einrichten.
Die meisten IDEs, CLIs und Dashboards wie Anaconda Navigator bieten integrierte Funktionen für den Wechsel zwischen virtuellen Umgebungen.
Profi-Tipp: Ab Python 3.5 wird die Verwendung von venv empfohlen. Mit Version 3.6 wurde pyvenv als veraltet eingestuft.
Virtuelle Umgebungen erleichtern die Entwicklung, Paketierung und Bereitstellung sicherer Python-Anwendungen. Ihre Verwendung wird dringend empfohlen. Weitere Informationen finden Sie in der Python-Dokumentation zu venv.
7. Setzen Sie DEBUG = False in der Produktionsumgebung
In einer Entwicklungsumgebung sind ausführliche Fehlermeldungen sinnvoll. In der Produktionsumgebung sollten Sie jedoch verhindern, dass Informationen preisgegeben werden, die Angreifern Einblicke in Ihre Umgebung, Bibliotheken oder Ihren Code ermöglichen.
Bei den meisten Frameworks ist das Debugging standardmäßig aktiviert. Bei Django ist es beispielsweise in settings.py eingeschaltet. Stellen Sie sicher, dass Sie das Debugging in der Produktionsumgebung auf False setzen, damit Angreifer keine vertraulichen Informationen über Ihre Anwendung erhalten.
Profi-Tipp: Es empfiehlt sich, Ihr Continuous-Deployment-System bei der Bereitstellung in der Produktionsumgebung überprüfen zu lassen, ob diese Einstellung deaktiviert ist.
8. Seien Sie bei der Zeichenkettenformatierung vorsichtig
Obwohl Python auf dem Prinzip beruht, dass es für eine Aufgabe nur einen Weg geben sollte, bietet die Sprache tatsächlich vier Möglichkeiten zur Formatierung von Zeichenketten (drei Methoden für Versionen vor Python 3.6).
Die Formatierung von Zeichenketten ist nach und nach flexibler und leistungsfähiger geworden (insbesondere f-Strings sind interessant). Mit der Flexibilität steigt jedoch auch das Potenzial für Exploits. Daher sollten Python-Nutzer sorgfältig abwägen, wie sie Zeichenketten mit von Nutzern bereitgestellten Eingaben formatieren.
Python enthält ein integriertes Modul namens string. Dieses Modul umfasst die Klasse Template, mit der sich Template-Zeichenketten erstellen lassen.
Sehen wir uns das folgende Beispiel an.
Im obigen Code wird die Variable greeting wie folgt ausgewertet: „Hello World, my name is Hayley.“
Dieses Zeichenkettenformat ist etwas umständlich, da es eine Import-Anweisung erfordert und weniger flexibel mit Datentypen umgeht. Außerdem wertet es Python-Anweisungen nicht wie f-Strings aus. Dadurch eignen sich Template-Zeichenketten hervorragend für den Umgang mit Benutzereingaben.
Noch ein kurzer Hinweis zur Formatierung von Zeichenfolgen: Seien Sie bei rohem SQL besonders vorsichtig, wie oben erwähnt.
9. Sehr vorsichtig (de)serialisieren
Python bietet mit dem Modul pickle einen integrierten Mechanismus zum Serialisieren und Deserialisieren von Python-Objekten, das sogenannte „Pickling“. Dieser gilt als unsicher. Daher empfiehlt es sich, ihn sehr vorsichtig und nur mit vertrauenswürdigen Datenquellen zu verwenden.
Der neue De-facto-Standard für die Serialisierung und Deserialisierung ist YAML. Das Paket PyYAML bietet einen Mechanismus, um benutzerdefinierte Datentypen in YAML und zurück zu serialisieren. PyYAML birgt jedoch diverse potenzielle Angriffsvektoren. Eine einfache, aber wirksame Maßnahme zur sicheren Verwendung von PyYAML ist, als Loader yaml.SafeLoader() statt yaml.Loader() zu verwenden.
Dadurch wird das Laden benutzerdefinierter Klassen verhindert, Standardtypen wie Hashes und Arrays werden jedoch unterstützt.
Ein weiterer typischer Anwendungsfall ist XML. Häufig kommen Standardbibliotheken zum Einsatz, die jedoch anfällig für typische Angriffe sind – insbesondere DoS-Angriffe oder die Expansion externer Entitäten (dabei wird auf eine externe Quelle verwiesen). Eine gute erste Schutzmaßnahme ist das Paket defusedxml. Es schützt vor diesen typischen XML-Sicherheitsproblemen.
Zusätzlicher Tipp ohne Sicherheitsbezug: Verwenden Sie Python-Typannotationen
Mit Version 3.5 wurden Typhinweise eingeführt. Die Python-Laufzeitumgebung erzwingt Typannotationen zwar nicht, doch Tools wie Typprüfer, IDEs, Linter, SAST-Tools und andere profitieren davon, wenn Entwicklerinnen und Entwickler genauere Angaben machen. Hier ein Beispiel zur Veranschaulichung:
Literal[...] wurde mit Version 3.8 eingeführt und wird von der Laufzeitumgebung nicht erzwungen (in unserem Beispiel können Sie beliebige Zeichenfolgen übergeben). Typprüfer können jedoch erkennen, wenn ein Parameter außerhalb des zulässigen Bereichs liegt, und Sie warnen. Diese Funktion ist äußerst nützlich – nicht nur für die Python-Sicherheit.
Hinweis: Da die Laufzeitumgebung Typhinweise nicht erzwingt, ist ihr Nutzen für die Sicherheit begrenzt.
Starten Sie mit Capture the Flag
Erfahren Sie in unserem virtuellen On-Demand-Workshop für Einsteiger, wie Sie Capture-the-Flag-Herausforderungen lösen.



