Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python Enhancement Proposals

PEP 458 – Sichere PyPI-Downloads mit signierten Repository-Metadaten

Autor:
Trishank Karthik Kuppusamy <karthik at trishank.com>, Vladimir Diaz <vladimir.diaz at nyu.edu>, Marina Moore <mm9693 at nyu.edu>, Lukas Puehringer <lukas.puehringer at nyu.edu>, Joshua Lock <jlock at vmware.com>, Lois Anne DeLong <lad278 at nyu.edu>, Justin Cappos <jcappos at nyu.edu>
Sponsor:
Alyssa Coghlan <ncoghlan at gmail.com>
BDFL-Delegate:
Donald Stufft <donald at stufft.io>
Discussions-To:
Discourse thread
Status:
Akzeptiert
Typ:
Standards Track
Thema:
Packaging
Erstellt:
27-Sep-2013
Post-History:
06-Jan-2019, 13-Nov-2019
Resolution:
Discourse-Nachricht

Inhaltsverzeichnis

Zusammenfassung

Dieses PEP beschreibt Änderungen an der PyPI-Infrastruktur, die erforderlich sind, um sicherzustellen, dass Benutzer gültige Pakete von PyPI erhalten. Diese Änderungen sollten minimale Auswirkungen auf andere Teile des Ökosystems haben. Das PEP konzentriert sich auf die Kommunikation zwischen PyPI und Benutzern und erfordert daher keine Maßnahmen von Paketentwicklern. Entwickler werden Pakete über den aktuellen Prozess hochladen, und PyPI generiert automatisch signierte Repository-Metadaten für diese Pakete.

Damit der Sicherheitsmechanismus wirksam ist, sind zusätzliche Arbeiten von PyPI-Konsumenten (wie pip) erforderlich, um die von PyPI bereitgestellten Signaturen und Metadaten zu überprüfen. Diese Überprüfung kann für die Benutzer transparent sein (sofern sie nicht fehlschlägt) und bietet einen automatischen Sicherheitsmechanismus. Es gibt Dokumentation, wie TUF-Metadaten im TUF-Repository verbraucht werden. Änderungen an PyPI-Konsumenten sind jedoch keine Voraussetzung für die Veröffentlichung der Metadaten von PyPI und können gemäß den Zeitplänen und Prioritäten einzelner Projekte erfolgen.

Vorgeschlagene TUF-Integration

Dieses PEP schlägt vor, wie The Update Framework [2] (TUF) mit dem Python Package Index (PyPI [1]) integriert werden sollte. TUF wurde entwickelt, um eine flexible Sicherheits-Ergänzung für Software-Updater oder Paketmanager zu sein. Eine vollständige Implementierung des Frameworks integriert bewährte Sicherheitspraktiken, wie z. B. die Trennung von Rollenverantwortlichkeiten, die Anwendung der "Many-Man-Regel" für die Signatur von Paketen, die Aufbewahrung von Signierschlüsseln offline und den Widerruf abgelaufener oder kompromittierter Signierschlüssel. Infolgedessen müssten Angreifer mehrere Signierschlüssel stehlen, die unabhängig voneinander gespeichert sind, um die für die Angabe der verfügbaren Dateien eines Repositories zuständige Rolle zu kompromittieren. Alternativ müsste auch eine Rolle, die für die Angabe des neuesten Snapshots des Repositories zuständig ist, kompromittiert werden.

Die in diesem PEP vorgeschlagene anfängliche Integration wird modernen Paketmanagern wie pip [3] ermöglichen, sicherer gegen Angriffe auf PyPI-Spiegel und das Content-Distribution-Netzwerk von PyPI selbst zu sein und Benutzer besser vor solchen Angriffen zu schützen. Insbesondere beschreibt dieses PEP, wie PyPI-Prozesse angepasst werden sollten, um TUF-Metadaten zu generieren und zu integrieren (d. h. das minimale Sicherheitsmodell). Dieses minimale Sicherheitsmodell unterstützt die Überprüfung von PyPI-Distributionen, die mit Schlüsseln signiert sind, die auf PyPI gespeichert sind. Distributionen, die von Entwicklern hochgeladen werden, werden von PyPI signiert, erfordern keine Aktion von den Entwicklern (außer dem Hochladen der Distribution) und sind sofort zum Download verfügbar. Das minimale Sicherheitsmodell minimiert auch die administrativen Aufgaben von PyPI, indem ein Großteil des Signierprozesses automatisiert wird.

In *diesem* PEP wird keine Unterstützung für von Entwicklern signierte Projekt-Distributionen (maximales Sicherheitsmodell) diskutiert. Diese mögliche zukünftige Erweiterung wird in PEP 480 ausführlich behandelt. Das maximale Sicherheitsmodell erfordert mehr administrative Arbeit von PyPI (wenn auch keine zusätzliche Arbeit für Clients) und schlägt außerdem eine einfach zu bedienende Schlüsselverwaltungslösung für Entwickler/Publisher, Ideen für die Schnittstelle zu einer potenziellen zukünftigen Build-Farm auf der PyPI-Infrastruktur und die Machbarkeit der Ende-zu-Ende-Signierung vor.

Während es Implementierungsempfehlungen gibt, schreibt dieses PEP nicht genau vor, wie Paketmanager wie pip angepasst werden sollten, um Projekte von PyPI mit TUF-Metadaten zu installieren oder zu aktualisieren. Paketmanager, die daran interessiert sind, TUF auf der Client-Seite zu nutzen, können die Bibliotheksdokumentation konsultieren, die zu diesem Zweck erstellt wurde.

Non-goals

Dieses PEP eliminiert keine bestehenden Funktionen von PyPI. Insbesondere ersetzt es nicht die bestehende Unterstützung für OpenPGP-Signaturen. Entwickler können weiterhin getrennte OpenPGP-Signaturen zusammen mit Distributionen hochladen. In Zukunft kann PEP 480 es Entwicklern ermöglichen, TUF-Metadaten direkt mit ihren OpenPGP-Schlüsseln zu signieren.

PEP Status

Aufgrund des Umfangs der für die Implementierung dieses PEP erforderlichen Arbeit wurde es Anfang 2019 aufgeschoben, bis die entsprechende Finanzierung für die Umsetzung des PEP gesichert werden konnte. Die Python Software Foundation hat diese Finanzierung gesichert [22] und neue PEP-Koautoren haben die PEP-Diskussion wieder aufgenommen.

Motivation

Angriffe auf Software-Repositories sind üblich, selbst in Organisationen mit sehr guten Sicherheitspraktiken . Der resultierende Kompromittierung des Repositories erlaubt einem Angreifer, alle im Repository gespeicherten Dateien zu bearbeiten und diese Dateien mit beliebigen im Repository gespeicherten Schlüsseln (Online-Schlüssel) zu signieren. In vielen Signaturschemata (wie TLS) erlaubt dieser Zugriff dem Angreifer, Dateien im Repository zu ersetzen und es so aussehen zu lassen, als kämen diese Dateien von PyPI. Ohne eine Möglichkeit, den vertrauenswürdigen privaten Schlüssel zu widerrufen und zu ersetzen, ist es sehr schwierig, sich von einer Repository-Kompromittierung zu erholen. Neben den Gefahren der Repository-Kompromittierung sind Software-Repositories anfällig für Angreifer im Netzwerk (MITM), die Dateien abfangen und ändern. Diese und andere Angriffe auf Software-Repositories sind hier detailliert beschrieben.

Dieses PEP zielt zusammen mit dem Folgevorschlag in PEP 480 darauf ab, Benutzer von PyPI vor Kompromittierungen der Integritäts-, Konsistenz- und Aktualitätseigenschaften von PyPI-Paketen zu schützen und die Widerstandsfähigkeit gegen Kompromittierungen durch Minderung des Schlüsselrisikos und Bereitstellung von Mechanismen zur Erholung von einer Kompromittierung von PyPI oder seinen Signierschlüsseln zu verbessern.

Am 5. Januar 2013 kündigte die Python Software Foundation (PSF) an [4], dass es zu einem Sicherheitsvorfall bei den Python- und Jython-Wikis auf python.org gekommen sei. Infolgedessen wurden alle Wiki-Daten zerstört. Glücklicherweise war die PyPI-Infrastruktur von diesem Vorfall nicht betroffen. Der Vorfall ist jedoch eine Erinnerung daran, dass PyPI proaktive Schritte unternehmen musste, um Benutzer im Falle einer Kompromittierung so weit wie möglich zu schützen. Angriffe auf Software-Repositories finden ständig statt [5]. Die PSF muss die Möglichkeit von Sicherheitsverletzungen akzeptieren und PyPI entsprechend vorbereiten, da es eine wertvolle Ressource ist, die von Tausenden, wenn nicht Millionen von Menschen genutzt wird.

Vor dem Wiki-Angriff verwendete PyPI MD5-Hashes, um Paketmanagern wie pip mitzuteilen, ob eine Distributionsdatei während des Transports beschädigt wurde oder nicht. Das Fehlen von SSL erschwerte es den Paketmanagern jedoch, die Transportintegrität zu PyPI zu überprüfen. Es war daher einfach, einen Man-in-the-Middle-Angriff zwischen pip und PyPI zu starten und den Inhalt von Distributionen willkürlich zu ändern. Infolgedessen konnten Benutzer dazu verleitet werden, bösartige Distributionen zu installieren. Nach dem Wiki-Angriff wurden mehrere Schritte vorgeschlagen (einige davon wurden umgesetzt), um ein weitaus höheres Sicherheitsniveau zu gewährleisten als zuvor. Dazu gehörten die Anforderung von SSL für die Kommunikation mit PyPI [6], die Beschränkung von Projektnamen [7] und die Migration von MD5 zu SHA-2-Hashes [8].

Diese Schritte sind zwar notwendig, aber nicht ausreichend, um Distributionen zu schützen, da Angriffe über andere Wege weiterhin möglich sind. So wird beispielsweise ein öffentlicher Spiegel angewiesen, PyPI ehrlich zu spiegeln, aber einige Spiegel könnten sich falsch verhalten, sei es versehentlich oder durch böswillige Intervention. Paketmanager wie pip sollen Signaturen von PyPI verwenden, um Distributionsdateien zu verifizieren, die von einem öffentlichen Spiegel heruntergeladen wurden, aber es ist keine bekannte tatsächliche Verwendung bekannt [10]. Daher wäre es ratsam, zusätzliche Sicherheitsmaßnahmen hinzuzufügen, um Angriffe von öffentlichen Spiegeln oder Content Delivery Networks [11] (CDNs) zu erkennen.

Auch wenn offizielle Spiegel auf PyPI depreziert wurden, bleiben eine Vielzahl anderer Angriffsvektoren auf Paketmanager bestehen [13]. Diese Angriffe können Client-Systeme zum Absturz bringen, dazu führen, dass veraltete Distributionen installiert werden, oder sogar einem Angreifer die Ausführung von beliebigem Code ermöglichen. Im September 2013 wurde im Distutils-Mailingliste ein Beitrag veröffentlicht, der zeigte, dass die damals neueste Version von pip anfällig für solche Angriffe war und wie TUF Benutzer davor schützen könnte [14]. Insbesondere wurden Tests durchgeführt, um zu sehen, wie pip auf diese Angriffe mit und ohne TUF reagieren würde. Getestete Angriffe waren Replay und Freeze, beliebige Installation, langsame Abfrage und endlose Daten. Der Beitrag enthielt auch eine Demonstration, wie pip reagieren würde, wenn PyPI kompromittiert wäre.

Um einen kompromittierungsresilienten Schutz von PyPI zu bieten, schlägt dieses PEP die Verwendung von The Update Framework [2] (TUF) vor. TUF bietet Schutz vor einer Vielzahl von Angriffen auf Software-Update-Systeme und bietet gleichzeitig Mechanismen zur Erholung von einer Repository-Kompromittierung. TUF wird von einer Reihe von Organisationen produktiv eingesetzt, einschließlich der Nutzung im Notary-Dienst der Cloud Native Computing Foundation, der die Infrastruktur für die Signierung von Container-Images in Docker Registry bereitstellt. Die TUF-Spezifikation wurde Gegenstand von drei unabhängigen Sicherheitsaudits .

Der Umfang von *diesem* PEP ist der Schutz von Benutzern vor Kompromittierungen von PyPI-Spiegeln und der eigenen TLS-Terminierungs- und Content-Distribution-Infrastruktur von PyPI. Der Schutz vor Kompromittierungen von PyPI selbst wird in PEP 480 diskutiert.

Bedrohungsmodell

Das Bedrohungsmodell geht von Folgendem aus:

  • Offline-Schlüssel sind sicher und werden sicher aufbewahrt.
  • Angreifer können die auf PyPI gespeicherten vertrauenswürdigen Schlüssel *nicht* kompromittieren.
  • Angreifer können auf Client-Anfragen reagieren.

Ein Angreifer gilt als erfolgreich, wenn er einen Client dazu bringen kann, etwas anderes als die aktuellste Version einer Software-Distributionsdatei zu installieren (oder installiert zu lassen). Wenn der Angreifer die Installation von Updates verhindert, möchte er nicht, dass Clients bemerken, dass etwas nicht stimmt.

Dieses Bedrohungsmodell beschreibt das minimale Sicherheitsmodell. Das in PEP 480 beschriebene maximale Sicherheitsmodell geht ebenfalls davon aus, dass Angreifer die Online-Schlüssel von PyPI kompromittieren können.

Definitionen

Die Schlüsselwörter „MUSS“, „DARF NICHT“, „ERFORDERLICH“, „SOLL“, „SOLL NICHT“, „EMPFOHLEN“, „KANN“ und „OPTIONAL“ in diesem Dokument sind wie in RFC 2119 beschrieben zu interpretieren.

Dieses PEP konzentriert sich ausschließlich auf die Integration von TUF in PyPI. Der Leser wird jedoch ermutigt, die Designprinzipien von TUF [2] zu prüfen und mit der TUF-Spezifikation [16] vertraut zu sein.

Die in diesem PEP verwendeten Begriffe sind im Python Packaging Glossary [17] definiert: *Projekt*, *Release*, *Distribution*.

Zusätzliche Begriffe, die in diesem PEP verwendet werden, sind wie folgt definiert:

  • Rolle: TUF spezifiziert eine *Root*-Rolle und mehrere andere Rollen, denen die *Root*-Rolle die Verantwortlichkeiten direkt oder indirekt delegiert. Der Begriff *Top-Level-Rolle* bezieht sich auf die *Root*-Rolle und jede Rolle, die direkt von der *Root*-Rolle spezifiziert wird, d.h. die *Timestamp*-, *Snapshot*- und *Targets*-Rollen. Jede Rolle hat eine einzige Metadatendatei, für deren Bereitstellung sie zuständig ist.
  • Distributionsdatei: Eine versionierte Archivdatei, die Python-Pakete, Module und andere Ressourcendateien enthält, die zur Verteilung eines Releases verwendet werden. Die Begriffe *Distributionsdatei*, *Distributionspaket* [17] oder einfach *Distribution* oder *Paket* können in diesem PEP austauschbar verwendet werden.
  • Einfacher Index: Die HTML-Seite, die interne Links zu Distributionsdateien enthält.
  • Ziel-Dateien: Als Faustregel sind Ziel-Dateien alle Dateien auf PyPI, deren Integrität mit TUF garantiert werden soll. Typischerweise umfasst dies Distributionsdateien und PyPI-Metadaten wie einfache Indizes.
  • Metadaten: Metadaten sind signierte Dateien, die Rollen, andere Metadaten und Ziel-Dateien beschreiben. Sofern nicht anders angegeben, beziehen sich Metadaten auf TUF-spezifische Metadaten.
  • Repository: Ein Repository ist eine Quelle für benannte Metadaten und Ziel-Dateien. Clients fordern Metadaten und Ziel-Dateien an, die im Repository gespeichert sind.
  • Konsistenter Snapshot: Eine Sammlung von TUF-Metadaten und Ziel-Dateien, die den vollständigen Zustand aller Projekte auf PyPI erfassen, wie er zu einem bestimmten Zeitpunkt existierte.
  • Entwickler: Entweder der Eigentümer oder Betreuer eines Projekts, der berechtigt ist, die TUF-Metadaten sowie die Ziel-Dateien für ein Projekt zu aktualisieren.
  • Online-Schlüssel: Ein privater kryptografischer Schlüssel, der im PyPI-Server-Infrastruktur gespeichert sein MUSS. Dies dient in der Regel der automatischen Signierung mit dem Schlüssel. Ein Angreifer, der die PyPI-Infrastruktur kompromittiert, kann diese Schlüssel jedoch lesen.
  • Offline-Schlüssel: Ein privater kryptografischer Schlüssel, der unabhängig von der PyPI-Server-Infrastruktur gespeichert sein MUSS. Dies verhindert die automatische Signierung mit dem Schlüssel. Ein Angreifer, der die PyPI-Infrastruktur kompromittiert, kann diese Schlüssel nicht sofort lesen.
  • Schwellenwert-Signaturverfahren: Eine Rolle kann ihre Widerstandsfähigkeit gegen Schlüsselkompromittierungen erhöhen, indem sie festlegt, dass mindestens t von n Schlüsseln erforderlich sind, um ihre Metadaten zu signieren. Eine Kompromittierung von t-1 Schlüsseln reicht nicht aus, um die Rolle selbst zu kompromittieren. Wenn eine Rolle (t, n) Schlüssel erfordert, bezeichnet dies die Schwellenwert-Signatur-Eigenschaft.

Überblick über TUF

Auf höchster Ebene bietet TUF Anwendungen eine sichere Methode, um neue Versionen von Dateien zu kennen und zu erhalten. Oberflächlich betrachtet klingt das alles einfach. Die grundlegenden Schritte zum Aktualisieren von Anwendungen sind:

  • Wissen, dass ein Update existiert.
  • Herunterladen einer korrekten Kopie der neuesten Version der aktualisierten Datei.

Das Problem ist, dass das Aktualisieren von Anwendungen nur dann einfach ist, wenn keine böswilligen Aktivitäten im Spiel sind. Wenn ein Angreifer versucht, diese scheinbar einfachen Schritte zu stören, kann er viel tun.

Nehmen wir an, ein Software-Updater verfolgt den Ansatz der meisten Systeme (zumindest derjenigen, die versuchen, sicher zu sein). Er lädt sowohl die gewünschte Datei als auch eine kryptografische Signatur der Datei herunter. Der Software-Updater weiß bereits, welchem Schlüssel er vertraut, um die Signatur zu erstellen. Er prüft, ob die Signatur korrekt ist und von diesem vertrauenswürdigen Schlüssel erstellt wurde. Leider ist der Software-Updater immer noch auf viele Arten gefährdet, einschließlich der folgenden Szenarien:

  • Ein Angreifer gibt dem Software-Updater immer wieder dasselbe Update, sodass dieser nie von einem Update erfährt.
  • Ein Angreifer gibt dem Software-Updater eine ältere, unsichere Version einer Datei, die er bereits hat, sodass er diese herunterlädt und blind verwendet, in dem Glauben, sie sei neuer.
  • Ein Angreifer gibt dem Software-Updater eine neuere Version einer Datei, aber nicht die allerneueste. Die Datei ist für den Software-Updater neuer, aber sie kann unsicher sein und vom Angreifer ausgenutzt werden.
  • Ein Angreifer kompromittiert den zum Signieren dieser Dateien verwendeten Schlüssel und der Software-Updater lädt nun eine bösartige Datei herunter, die ordnungsgemäß signiert ist.

TUF wurde entwickelt, um diese und andere Angriffe zu bewältigen, indem signierte Metadaten (Textdateien, die die Dateien des Repositories beschreiben) zum Repository hinzugefügt und die Metadaten während des Update-Vorgangs referenziert werden. Repository-Dateien werden anhand der in den Metadaten enthaltenen Informationen verifiziert, bevor sie an das Software-Update-System übergeben werden. Das Framework bietet außerdem Multi-Signatur-Vertrauen, expliziten und impliziten Widerruf von kryptografischen Schlüsseln, Trennung der Verantwortlichkeiten für Metadaten und minimiertes Schlüsselrisiko. Eine vollständige Liste und Übersicht der von TUF behandelten Repository-Angriffe und Schwachstellen von Software-Update-Systemen finden Sie in Anhang A.

PyPI mit TUF integrieren

Ein Software-Update-System muss zwei Hauptaufgaben erfüllen, um sich in TUF zu integrieren. Erstens MUSS das Repository auf der Serverseite geändert werden, um signierte TUF-Metadaten bereitzustellen. Dieses PEP befasst sich mit dem ersten Teil der Integration und den Änderungen auf PyPI, die zur Unterstützung von Software-Updates mit TUF erforderlich sind.

Zweitens muss das Framework auf der Client-Seite des Update-Systems hinzugefügt werden. TUF kann beispielsweise mit dem pip-Paketmanager integriert werden. Daher SOLLTEN neue Versionen von pip standardmäßig TUF verwenden, um Distributionen von PyPI herunterzuladen und zu verifizieren, bevor sie installiert werden. Es können jedoch unvorhergesehene Probleme auftreten, die Benutzer daran hindern, Distributionen, einschließlich pip selbst, über TUF zu installieren oder zu aktualisieren. Daher SOLLTE pip eine Option anbieten, z. B. --unsafely-disable-package-verification, um solche Probleme zu umgehen, bis sie behoben sind. Hinweis: Der vorgeschlagene Optionsname ist bewusst lang gewählt, da ein Benutzer darauf hingewiesen werden muss, dass die Aktion unsicher und im Allgemeinen nicht empfohlen ist.

Wir gehen davon aus, dass pip TUF verwenden würde, um nur von PyPI heruntergeladene Distributionen zu verifizieren. pip KANN TAP 4 unterstützen, um TUF auch zur Überprüfung von Distributionen zu verwenden, die von anderswo heruntergeladen wurden.

Welche zusätzlichen Repository-Dateien werden auf PyPI benötigt?

Damit Paketmanager wie pip Distributionen mit TUF herunterladen und verifizieren können, müssen einige zusätzliche Dateien zu PyPI hinzugefügt werden. Diese zusätzlichen Repository-Dateien werden TUF-Metadaten genannt und enthalten Informationen wie vertrauenswürdige Schlüssel, die kryptografischen Hashes von Dateien, Signaturen, Versionsnummern der Metadaten und das Datum, nach dem die Metadaten als abgelaufen gelten sollten.

Wenn ein Paketmanager nach Updates sucht, bittet er TUF, die Arbeit zu erledigen. Das heißt, ein Paketmanager muss sich niemals mit diesen zusätzlichen Metadaten befassen oder verstehen, was darunter vor sich geht. Wenn TUF zurückmeldet, dass Updates verfügbar sind, kann ein Paketmanager TUF bitten, diese Dateien von PyPI herunterzuladen. TUF lädt sie herunter und prüft sie anhand der TUF-Metadaten, die es ebenfalls vom Repository herunterlädt. Wenn die heruntergeladenen Ziel-Dateien vertrauenswürdig sind, übergibt TUF sie an den Paketmanager.

Der Abschnitt Dokumentenformate der TUF-Spezifikation enthält Informationen über jeden erforderlichen Metadatentyp und seinen erwarteten Inhalt. Der folgende Abschnitt behandelt die verschiedenen Arten von Metadaten, die für PyPI EMPFOHLEN werden.

Zusätzlich SOLLTEN alle Ziel-Dateien mindestens zweimal auf der Festplatte verfügbar sein. Einmal unter ihrem ursprünglichen Dateinamen, um die Abwärtskompatibilität zu gewährleisten, und einmal mit ihrem SHA-512-Hash im Dateinamen. Dies ist erforderlich, um Konsistente Snapshots zu erstellen.

Abhängig vom verwendeten Dateisystem KÖNNEN verschiedene Daten-Deduplizierungsmechanismen eingesetzt werden, um Speicherplatzsteigerungen durch Hardcopies von Ziel-Dateien zu vermeiden.

PyPI und TUF-Metadaten

TUF-Metadaten liefern Informationen, die Clients für Update-Entscheidungen nutzen können. Beispielsweise listet ein *Targets*-Metadaten die auf PyPI verfügbaren Ziel-Dateien auf und enthält die erforderlichen Signaturen, kryptografischen Hashes und Dateigrößen für jede Datei. Unterschiedliche Metadatendateien liefern unterschiedliche Informationen, die von separaten Rollen signiert werden. Die *Root*-Rolle gibt an, welche Metadaten zu welcher Rolle gehören. Das Konzept der Rollen ermöglicht es TUF, Verantwortlichkeiten an mehrere Rollen zu delegieren und somit die Auswirkungen einer kompromittierten Rolle zu minimieren.

TUF erfordert vier Top-Level-Rollen: *Root*, *Timestamp*, *Snapshot* und *Targets*. Die *Root*-Rolle gibt die öffentlichen kryptografischen Schlüssel der Top-Level-Rollen (einschließlich ihrer eigenen) an. Die *Timestamp*-Rolle verweist auf den neuesten *Snapshot* und kann anzeigen, wann ein neuer Snapshot des Repositories verfügbar ist. Die *Snapshot*-Rolle gibt die neueste Version aller TUF-Metadatendateien (außer *Timestamp*) an. Die *Targets*-Rolle listet die Dateipfade der verfügbaren Ziel-Dateien zusammen mit ihren kryptografischen Hashes auf. Die Dateipfade müssen relativ zu einer Basis-URL angegeben werden. Dies ermöglicht es, die tatsächlichen Ziel-Dateien von überall aus zu liefern, solange die Basis-URL vom Client zugänglich ist. Jede Top-Level-Rolle erfüllt ihre Aufgaben ausnahmslos. Tabelle 1 gibt einen Überblick über die in TUF verwendeten Rollen.

Rollen und Verantwortlichkeiten
Root Die Root-Rolle ist der Vertrauensanker für das gesamte Repository. Die Root-Rolle signiert die Metadatendatei root.json. Diese Datei gibt an, welche Schlüssel für jede der Top-Level-Rollen autorisiert sind, einschließlich der Root-Rolle selbst. Die Rollen „root“, „snapshot“, „timestamp“ und „targets“ müssen angegeben werden, und jede hat eine Liste öffentlicher Schlüssel.
Targets Die Targets-Rolle ist dafür verantwortlich, anzugeben, welche Ziel-Dateien vom Repository verfügbar sind. Genauer gesagt teilt sie die Verantwortung für die Bereitstellung von Informationen über den Inhalt von Updates. Die Targets-Rolle signiert Metadaten von targets.json und kann die Vertrauenswürdigkeit für Repository-Dateien auf andere Rollen (delegierte Rollen) übertragen.
Delegierte Rollen Wenn die Top-Level-Targets-Rolle eine Delegation durchführt, können die daraus resultierenden delegierten Rollen ihre eigenen Metadatendateien bereitstellen. Das Format der von delegierten Targets-Rollen bereitgestellten Metadatendateien ist dasselbe wie das von targets.json. Wie bei targets.json werden die neuesten Versionen von Metadatendateien, die zu delegierten Rollen gehören, in den Metadaten der Snapshot-Rolle beschrieben.
Snapshot Die Snapshot-Rolle ist dafür verantwortlich, sicherzustellen, dass Clients einen konsistenten Repository-Status sehen. Sie liefert Repository-Statusinformationen, indem sie die neuesten Versionen der Top-Level-Targets- und delegierten Targets-Metadatendateien im Repository in snapshot.json angibt. Root und Timestamp sind nicht in snapshot.json aufgeführt, da Timestamp für seine Aktualität signiert, nachdem snapshot.json erstellt wurde, und Root, das alle Top-Level-Schlüssel besitzt, im Voraus erforderlich ist, um irgendeine der Top-Level-Rollen zu vertrauen.
Timestamp Die Timestamp-Rolle ist dafür verantwortlich, Informationen über die Aktualität verfügbarer Updates bereitzustellen. Zeitlichkeitsinformationen werden bereitgestellt, indem häufig eine neue timestamp.json-Datei mit einer kurzen Ablaufzeit signiert wird. Diese Datei gibt die neueste Version von snapshot.json an.

Tabelle 1: Überblick über die TUF-Rollen.

Sofern nicht anders angegeben, EMPFIEHLT dieses PEP, dass jede Metadaten- oder Ziel-Datei mit der SHA2-512-Funktion der SHA-2-Familie gehasht wird. SHA-2 hat native und gut getestete Unterstützung für Python 2 und 3 (was die Überprüfung dieser Hashes ohne zusätzliche, nicht-Python-Abhängigkeiten ermöglicht). Wenn stärkere Sicherheitsgarantien erforderlich sind, KÖNNEN stattdessen sowohl SHA2-256 als auch SHA512 oder sowohl SHA2-256 als auch SHA3-256 verwendet werden. SHA2-256 und SHA3-256 basieren auf sehr unterschiedlichen Designs voneinander und bieten zusätzlichen Schutz vor Kollisionsangriffen. SHA-3 erfordert jedoch die Installation zusätzlicher, nicht-Python-Abhängigkeiten für Python 2.

Metadaten signieren und Repository-Verwaltung

Die Top-Level- *Root*-Rolle signiert die Schlüssel der Top-Level- *Timestamp*-, *Snapshot*-, *Targets*- und *Root*-Rollen. Die *Timestamp*-Rolle signiert jeden neuen Snapshot der Repository-Metadaten. Die *Snapshot*-Rolle signiert *Root*, *Targets* und alle delegierten Targets-Rollen. Die delegierte Targets-Rolle *bins* delegiert weiter an die *bin-n*-Rollen, die alle zu registrierten PyPI-Projekten gehörenden Distributionsdateien signieren.

Abbildung 1 gibt einen Überblick über die auf PyPI verfügbaren Rollen, einschließlich der Top-Level-Rollen und der von *Targets* delegierten Rollen. Die Abbildung zeigt auch die Arten von Schlüsseln, die zur Signierung jeder Rolle verwendet werden, und welche Rollen zum Signieren von auf PyPI verfügbaren Dateien vertrauenswürdig sind. Die nächsten beiden Abschnitte behandeln die Details der Signierung von Repository-Dateien und die für jede Rolle verwendeten Schlüsseltypen.

../_images/pep-0458-1.png

Abbildung 1: Überblick über die auf PyPI verfügbaren Rollen-Metadaten.

Die Rollen, die sich am häufigsten ändern, sind *Timestamp*, *Snapshot* und die von *bins* delegierten Rollen (d. h. *bin-n*). Die Metadaten *Timestamp* und *Snapshot* MÜSSEN aktualisiert werden, wenn die Metadaten *Root*, *Targets* oder delegierte Metadaten aktualisiert werden. Beachten Sie jedoch, dass die Metadaten *Root* und *Targets* viel seltener aktualisiert werden als delegierte Metadaten. Ebenso wird die *bins*-Rolle nur aktualisiert, wenn eine *bin-n*-Rolle hinzugefügt, aktualisiert oder entfernt wird. Daher werden die Metadaten *Timestamp*, *Snapshot* und *bin-n* höchstwahrscheinlich häufig (möglicherweise jede Minute) aktualisiert, da delegierte Metadaten häufig aktualisiert werden, um die kontinuierliche Bereitstellung von Projekten zu unterstützen. Kontinuierliche Bereitstellung ist eine Reihe von Prozessen, die PyPI verwendet, um Snapshots zu erstellen, die sicher koexistieren und unabhängig von anderen Snapshots gelöscht werden können [18].

Jährlich SOLLTEN PyPI-Administratoren die Schlüssel für die *Root*- und *Targets*-Rollen signieren. Automatisierung wird kontinuierlich einen zeitgestempelten Snapshot aller Projekte signieren. Ein Repository Metadaten-API steht zur Verfügung, mit dem ein TUF-Repository verwaltet werden kann.

Im Normalbetrieb werden die *bin-n*-Metadaten signiert und aktualisiert, wenn neue Distributionen auf PyPI hochgeladen werden. Es wird jedoch auch ein einmaliger Online-Initialisierungsmechanismus benötigt, um *bin-n*-Metadaten für alle bestehenden Distributionen, die Teil des PyPI-Repositorys sind, bei jeder Reinitialisierung von PyPI zu erstellen und zu signieren.

Wie man anfängliches Vertrauen in die PyPI-Root-Schlüssel aufbaut

Paketmanager wie pip MÜSSEN die *Root*-Metadatendatei mit den Installationsdateien ausliefern, die Benutzer ursprünglich herunterladen. Dies umfasst Informationen über die vertrauenswürdigen Schlüssel für alle Top-Level-Rollen (einschließlich der Root-Schlüssel selbst). Paketmanager müssen außerdem eine TUF-Client-Bibliothek mitliefern. Jede neue Version von *Root*-Metadaten, die die TUF-Client-Bibliothek herunterladen könnte, wird anhand der ursprünglich mit dem Paketmanager gelieferten Root-Schlüssel verifiziert. Wenn ein Root-Schlüssel kompromittiert wird, aber ein Schwellenwert von Schlüsseln weiterhin gesichert ist, MÜSSEN PyPI-Administratoren neue *Root*-Metadaten verteilen, die das Vertrauen in die kompromittierten Schlüssel widerrufen. Wenn ein Schwellenwert von Root-Schlüsseln kompromittiert wird, MÜSSEN die *Root*-Metadaten Out-of-Band aktualisiert werden. (Der Schwellenwert für Root-Schlüssel sollte jedoch so gewählt werden, dass dieses Ereignis extrem unwahrscheinlich ist.) Paketmanager müssen nicht sofort aktualisiert werden, wenn Root-Schlüssel zwischen neuen Versionen des Paketmanagers widerrufen oder hinzugefügt werden, da der TUF-Update-Prozess automatisch Fälle behandelt, in denen ein Schwellenwert früherer *Root*-Schlüssel für neue *Root*-Schlüssel signiert (vorausgesetzt, es gibt keine Abwärtsinkompatibilitäten in der verwendeten TUF-Spezifikation). Wenn also beispielsweise ein Paketmanager ursprünglich mit Version 1 der *Root*-Metadaten ausgeliefert wurde und ein Schwellenwert von *Root*-Schlüsseln in Version 1 für Version 2 der *Root*-Metadaten signierte und ein Schwellenwert von *Root*-Schlüsseln in Version 2 für Version 3 der *Root*-Metadaten signierte, dann sollte der Paketmanager seine Kopie der *Root*-Metadaten von Version 1 auf 3 transparent aktualisieren können, indem er seine TUF-Client-Bibliothek verwendet.

Somit, um dies zu wiederholen, müssen die neueste gute Kopie der *Root*-Metadaten und eine TUF-Client-Bibliothek in jeder neuen Version von pip enthalten sein, die mit CPython (über ensurepip) ausgeliefert wird. Die TUF-Client-Bibliothek im Paketmanager lädt dann die *Root*-Metadaten und lädt den Rest der Rollen herunter, einschließlich der Aktualisierung der *Root*-Metadaten, falls diese sich geändert haben. Eine Übersicht über den Update-Prozess ist verfügbar.

Minimales Sicherheitsmodell

Es gibt zwei Sicherheitsmodelle, die bei der Integration von TUF in PyPI zu berücksichtigen sind. Das in diesem PEP vorgeschlagene ist das minimale Sicherheitsmodell, das die Überprüfung von PyPI-Distributionen unterstützt, die mit privaten kryptografischen Schlüsseln signiert sind, die auf PyPI gespeichert sind. Von Entwicklern hochgeladene Distributionen werden von PyPI signiert und sind sofort zum Download verfügbar. Eine mögliche zukünftige Erweiterung dieses PEP, die in PEP 480 diskutiert wird, schlägt das maximale Sicherheitsmodell vor und ermöglicht es einem Entwickler, für sein Projekt zu signieren. Entwicklerschlüssel werden nicht online gespeichert: Daher sind Projekte sicher vor PyPI-Kompromittierungen.

Das minimale Sicherheitsmodell erfordert keine Aktion von einem Entwickler und schützt vor böswilligen CDNs [19] und öffentlichen Spiegeln. Zur Unterstützung der kontinuierlichen Bereitstellung von hochgeladenen Distributionen signiert PyPI Projekte mit einem Online-Schlüssel. Dieses Sicherheitsniveau verhindert, dass Projekte versehentlich oder absichtlich von einem Spiegel oder einer CDN manipuliert werden, da keiner der Schlüssel zum Signieren von Projekten vorhanden ist. Es schützt jedoch Projekte nicht vor Angreifern, die PyPI kompromittiert haben, da diese dann TUF-Metadaten mit den online gespeicherten Schlüsseln manipulieren können.

Dieses PEP schlägt vor, dass die *bin-n*-Rollen alle PyPI-Projekte mit Online-Schlüsseln signieren. Diese *bin-n*-Rollen MÜSSEN alle von der übergeordneten *bins*-Rolle delegiert werden, die mit einem Offline-Schlüssel signiert ist, und im Gegenzug MÜSSEN sie von der Top-Level- *Targets*-Rolle delegiert werden, die ebenfalls mit einem Offline-Schlüssel signiert ist. Das bedeutet, dass ein Paketmanager wie pip (d. h. mit TUF) beim Herunterladen einer Distributionsdatei von einem Projekt auf PyPI die *Targets*-Rolle bezüglich der TUF-Metadaten für diese Distributionsdatei konsultiert. Wenn letztendlich keine *bin-n*-Rollen, die von *Targets* über *bins* delegiert werden, die Distributionsdatei spezifizieren, dann gilt sie auf PyPI als nicht existent.

Beachten Sie, der Grund, warum *Targets* nicht direkt an *bin-n* delegiert, sondern die Zwischenrolle *bins* verwendet, ist, dass andere Delegation leicht hinzugefügt oder entfernt werden können, ohne die *bins*-zu-*bin-n*-Zuordnung zu beeinträchtigen. Dies ist entscheidend für die Implementierung von PEP 480.

Metadaten-Ablaufzeiten

Die Metadaten für die *Root*-, *Targets*- und *bins*-Rollen SOLLTEN jeweils in einem Jahr ablaufen, da diese Metadatendateien voraussichtlich nur sehr selten geändert werden.

Die Metadaten *Timestamp*, *Snapshot* und *bin-n* SOLLTEN jeweils in einem Tag ablaufen, da eine CDN oder ein Spiegel sich täglich mit PyPI synchronisieren SOLLTE. Darüber hinaus berücksichtigt dieser großzügige Zeitrahmen auch Client-Uhren, die stark abweichen oder verstellt sind.

Metadaten-Skalierbarkeit

Mit zunehmender Anzahl von Projekten und Distributionen in einem Repository muss auch die TUF-Metadaten entsprechend wachsen. Betrachten wir beispielsweise die bins-Rolle. Im August 2013 wurde festgestellt, dass die Größe der bins-Metadaten etwa 42 MB betrug, wenn die bins-Rolle selbst für etwa 220.000 PyPI-Ziele (einfache Indizes und Distributionen) unterzeichnete. Dieses PEP befasst sich nicht im Detail damit, aber TUF verfügt über ein sogenanntes „hashed bin delegation“-Schema, das eine große targets-Metadatendatei in viele kleine aufteilt. Dies ermöglicht es einem TUF-Client-Updater, intelligent nur eine kleine Anzahl von TUF-Metadatendateien herunterzuladen, um jedes von der bins-Rolle signierte Projekt zu aktualisieren. Beispielsweise führte die Anwendung dieses Schemas auf das vorherige Repository dazu, dass pip zwischen 1,3 KB und 111 KB herunterlud, um ein PyPI-Projekt über TUF zu installieren oder zu aktualisieren.

Basierend auf unseren Erkenntnissen zum Zeitpunkt der Aktualisierung dieses Dokuments für die Implementierung (7. November 2019), zusammengefasst in den Tabellen 2-3, SOLLTE PyPI alle Ziele in der bins-Rolle aufteilen, indem sie an 16.384 bin-n-Rollen delegiert werden (siehe C10 in Tabelle 2). Jede bin-n-Rolle würde die PyPI-Ziele signieren, deren SHA2-512-Hashes in diesen Bin fallen (siehe Abbildung 1 und Konsistente Snapshots). Es wurde festgestellt, dass diese Anzahl von Bins zu einem Metadaten-Overhead von 5-9% (relativ zur durchschnittlichen Größe der heruntergeladenen Distributionsdateien; siehe V13 und V15 in Tabelle 3) für wiederkehrende Benutzer und einem Overhead von 69% für neue Benutzer, die pip zum ersten Mal installieren, führt (siehe V17 in Tabelle 3).

Einige Annahmen, die bei der Berechnung dieser Metadaten-Overhead-Prozentsätze verwendet wurden

  1. Wir ignorieren root-, timestamp- und Top-Level-targets-Metadaten.
  2. pip wird immer mit der neuesten guten Kopie der Metadaten für alle Rollen gebündelt.
Name Description Wert
C1 Anzahl der Bytes in einem SHA2-512-Hexadezimal-Digest 128
C2 Anzahl der Bytes für eine SHA2-512-Public-Key-ID 64
C3 Anzahl der Bytes für eine Ed25519-Signatur 128
C4 Anzahl der Bytes für einen Ed25519-Public-Key 64
C5 Anzahl der Bytes für einen relativen Zieldateipfad 256
C6 Anzahl der Bytes zur Kodierung einer Zieldateigröße 7
C7 Anzahl der Bytes zur Kodierung einer Versionsnummer 6
C8 Anzahl der Ziele (einfache Indizes und Distributionen) 2,273,539
C9 Durchschnittliche Anzahl von Bytes für eine heruntergeladene Distribution 2,184,393
C10 Anzahl der Bins 16,384

C8 wurde durch Abfragen der Anzahl der Release-Dateien berechnet. C9 wurde abgeleitet, indem der Durchschnitt zwischen einer groben Schätzung der durchschnittlichen Größe der Release-Dateien, die in den letzten 31 Tagen heruntergeladen wurden (1.628.321 Bytes), und der durchschnittlichen Größe der Release-Dateien auf der Festplatte (2.740.465 Bytes) genommen wurde. Ee Durbin half bei der Bereitstellung dieser Zahlen am 7. November 2019.

Tabelle 2: Eine Liste von Konstanten, die zur Berechnung des Metadaten-Overheads verwendet werden.

Name Description Formel Wert
V1 Länge eines Pfad-Hash-Präfixes math.ceil(math.log(C10, 16)) 4
V2 Gesamtzahl der Pfad-Hash-Präfixe 16**V1 65,536
V3 Durchschnittliche Anzahl von Zielen pro Bin math.ceil(C8/C10) 139
V4 Durchschnittliche Größe von SHA-512-Hashes pro Bin V3*C1 17,792
V5 Durchschnittliche Größe von Zielpfaden pro Bin V3*C5 35,584
V6 Durchschnittliche Größe von Längen pro Bin V3*C6 973
V7 Durchschnittliche Größe von bin-n-Metadaten (Bytes) V4+V5+V6 54,349
V8 Gesamtgröße der Public-Key-IDs in Bins C10*C2 1,048,576
V9 Gesamtgröße der Pfad-Hash-Präfixe in Bins V1*V2 262,144
V10 Geschätzte Größe der Bins-Metadaten (Bytes) V8+V9 1,310,720
V11 Geschätzte Größe der Snapshot-Metadaten (Bytes) C10*C7 98,304
V12 Geschätzter Metadaten-Overhead pro Distribution pro wiederkehrendem Benutzer (derselbe Snapshot) 2*V7 108,698
V13 Geschätzter Metadaten-Overhead pro Distribution pro wiederkehrendem Benutzer (derselbe Snapshot) round((V12/C9)*100) 5%
V14 Geschätzte Größe des Metadaten-Overheads pro Distribution pro wiederkehrendem Benutzer (anderer Snapshot) V12+V11 207,002
V15 Geschätzter Metadaten-Overhead pro Distribution pro wiederkehrendem Benutzer (anderer Snapshot) round((V14/C9)*100) 9%
V16 Geschätzte Größe des Metadaten-Overheads pro Distribution pro neuem Benutzer V14+V10 1,517,722
V17 Geschätzter Metadaten-Overhead pro Distribution pro neuem Benutzer round((V16/C9)*100) 69%

Tabelle 3: Geschätzte Metadaten-Overheads für neue und wiederkehrende Benutzer.

Der interessierte Leser findet hier eine interaktive Version des Metadaten-Overhead-Rechners: hier

Diese Anzahl von Bins SOLLTE steigen, wenn der Metadaten-Overhead für wiederkehrende Benutzer 50 % überschreitet. Derzeit SOLLTE dies geschehen, wenn die Anzahl der Ziele mindestens um das 10-fache von über 2 Mio. auf über 22 Mio. steigt, wobei der Metadaten-Overhead für wiederkehrende und neue Benutzer dann etwa 50-54 % bzw. 114 % betragen würde, vorausgesetzt, die Anzahl der Bins bleibt gleich. Wenn die Anzahl der Bins erhöht wird, wären die Kosten für alle Benutzer effektiv die Kosten für neue Benutzer, da ihre Kosten durch die (gelegentlichen) Kosten für den Download der großen Anzahl von Delegationen in den bins-Metadaten dominiert würden. Wenn die Kosten für neue Benutzer zu hoch sind, hauptsächlich aufgrund des Overheads beim Herunterladen der bins-Metadaten, SOLLTE dieses Thema überprüft werden, bevor dies geschieht.

Beachten Sie, dass Änderungen an der Anzahl der Bins auf dem Server für den Client transparent sind. Der Paketmanager muss einen neuen Satz Metadaten herunterladen, als wäre er ein neuer Benutzer, aber diese Operation erfordert keine explizite Logik oder Benutzerinteraktion.

Es ist möglich, TUF-Metadaten kompakter zu gestalten, indem sie in einem binären Format anstelle des JSON-Textformats dargestellt werden. Dennoch werden eine ausreichend große Anzahl von Projekten und Distributionen irgendwann Skalierbarkeitsprobleme verursachen, und daher werden für die bins-Rolle immer noch Delegationen benötigt (wie in Abbildung 1 skizziert), um das Problem zu lösen. Das JSON-Format ist ein offener und bekannter Standard für den Datenaustausch, der bereits von der TUF-Referenzimplementierung unterstützt wird und daher das empfohlene Datenformat dieses PEP ist. Aufgrund der großen Anzahl von Delegationen SOLLTEN jedoch auch komprimierte Versionen aller Metadaten über die bestehenden Warehouse-Mechanismen für HTTP-Komprimierung für Clients verfügbar gemacht werden. Darüber hinaus könnten die JSON-Metadaten vor dem Senden an Clients komprimiert werden. Die TUF-Referenzimplementierung unterstützt derzeit nicht den Download komprimierter JSON-Metadaten, dies könnte jedoch hinzugefügt werden, um die Metadatengröße zu reduzieren.

PyPI und Schlüsselanforderungen

In diesem Abschnitt werden die Arten von Schlüsseln untersucht, die zum Signieren von TUF-Rollen auf PyPI erforderlich sind. TUF ist hinsichtlich der Wahl von digitalen Signaturalgorithmen agnostisch. Dieses PEP EMPFIEHLT jedoch, dass alle digitalen Signaturen mit dem Ed25519-Algorithmus erzeugt werden [15]. Ed25519 verfügt über native und gut getestete Python-Unterstützung (ermöglicht die Verifizierung von Signaturen ohne zusätzliche, nicht-Python-Abhängigkeiten), verwendet kleine Schlüssel und wird von modernen HSM- und Authentifizierungs-Token-Hardware unterstützt.

Verwaltung von Online-Schlüsseln

Der von den timestamp-, snapshot- und allen bin-n-Rollen gemeinsam genutzte Online-Schlüssel KANN, verschlüsselt oder unverschlüsselt, auf der Python-Infrastruktur gespeichert werden. Zum Beispiel KANN der Schlüssel auf einem selbst gehosteten Schlüsselverwaltungsservice (z.B. Hashicorp Vault) oder einem Drittanbieter (z.B. AWS KMS, Google Cloud KMS oder Azure Key Vault) gespeichert werden.

Einige dieser Schlüsselverwaltungsservices erlauben die Speicherung von Schlüsseln auf Hardware Security Modules (HSMs) (z.B. Hashicorp Vault, AWS CloudHSM, Google Cloud HSM, Azure Key Vault). Dies verhindert, dass Angreifer den Online-Privatschlüssel exfiltrieren (jedoch nicht, ihn zu verwenden, obwohl ihre Aktionen nun kryptografisch überprüfbar sind). Dies erfordert jedoch eine Modifikation der Referenz-TUF-Implementierung zur Unterstützung von HSMs (WIP).

Unabhängig davon, wo und wie dieser Online-Schlüssel aufbewahrt wird, SOLLTE seine Verwendung sorgfältig protokolliert, überwacht und auditiert werden, idealerweise so, dass Angreifer, die PyPI kompromittieren, diese Protokollierung, Überwachung und Auditierung nicht sofort abschalten können.

Verwaltung von Offline-Schlüsseln

Wie im vorherigen Abschnitt erläutert, MÜSSEN die Schlüssel der root-, targets- und bins-Rollen für maximale Sicherheit offline sein. Diese Schlüssel werden offline sein in dem Sinne, dass ihre privaten Schlüssel NICHT auf PyPI gespeichert werden dürfen, obwohl einige von ihnen in der privaten Infrastruktur des Projekts online sein KÖNNTEN.

Es SOLLTE eine Offline-Schlüsselzeremonie geben, um diese Schlüssel so zu generieren, zu sichern und zu speichern, dass die privaten Schlüssel nur von den Python-Administratoren bei Bedarf gelesen werden können (z.B. zum Rotieren der Schlüssel für die Top-Level-TUF-Rollen). Daher SOLLTEN Schlüssel generiert werden, vorzugsweise an einem physischen Ort, an dem Side-Channel- Angriffe keine Rolle spielen, unter Verwendung von

  1. Einem vertrauenswürdigen, air-gapped Computer mit einem echten Zufallszahlengenerator generator und ohne dass Daten nach der Zeremonie verbleiben
  2. Ein vertrauenswürdiges Betriebssystem
  3. Ein vertrauenswürdiger Satz von Drittanbieterpaketen (wie z.B. aktualisierte Versionen von kryptografischen Bibliotheken oder die TUF-Referenzimplementierung, wenn die vom vertrauenswürdigen Betriebssystem bereitgestellten Versionen nicht aktuell genug sind)

Um die Persistenz sensibler Daten (z.B. privater Schlüssel) über Backup-Medien hinaus nach der Zeremonie zu vermeiden, SOLLTEN Offline-Schlüssel verschlüsselt mit starken Passwörtern generiert werden, entweder auf (in absteigender Reihenfolge des Vertrauens): privaten HSMs (z.B. YubiHSM), Cloud-basierten HSMs (z.B. die oben genannten), im flüchtigen Speicher (z.B. RAM) oder im nicht-flüchtigen Speicher (z.B. SSD oder microSD). Wenn Schlüssel auf nicht-flüchtigem Speicher generiert werden müssen, MUSS dieser Speicher nach der sicheren Sicherung der Schlüssel unwiederbringlich zerstört werden.

Passwörter, die zur Verschlüsselung von Schlüsseln verwendet werden, SOLLTEN an einem dauerhaften und vertrauenswürdigen Ort gespeichert werden, zu dem nur Python-Admins Zugang haben.

Um OPSEC-Fehler während der Zeremonie zu minimieren, SOLLTEN Skripte für die Ausführung auf dem vertrauenswürdigen Schlüsselgenerierungscomputer geschrieben werden, um zeitraubende Schritte der Zeremonie zu automatisieren, wie z.B.

  • Exportieren von allem Code und allen Daten (frühere TUF-Metadaten und root-Schlüssel), die zur Generierung neuer Schlüssel und zum Ersetzen alter Schlüssel erforderlich sind, auf Sneakernet
  • Verschärfen der Firewall, Aktualisieren des gesamten Betriebssystems, um Sicherheitslücken zu beheben, und Airgapping des Computers
  • Exportieren aller neuen TUF-Metadaten und Schlüssel auf verschlüsselte Backup-Medien. Dieses Backup liefert eine vollständige Kopie der Daten, die zur Wiederherstellung des PyPI-TUF-Repositorys erforderlich sind
  • Exportieren nur neuer TUF-Metadaten und Online-Schlüssel auf verschlüsselte Backup-Medien. Dieses Backup liefert alle Online-Daten für den Import in die PyPI-Infrastruktur und ist nützlich, z.B. wenn die Online-Daten aus einem früheren archivierten Zustand wiederhergestellt werden müssen
  • Ausdrucken und Speichern kryptografischer Hashes neuer TUF-Metadaten. Diese ausgedruckte Kopie liefert ein zusätzliches Offline-Papier-Backup, das als Vergleich im Falle einer Kompromittierung verwendet werden kann

Beachten Sie, dass die Einmal-Schlüssel für die targets- und bins-Rollen sicher während der Offline-Schlüsselzeremonie generiert, verwendet und gelöscht werden KÖNNEN. Darüber hinaus MÜSSEN die root-Schlüssel NICHT während der Offline-Schlüsselzeremonie selbst generiert werden. Stattdessen KANN ein Schwellenwert t von n Python-Administratoren, wie oben diskutiert, die root-Metadaten nach der Offline-Schlüsselzeremonie, die zur Generierung aller anderen Schlüssel verwendet wurde, unabhängig voneinander signieren.

Wie sollen Metadaten generiert werden?

Projektentwickler erwarten, dass die Distributionen, die sie auf PyPI hochladen, sofort zum Download verfügbar sind. Leider wird es Probleme geben, wenn viele Leser und Schreiber gleichzeitig auf dieselben Metadaten- und Zieldateien zugreifen. Das heißt, es muss einen Weg geben, die Konsistenz von Metadaten- und Zieldateien zu gewährleisten, wenn mehrere Entwickler diese Dateien gleichzeitig ändern. Es gibt auch Probleme mit der Konsistenz auf PyPI ohne TUF, aber das Problem ist mit signierten Metadaten, die die auf PyPI verfügbaren Dateien in Echtzeit verfolgen MÜSSEN, schwerwiegender.

Angenommen, PyPI generiert einen snapshot, der die neueste Version aller Metadaten außer timestamp auf Version 1 anzeigt, und ein Client fordert diesen snapshot von PyPI an. Während der Client mit dem Herunterladen dieses snapshot beschäftigt ist, versieht PyPI einen neuen Snapshot mit einer Zeitstempelung, sagen wir, Version 2. Ohne die Konsistenz der Metadaten zu gewährleisten, hätte der Client eine Kopie von snapshot, die nicht mit dem auf PyPI verfügbaren übereinstimmt. Das Ergebnis wäre nicht von willkürlich von einem Angreifer eingefügten Metadaten zu unterscheiden. Das Problem würde auch bei Spiegeln auftreten, die versuchen, sich mit PyPI zu synchronisieren.

Konsistente Snapshots

Um die TUF-Metadaten auf PyPI mit den hochgradig volatilen Zieldateien konsistent zu halten, SOLLTEN konsistente Snapshots verwendet werden. Jeder konsistente Snapshot erfasst den Zustand aller bekannten Projekte zu einem bestimmten Zeitpunkt und KANN sicher mit jedem anderen Snapshot koexistieren oder unabhängig gelöscht werden, ohne andere Snapshots zu beeinträchtigen.

Um konsistente Snapshots zu erhalten, MÜSSEN alle TUF-Metadaten beim Schreiben auf die Festplatte eine Versionsnummer in ihrem Dateinamen enthalten

VERSION_NUMBER.ROLENAME.json,
wobei VERSION_NUMBER eine inkrementierende Ganzzahl ist und ROLENAME eine der Top-Level-Metadatenrollen ist – root, snapshot oder targets – oder eine der delegierten Ziele-Rollen – bins oder bin-n.

Die einzige Ausnahme ist die timestamp-Metadatendatei, deren Version beim Aktualisieren durch einen Client nicht im Voraus bekannt wäre. Die timestamp-Metadaten listen die Version der snapshot-Metadaten auf, die wiederum die Versionen der targets- und delegierten Ziele-Metadaten auflistet, alles als Teil eines gegebenen konsistenten Snapshots.

Bei normaler Verwendung ist ein Überlauf der Versionsnummer unwahrscheinlich. Eine 8-Byte-Ganzzahl kann beispielsweise einmal pro Millisekunde inkrementiert werden und fast 300 Millionen Jahre halten. Wenn ein Angreifer die Versionsnummer willkürlich erhöht, kann sich das Repository durch Widerrufen der kompromittierten Schlüssel und Zurücksetzen der Versionsnummer erholen, wie in der TUF- Spezifikation beschrieben.

Die targets- oder delegierten Ziele-Metadaten verweisen auf die eigentlichen Zieldateien, einschließlich ihrer kryptografischen Hashes wie oben angegeben. Um eine Zieldatei als Teil eines konsistenten Snapshots zu kennzeichnen, MUSS sie daher beim Schreiben auf die Festplatte ihren Hash im Dateinamen enthalten

HASH.DATEINAME
wobei HASH der Hex-Digest des Hashes des Dateiinhaltes ist und DATEINAME der ursprüngliche Dateiname ist.

Dies bedeutet, dass es mehrere Kopien jeder Zieldatei geben KANN, eine für jede der oben genannten kryptografischen Hash-Funktionen.

Unter der Annahme von unendlichem Speicherplatz, streng inkrementierender Versionsnummern und keiner Hash-Kollisionen kann ein Client sicher von einem Snapshot lesen, während PyPI einen anderen Snapshot produziert.

Clients wie pip, die das TUF-Protokoll verwenden, MÜSSEN modifiziert werden, um jede Metadaten- und Zieldatei herunterzuladen, mit Ausnahme der timestamp-Metadaten. Dies geschieht, indem in der Dateianforderung die Version der Datei (für Metadaten) oder der kryptografische Hash der Datei (für Zieldateien) im Dateinamen enthalten ist.

Auf diese einfache, aber effektive Weise kann PyPI einen konsistenten Schnappschuss aller Projekte und der zugehörigen Metadaten zu einem bestimmten Zeitpunkt erfassen. Der nächste Unterabschnitt liefert Implementierungsdetails dieser Idee.

Hinweis: Dieses PEP verbietet nicht die Verwendung fortschrittlicher Dateisysteme oder Tools zur Erstellung konsistenter Snapshots. Es gibt zwei wichtige Gründe, warum dieses PEP eine einfache Lösung vorschlägt. Erstens schreibt die Lösung nicht vor, dass PyPI ein bestimmtes Dateisystem oder Tool verwendet. Zweitens ermöglicht der generische dateisystembasierte Ansatz Spiegeln die Verwendung vorhandener Dateiübertragungstools wie rsync, um konsistente Snapshots effizient von PyPI zu übertragen.

Erstellung konsistenter Snapshots

Wenn eine neue Distributionsdatei auf PyPI hochgeladen wird, MUSS PyPI die verantwortliche bin-n-Metadaten aktualisieren. Denken Sie daran, dass alle Zieldateien nach ihren Dateinamen-Hashes in Bins sortiert werden. PyPI MUSS auch snapshot aktualisieren, um die aktualisierten bin-n-Metadaten zu berücksichtigen, und timestamp, um die aktualisierten snapshot-Metadaten zu berücksichtigen. Diese Aktualisierungen SOLLTEN von einem automatisierten snapshot process behandelt werden.

Dateiuploads KÖNNEN parallel behandelt werden, jedoch MÜSSEN konsistente Snapshots streng sequenziell erstellt werden. Darüber hinaus KANN, solange Distributionsdateien in sich geschlossen sind, für jede hochgeladene Datei ein konsistenter Snapshot erstellt werden. Um dies zu tun, legen die Upload-Prozesse neue Distributionsdateien in eine nebenläufigkeitssichere FIFO-Warteschlange, und der Snapshot-Prozess liest nacheinander aus dieser Warteschlange und führt die folgenden Aufgaben aus:

Zuerst fügt er den neuen Dateipfad zu den relevanten bin-n-Metadaten hinzu, inkrementiert seine Versionsnummer, signiert ihn mit dem bin-n-Rollen-Schlüssel und schreibt ihn als VERSION_NUMBER.bin-N.json.

Dann nimmt er die aktuellsten snapshot-Metadaten, aktualisiert seine bin-n-Metadaten-Versionsnummern, inkrementiert seine eigene Versionsnummer, signiert sie mit dem snapshot-Rollen-Schlüssel und schreibt sie als VERSION_NUMBER.snapshot.json.

Und schließlich nimmt der Snapshot-Prozess die aktuellsten timestamp-Metadaten, aktualisiert seinen snapshot-Metadaten-Hash und seine Versionsnummer, inkrementiert seine eigene Versionsnummer, setzt eine neue Ablaufzeit, signiert sie mit dem timestamp-Rollen-Schlüssel und schreibt sie als timestamp.json.

Beim Aktualisieren von bin-n-Metadaten für einen konsistenten Snapshot SOLLTE der Snapshot-Prozess auch neue oder aktualisierte Hashes von einfachen Indexseiten in die relevanten bin-n-Metadaten aufnehmen. Beachten Sie, dass einfache Indexseiten dynamisch bei API-Aufrufen generiert werden können, daher ist es wichtig, dass ihre Ausgabe über die Gültigkeitsdauer eines konsistenten Snapshots stabil bleibt.

Da der Snapshot-Prozess konsistente Snapshots streng sequenziell erstellen MUSS, stellt er einen Engpass dar. Glücklicherweise ist die Signierung schnell genug, dass dies tausendmal oder öfter pro Sekunde erfolgen kann.

Darüber hinaus KANN PyPI Distributionsdateien an Clients ausliefern, bevor die entsprechenden konsistenten Snapshot-Metadaten generiert sind. In diesem Fall SOLLTE die Client-Software den Benutzer informieren, dass der vollständige TUF-Schutz noch nicht verfügbar ist, aber bald sein wird.

PyPI SOLLTE ein Transaktionsprotokoll verwenden, um Upload-Prozesse und die Snapshot-Warteschlange für Auditing und zur Wiederherstellung nach Serverfehlern aufzuzeichnen.

Bereinigung alter Metadaten

Um zu vermeiden, dass der Speicherplatz durch die ständige Erzeugung neuer konsistenter Snapshots ausgeht, SOLLTE PyPI regelmäßig alte konsistente Snapshots löschen, d.h. Metadaten- und Zieldateien, die vor einiger Zeit obsolet wurden, z.B. vor 1 Stunde.

Um den letzten konsistenten Snapshot zu erhalten, KANN PyPI einen „Mark-and-Sweep“-Algorithmus verwenden. Das heißt, es wird vom Stamm des neuesten konsistenten Snapshots aus gestartet, d.h. timestamp über snapshot über targets und delegierte Ziele bis zu den Zieldateien, wobei alle besuchten Dateien markiert werden, und alle unmarkierten Dateien gelöscht werden. Die letzten paar konsistenten Snapshots können auf ähnliche Weise erhalten bleiben.

Das Löschen eines konsistenten Snapshots führt dazu, dass Clients bei jeder Anfrage nach einer Datei innerhalb dieses konsistenten Snapshots nur HTTP 404-Antworten erhalten. Clients SOLLTEN dann ihre Anfragen (wie zuvor) mit dem neuesten konsistenten Snapshot erneut versuchen.

Beachten Sie, dass root-Metadaten, obwohl versioniert, kein Teil eines konsistenten Snapshots sind. PyPI darf alte Versionen von root-Metadaten NICHT löschen. Dies garantiert, dass Clients die neuesten root-Schlüssel aktualisieren können, egal wie veraltet ihre lokalen root-Metadaten sind.

Vertrauen in Projekte und Distributionen widerrufen

Von Zeit zu Zeit muss entweder ein Projekt oder eine Distribution widerrufen werden. Um das Vertrauen in ein Projekt oder eine Distribution zu widerrufen, kann die zugehörige bin-n-Rolle einfach die entsprechenden Ziele entfernen und die bin-n-Metadaten neu signieren. Diese Aktion erfordert nur Aktionen mit dem Online-bin-n-Schlüssel.

Analyse von Schlüsselkompromittierungen

Dieses PEP hat das minimale Sicherheitsmodell behandelt, die TUF-Rollen, die zur Unterstützung der kontinuierlichen Bereitstellung von Distributionen hinzugefügt werden sollten, und wie die Metadaten für jede Rolle generiert und signiert werden. Die folgenden Abschnitte erörtern, wie PyPI Repository-Metadaten audieren SOLLTE und welche Methoden PyPI zur Erkennung und Wiederherstellung von PyPI-Kompromittierungen verwenden kann.

Tabelle 4 fasst einige der Angriffe zusammen, die möglich sind, wenn eine Schwellenwertanzahl von privaten kryptografischen Schlüsseln (die zu beliebigen PyPI-Rollen gehören) kompromittiert wird. Die linkeste Spalte listet die Rollen (oder eine Kombination von Rollen) auf, die kompromittiert wurden, und die Spalten rechts davon zeigen, ob die kompromittierten Rollen die Clients anfällig für böswillige Updates, einen Freeze-Angriff oder Metadaten-Inkonsistenzangriffe machen. Beachten Sie, dass, wenn die timestamp-, snapshot- und bin-n-Rollen am selben Online-Ort gespeichert sind, eine Kompromittierung einer bedeutet, dass alle kompromittiert werden. Daher betrachtet die Tabelle diese Rollen zusammen. Eine Version dieser Tabelle, die diese Rollen getrennt betrachtet, ist in PEP 480 enthalten.

Rollenkompromittierung Böswillige Updates Freeze-Angriff Metadaten-Inkonsistenzangriffe
targets ODER bins KEINE Notwendigkeit für timestamp und snapshot zur Kooperation
timestamp UND snapshot UND bin-n JA, begrenzt durch die früheste Ablaufzeit der root-, targets- oder bins-Metadaten
Root JA

Tabelle 4: Mögliche Angriffe durch Kompromittierung bestimmter Kombinationen von Rollenschlüsseln. Im September 2013 wurde gezeigt, wie die damals neueste Version von pip anfällig für diese Angriffe war und wie TUF Benutzer davor schützen konnte [14].

Beachten Sie, dass die Kompromittierung von targets oder bins einem Angreifer nicht sofort ermöglicht, bösartige Updates zu liefern. Der Angreifer muss auch die timestamp- und snapshot-Rollen kompromittieren, die beide online sind und daher wahrscheinlicher kompromittiert werden. Dies bedeutet, dass man, um einen Angriff zu starten, nicht nur ein Man-in-the-Middle sein muss, sondern auch den timestamp-Schlüssel kompromittieren muss (oder die root-Schlüssel kompromittieren und einen neuen timestamp-Schlüssel signieren). Um einen anderen Angriff als einen Freeze-Angriff zu starten, muss man auch den snapshot-Schlüssel kompromittieren. In der Praxis empfiehlt dieses PEP, die snapshot-, timestamp- und bin-n-Schlüssel zusammen zu speichern oder sogar denselben Schlüssel für all diese Rollen zu verwenden. Aus diesem Grund muss der Angreifer nur diesen einen Server kompromittieren, um einen der oben genannten Angriffe durchzuführen. Beachten Sie, dass Clients immer noch vor der Kompromittierung von Nicht-Signatur-Infrastrukturen wie CDNs oder Spiegeln geschützt sind. Darüber hinaus erlaubt der Offline-root-Schlüssel dem Repository, sich von einem Angriff zu erholen, indem der Online-Schlüssel widerrufen wird.

Das maximale Sicherheitsmodell zeigt, wie TUF Online-Schlüsselkompromittierungen durch die Einführung zusätzlicher Rollen für die End-to-End-Signierung abmildert. Details zur Generierung von Entwicklerschlüsseln und zur Signierung von Upload-Distributionen finden Sie in PEP 480.

Im Falle einer Schlüsselkompromittierung

Eine Schlüsselkompromittierung bedeutet, dass ein Schwellenwert von Schlüsseln (die zu den Metadatenrollen auf PyPI gehören) sowie die PyPI-Infrastruktur kompromittiert und zum Signieren neuer Metadaten auf PyPI verwendet wurden.

Wenn ein Schwellenwert von Schlüsseln der timestamp-, snapshot-, targets-, bins- oder bin-n-Rollen kompromittiert wurde, MUSS PyPI die folgenden Schritte unternehmen:

  1. Die Schlüssel der timestamp-, snapshot- und targets-Rollen aus der root-Rolle widerrufen. Dies geschieht durch Ersetzen der kompromittierten timestamp-, snapshot- und targets-Schlüssel durch neu ausgestellte Schlüssel.
  2. Die bins-Schlüssel aus der targets-Rolle widerrufen, indem ihre Schlüssel durch neu ausgestellte Schlüssel ersetzt werden. Die neuen targets-Rollen-Metadaten signieren und die neuen Schlüssel verwerfen (da, wie bereits erläutert, dies die Sicherheit der targets-Metadaten erhöht).
  3. Alle Ziele der bin-n-Rollen SOLLTEN mit dem letzten bekannten guten konsistenten Snapshot verglichen werden, bei dem keine der timestamp-, snapshot-, bins- oder bin-n-Schlüssel bekanntermaßen kompromittiert waren. Hinzugefügte, aktualisierte oder gelöschte Ziele im kompromittierten konsistenten Snapshot, die nicht mit dem letzten bekannten guten konsistenten Snapshot übereinstimmen, KÖNNEN auf ihre vorherigen Versionen zurückgesetzt werden. Nach Sicherstellung der Integrität aller bin-n-Ziele sollten ihre Schlüssel in den bins-Metadaten erneuert werden.
  4. Die bins- und bin-n-Metadaten MÜSSEN ihre Versionsnummern inkrementieren, ihre Ablaufzeiten entsprechend verlängern und ihre Signaturen erneuern.
  5. Ein neuer zeitgestempelter konsistenter Snapshot MUSS ausgestellt werden.

Die Befolgung dieser Schritte würde alle diese Rollen präventiv schützen, auch wenn nur eine davon kompromittiert worden sein mag.

Wenn ein Schwellenwert von root-Schlüsseln kompromittiert wurde, MUSS PyPI die oben genannten Schritte durchführen und außerdem alle root-Schlüssel in der root-Rolle ersetzen.

Es wird auch EMPFOHLEN, dass PyPI Kompromittierungen ausreichend mit Sicherheitsbulletins dokumentiert. Diese Sicherheitsbulletins werden am informativsten sein, wenn Benutzer von pip-mit-TUF ein Projekt nicht installieren oder aktualisieren können, weil die Schlüssel für die timestamp-, snapshot- oder root-Rollen nicht mehr gültig sind. Sie könnten dann die PyPI-Website besuchen, um Sicherheitsbulletins zu konsultieren, die erklären, warum sie nicht mehr installieren oder aktualisieren können, und dann entsprechende Maßnahmen ergreifen. Wenn ein Schwellenwert von root-Schlüsseln aufgrund einer Kompromittierung nicht widerrufen wurde, dann können neue root-Metadaten sicher aktualisiert werden, da ein Schwellenwert von bestehenden root-Schlüsseln zum Signieren der Integrität der neuen root-Metadaten verwendet wird. TUF-Clients können die Integrität der neuen root-Metadaten mit einem Schwellenwert von zuvor bekannten root-Schlüsseln verifizieren. Dies wird der häufige Fall sein. Andernfalls, im schlimmsten Fall, in dem ein Schwellenwert von root-Schlüsseln aufgrund einer Kompromittierung widerrufen wurde, kann ein Endbenutzer wählen, neue root-Metadaten mit Out-of-Band-Mechanismen zu aktualisieren.

Überprüfung von Snapshots

Wenn eine bösartige Partei PyPI kompromittiert, kann sie beliebige Dateien mit jedem der Online-Schlüssel signieren. Die Rollen mit Offline-Schlüsseln (d.h. root, targets und bins) sind weiterhin geschützt. Um sicher aus einer Repository-Kompromittierung wiederherzustellen, sollten Snapshots auditiert werden, um sicherzustellen, dass Dateien nur auf vertrauenswürdige Versionen wiederhergestellt werden.

Wenn eine Repository-Kompromittierung erkannt wurde, muss die Integrität von drei Arten von Informationen validiert werden:

  1. Wenn die Online-Schlüssel des Repositorys kompromittiert wurden, können sie widerrufen werden, indem die targets-Rolle neue Metadaten delegiert, die auf einen neuen Schlüssel verweisen, signiert.
  2. Wenn die Rollenmetadaten im Repository geändert wurden, hätte dies Auswirkungen auf die Metadaten, die von Online-Schlüsseln signiert werden. Alle Rolleninformationen, die seit der letzten Periode erstellt wurden, sollten verworfen werden. Infolgedessen müssen Entwickler neuer Projekte ihre Projekte neu registrieren.
  3. Wenn die Zieldateien selbst manipuliert wurden, können sie anhand der gespeicherten Hash-Informationen für Zieldateien validiert werden, die zum Zeitpunkt der letzten Periode existierten.

Um Snapshots im Falle eines Kompromisses sicher wiederherstellen zu können, SOLLTE PyPI eine kleine Anzahl eigener Spiegelserver unterhalten, um PyPI-Snapshots nach einem bestimmten Zeitplan zu kopieren. Das Spiegelprotokoll kann für diesen Zweck sofort verwendet werden. Die Spiegelserver müssen gesichert und isoliert sein, sodass sie nur für das Spiegeln von PyPI zuständig sind. Die Spiegelserver können untereinander überprüft werden, um versehentliche oder böswillige Fehler zu erkennen.

Ein anderer Ansatz besteht darin, den kryptografischen Hash von snapshot periodisch zu generieren und zu twittern. Möglicherweise meldet sich ein Benutzer mit den tatsächlichen Metadaten und die Repository-Betreuer können den kryptografischen Hash der Metadatendatei verifizieren. Alternativ kann PyPI seine eigenen Versionen von snapshot periodisch archivieren, anstatt sich auf extern bereitgestellte Metadaten zu verlassen. In diesem Fall SOLLTE PyPI den kryptografischen Hash jeder Zieldatei im Repository nehmen und diese Daten auf einem Offline-Gerät speichern. Wenn sich ein Hash einer Zieldatei geändert hat, deutet dies auf einen Angriff hin.

Angriffe, die verschiedene Versionen von Metadaten ausliefern oder eine Version einer Distribution auf einer bestimmten Version einfrieren, können mit TUF durch Techniken wie implizite Schlüsselwiderrufung und Metadaten-Mismatch-Erkennung behandelt werden [2].

Verwaltung zukünftiger Änderungen am Update-Prozess

Wenn am Update-Prozess Änderungen vorgenommen werden, die zu Brüchen führen, sollte PyPI diese Änderungen implementieren, ohne bestehende Clients zu stören. Allgemeine Anleitungen dazu finden Sie in der laufenden Diskussion im TAP Repository.

Beachten Sie, dass die Änderungen an PyPI durch dieses PEP abwärtskompatibel sind. Der Speicherort von Zieldateien und einfachen Indizes wird in diesem PEP nicht geändert, sodass bestehende PyPI-Clients weiterhin Updates mit diesen Dateien durchführen können. Dieses PEP fügt der Fähigkeit von Clients hinzu, TUF-Metadaten zu verwenden, um die Sicherheit des Update-Prozesses zu verbessern.

Hash-Algorithmus-Übergangsplan

Wenn der für das Hashing von Ziel- und Metadatendateien verwendete Algorithmus anfällig wird, SOLLTE er durch einen stärkeren Hash-Algorithmus ersetzt werden.

Das TUF-Metadatenformat erlaubt es, Digests von verschiedenen Hash-Algorithmen nebeneinander aufzulisten, zusammen mit einer Algorithmus-ID, sodass Clients nahtlos zwischen Algorithmen wechseln können.

Sobald die Unterstützung für einen alten Algorithmus deaktiviert ist, können Clients, die den neuen Algorithmus nicht unterstützen, Pakete (einschließlich des Clients selbst) nur installieren oder aktualisieren, indem sie die TUF-Überprüfung deaktivieren. Um Clients den Übergang zu ermöglichen, ohne vorübergehend TUF-Sicherheitsgarantien zu verlieren, empfehlen wir das folgende Verfahren.

  1. Neuen Algorithmus in Warehouse implementieren.
  2. Bestehende, noch gültige TUF-Metadaten neu generieren, um Hashes mit beiden Algorithmen (alt und neu) einzuschließen. Alle neuen Metadaten ab sofort sollen beide Hash-Algorithmen auflisten. Beachten Sie, dass nur TUF-Metadaten, die Hash-Digests für Zieldateien oder andere Metadaten auflisten, erneuert werden müssen, nämlich bin-n, snapshot und timestamp. Daher sind nur Online-Schlüssel erforderlich, um erneuerten Metadaten zu signieren.
  3. Den Übergang auf stark sichtbaren Kanälen ankündigen, wie z. B. Packaging auf Python Discourse und die PyPI-Änderungen Mailingliste.
  4. Beliebten Clients wie pip und bandersnatch die Möglichkeit geben, den neuen Hash-Algorithmus zu übernehmen.
  5. Endbenutzern die Möglichkeit geben, ihre Clients zu aktualisieren.
  6. Großen Konsens von den PyPI-Betreuern erzielen, um den alten Hash-Algorithmus zu entfernen.
  7. Die Unterstützung für den alten Algorithmus in Warehouse entfernen und nur noch den neuen Algorithmus unterstützen.

Anhang A: Repository-Angriffe, die von TUF verhindert werden

  • Willkürliche Softwareinstallation: Ein Angreifer installiert alles, was er möchte, auf dem Client-System. Das heißt, ein Angreifer kann beliebige Dateien als Antwort auf Download-Anfragen bereitstellen, und die Dateien werden nicht als illegitim erkannt.
  • Rollback-Angriffe: Ein Angreifer präsentiert einem Software-Update-System Dateien, die älter sind als die, die der Client bereits gesehen hat. Dies führt dazu, dass der Client veraltete Dateien verwendet.
  • Angriffe mit unbegrenztem Einfrieren: Ein Angreifer präsentiert einem Software-Update-System weiterhin dieselben Dateien, die der Client bereits gesehen hat. Das Ergebnis ist, dass der Client nicht weiß, dass neue Dateien verfügbar sind.
  • Endlose Datenangriffe: Ein Angreifer antwortet auf eine Dateidownload-Anfrage mit einem endlosen Datenstrom, was dem Client schadet (z. B. eine Festplattenpartition wird voll oder der Speicher wird erschöpft).
  • Angriffe mit langsamer Abrufung: Ein Angreifer antwortet auf Clients mit einem sehr langsamen Datenstrom, der im Wesentlichen dazu führt, dass der Client den Update-Prozess nie fortsetzt.
  • Angriffe mit unnötigen Abhängigkeiten: Ein Angreifer teilt Clients mit, dass sie, um die gewünschte Software zu installieren, auch nicht verwandte Software installieren müssen. Diese nicht verwandte Software kann aus einer vertrauenswürdigen Quelle stammen, weist aber möglicherweise bekannte Schwachstellen auf, die vom Angreifer ausgenutzt werden können.
  • Mix-and-Match-Angriffe: Ein Angreifer präsentiert den Clients eine Ansicht eines Repositorys, die Dateien enthält, die zu keinem Zeitpunkt gleichzeitig im Repository vorhanden waren. Dies kann beispielsweise dazu führen, dass veraltete Versionen von Abhängigkeiten installiert werden.
  • Falsche Softwareinstallation: Ein Angreifer stellt einem Client eine vertrauenswürdige Datei zur Verfügung, die nicht die vom Client gewünschte ist.
  • Böswillige Spiegelserver verhindern Updates: Ein Angreifer, der die Kontrolle über einen Repository-Spiegelserver hat, kann verhindern, dass Benutzer Updates von anderen, guten Spiegelservern erhalten.
  • Anfälligkeit für Schlüsselkompromittierung: Ein Angreifer, der einen einzelnen Schlüssel oder weniger als eine bestimmte Anzahl von Schlüsseln kompromittieren kann, kann Clients kompromittieren. Dies schließt die Abhängigkeit von einem einzelnen Online-Schlüssel ein, z. B. nur durch SSL geschützt zu sein, oder einem einzelnen Offline-Schlüssel, da die meisten Software-Update-Systeme zur Signierung von Dateien verwendet werden.

Referenzen

Danksagungen

Dieses Material basiert auf Arbeiten, die von der National Science Foundation unter den Grants Nr. CNS-1345049 und CNS-0959138 unterstützt werden. Alle Meinungen, Ergebnisse und Schlussfolgerungen oder Empfehlungen, die in diesem Material ausgedrückt werden, stammen vom(n) Autor(en) und spiegeln nicht notwendigerweise die Ansichten der National Science Foundation wider.

Wir danken Alyssa Coghlan, Daniel Holth, Donald Stufft und der distutils-sig-Community im Allgemeinen dafür, dass sie uns geholfen haben, darüber nachzudenken, wie TUF nutzbar und effizient mit PyPI integriert werden kann.

Roger Dingledine, Sebastian Hahn, Nick Mathewson, Martin Peck und Justin Samuel halfen uns bei der Gestaltung von TUF aus seinem Vorgänger Thandy vom Tor-Projekt.

Wir würdigen die Bemühungen von Konstantin Andrianov, Geremy Condra, Zane Fisher, Justin Samuel, Tian Tian, Santiago Torres, John Ward und Yuyu Zheng bei der Entwicklung von TUF.

Vladimir Diaz, Monzur Muhammad, Sai Teja Peddinti, Sumana Harihareswara, Ee Durbin und Dustin Ingram halfen uns bei der Überprüfung dieses PEP.

Zane Fisher half uns bei der Überprüfung und Transkription dieses PEP.


Quelle: https://github.com/python/peps/blob/main/peps/pep-0458.rst

Zuletzt geändert: 2025-02-01 08:59:27 GMT