Bewährte Methoden für eine sichere Softwarelieferkette
Open Source ist überall. Man findet Open Source in vielen proprietären Codebasen und Communityprojekten. Organisationen und Einzelpersonen stellen sich heutzutage nicht die Frage, ob Software auf Open Source basiert oder nicht, sondern welcher Open-Source-Code verwendet werden sollte und in welchem Umfang.
Wenn Sie Ihre Lieferkette nicht kennen, kann ein Sicherheitsrisiko in einer Ihrer Abhängigkeiten in der vorgelagerten Lieferkette verheerend sein. Das führt dazu, dass Sie und Ihre Kunden für eine potenzielle Kompromittierung anfällig werden. In diesem Dokument wird ausführlicher darauf eingegangen, was mit dem Begriff „Softwarelieferkette“ gemeint ist, warum dieser von Bedeutung ist und wie Sie dazu beitragen können, die Lieferkette Ihres Projekts mit Best Practices zu schützen.
Abhängigkeiten
Der Begriff „Softwarelieferkette“ umfasst alle Elemente, die in Ihrer Software einfließen, und auch woher diese stammen. Dabei handelt es sich um die Abhängigkeiten und Eigenschaften Ihrer Abhängigkeiten, von denen Ihre Softwarelieferkette abhängt. Als Abhängigkeit werden alle Elemente bezeichnet, die Ihre Software benötigt, um ausgeführt werden zu können. Dabei kann es sich um Codeblöcke, Binärdateien oder andere Komponenten handeln und woher diese stammen, z. B. von einem Repository oder Paket-Manager.
Zur Lieferkette gehören außerdem die Person, die den Code geschrieben hat, der Zeitpunkt der Bereitstellung, die Art der Überprüfung auf Sicherheitsprobleme, bekannte Sicherheitsrisiken, unterstützte Versionen, Lizenzinformationen und alle sonstigen Prozesse.
Ihre Lieferkette umfasst auch andere Teile Ihres Stapels als nur die einzelne Anwendung, zum Beispiel Ihre Build- und Paketskripts oder die Software, die die Infrastruktur ausführt, auf der Ihre Anwendung basiert.
Sicherheitsrisiken
Heute sind Softwareabhängigkeiten in allen Bereichen zu finden. Es kommt häufig vor, dass Softwarehersteller Hunderte von Open-Source-Abhängigkeiten für Funktionalitäten verwenden, damit sie diese nicht selbst schreiben mussten. Dies kann bedeuten, dass der größte Teil Ihrer Anwendung aus Code besteht, den Sie nicht erstellt haben.
Da Sie Ihre Abhängigkeiten von Drittanbietern oder Open-Source-Abhängigkeiten vermutlich nicht so streng kontrollieren können wie den Code, den Sie selbst schreiben, können diese mögliche Sicherheitsrisiken in Ihrer Lieferkette hervorrufen.
Wenn Abhängigkeiten ein Sicherheitsrisiko aufweisen, ist die Wahrscheinlichkeit hoch, dass auch ein Sicherheitsrisiko bei Ihnen auftritt. Dies kann frustrierend sein, da sich eine Ihrer Abhängigkeiten unter Umständen ändert, ohne dass Sie dies überhaupt bemerken. Selbst wenn ein in einer Abhängigkeit vorhandenes Sicherheitsrisiko derzeit noch nicht ausnutzbar ist, kann es in der Zukunft so weit kommen.
Die Tatsache, dass Sie die Arbeit Tausender Open-Source-Entwickler und Bibliotheksersteller nutzen können, bedeutet auch, dass Tausende fremder Entwickler effektiv an Ihrem Produktionscode mitarbeiten können. Ihr Produkt wird durch Ihre Softwarelieferkette durch nicht gepatchte Sicherheitsrisiken, arglose Fehler oder sogar böswillige Angriffe auf Abhängigkeiten beeinträchtigt.
Kompromittierungen in der Lieferkette
Die gängige Definition einer Lieferkette stammt aus der Fertigungsindustrie und bezeichnet die Prozesskette von der Herstellung bis zum Vertrieb. Diese umfasst die Planung, die Materialbeschaffung, den Herstellungsprozess und den Verkauf. Eine Softwarelieferkette ist ähnlich, nur dass anstelle der Materialien Code genutzt wird. Die Fertigung ist hier die Entwicklung. Anstatt das Erz aus der Erde zu holen, wird Code von Anbietern bezogen (kommerziell oder Open Source), und in der Regel stammt Open-Source-Code aus Repositorys. Das Hinzufügen von Code aus einem Repository bedeutet, dass Ihr Produkt von diesem Code abhängig ist.
Ein Angriff auf die Softwarelieferkette liegt beispielsweise vor, wenn bösartiger Code absichtlich zu einer Abhängigkeit hinzugefügt wird, wobei der Code mithilfe der Lieferkette dieser Abhängigkeit an die Opfer verteilt wird. Angriffe auf Lieferketten sind ernst zu nehmen. Es gibt viele Methoden zum Angriff auf eine Lieferkette, zum Beispiel das direkte Einfügen von schädlichem Code als neuer Mitwirkender, das Übernehmen des Kontos eines Mitwirkenden, ohne dass andere dies bemerken, oder sogar das Kompromittieren eines Signaturschlüssels, um Software zu verteilen, die nicht offiziell Teil der Abhängigkeit ist.
Ein Angriff auf eine Softwarelieferkette ist an und für sich selten das Endziel, sondern eine erste gute Gelegenheit für einen Angreifer, Schadsoftware einzuschleusen oder eine Hintertür für zukünftigen Zugriff bereitzustellen.
Nicht gepatchte Software
Die Verwendung von Open Source hat beträchtliche Ausmaße erreicht und wird wahrscheinlich nicht so bald wieder abnehmen. Da wir die Verwendung von Open-Source-Software nicht unterbinden, stellt die nicht gepatchte Software die größte Bedrohung für die Sicherheit von Lieferketten dar. Wie können Sie ausgehend von dieser Tatsache mit dem Risiko umgehen, dass eine Abhängigkeit Ihres Projekts ein Sicherheitsrisiko aufweist?
- Kenntnis Ihrer Umgebung: Dies erfordert die Ermittlung Ihrer Abhängigkeiten und der transitiven Abhängigkeiten, um die Risiken dieser Abhängigkeiten wie Sicherheitsrisiken oder Lizenzierungseinschränkungen zu verstehen.
- Verwalten Ihrer Abhängigkeiten: Wenn ein neues Sicherheitsrisiko erkannt wird, müssen Sie feststellen, ob Sie betroffen sind. Wenn dies der Fall ist, führen Sie ein Update auf die aktuelle Version und das neueste verfügbare Sicherheitspatch durch. Dies ist besonders wichtig, um Änderungen zu prüfen, die neue Abhängigkeiten einführen, oder ältere Abhängigkeiten in regelmäßigen Abständen zu überprüfen.
- Überwachen der Lieferkette: Die Überwachung erfolgt durch Überprüfung der Kontrollmechanismen, die Ihnen zum Verwalten Ihrer Abhängigkeiten zur Verfügung stehen. Auf diese Weise können Sie restriktivere Bedingungen für Ihre Abhängigkeiten erzwingen.
Nachfolgend werden verschiedene Tools und Techniken behandelt, die von NuGet und GitHub bereitstellt werden und die Sie sofort nutzen können, um potenzielle Risiken in Ihrem Projekt zu beheben.
Wissen, was sich in Ihrer Umgebung befindet
Pakete mit bekannten Sicherheitsrisiken
📦 Paketnutzer | 📦🖊 Paketersteller
.NET 8 und Visual Studio 17.8 haben NuGetAudit hinzugefügt, das während der Wiederherstellung vor direkten Paketen mit bekannten Sicherheitslücken warnt. NET 9 und Visual Studio 17.12 haben den Standard geändert, um auch vor transitiven Paketen zu warnen.
NuGetAudit erfordert eine Quelle, die eine Datenbank für bekannte Schwachstellen bereitstellt. Wenn Sie also nuget.org nicht als Paketquelle verwenden, sollten Sie es als Audit-Quelle hinzufügen.
Zu dem Zeitpunkt, an dem NuGet Sie warnt, ist die Sicherheitslücke bereits öffentlich bekannt. Angreifer können diese öffentliche Offenlegung nutzen, um Angriffe auf Ziele zu entwickeln, die ihre Anwendungen nicht gepatcht haben. Wenn Sie also eine Warnung erhalten, dass ein Paket, das Ihr Projekt verwendet, eine bekannte Sicherheitslücke aufweist, sollten Sie schnell handeln.
NuGet-Abhängigkeitsdiagramm
📦 Paketnutzer
Sie können Ihre NuGet-Abhängigkeiten in Ihrem Projekt anzeigen, indem Sie direkt die entsprechende Projektdatei öffnen.
Diese ist in der Regel an zwei Stellen vorhanden:
packages.config
– im Projektstamm<PackageReference>
– in der Projektdatei
Je nachdem, welche Methode Sie zum Verwalten Ihrer NuGet-Abhängigkeiten verwenden, können Sie auch Visual Studio verwenden, um Ihre Abhängigkeiten direkt im Projektmappen-Explorer oder im NuGet-Paket-Manager anzuzeigen.
In CLI-Umgebungen können Sie den dotnet list package
-Befehl verwenden, um Ihr Projekt oder die Abhängigkeiten der Projektmappe aufzulisten.
Sie können den dotnet nuget why
-Befehl auch verwenden, um zu verstehen, warum transitive Pakete (d. h. Pakete, die nicht direkt von Ihrem Projekt referenziert werden) in den Paketgraphen Ihres Projekts aufgenommen werden.
Weitere Informationen zum Verwalten von NuGet-Abhängigkeiten finden Sie in der folgenden Dokumentation.
GitHub-Abhängigkeitsdiagramm
📦 Paketnutzer | 📦🖊 Paketersteller
Sie können das Abhängigkeitsdiagramm von GitHub verwenden, um die Pakete, von denen Ihr Projekt abhängt, und die von ihm abhängigen Repositorys anzuzeigen. Dies kann Ihnen dabei helfen, erkannte Sicherheitsrisiken in den Abhängigkeiten anzuzeigen.
Weitere Informationen zu Repositoryabhängigkeiten von GitHub finden Sie in der folgenden Dokumentation.
Abhängigkeitsversionen
📦 Paketnutzer | 📦🖊 Paketersteller
Um eine sichere Lieferkette von Abhängigkeiten sicherzustellen, sollten Sie darauf achten, dass alle Ihre Abhängigkeiten und Tools regelmäßig auf die neueste stabile Version aktualisiert werden, da diese häufig die neuesten Funktionen und Sicherheitspatches für bekannte Schwachstellen enthält. Ihre Abhängigkeiten können Code, von dem Sie abhängig sind, von Ihnen verwendete Binärdateien, von Ihnen verwendete Tools und andere Komponenten enthalten. Dies kann enthalten:
Verwalten Ihrer Abhängigkeiten
Veraltete und anfällige NuGet-Abhängigkeiten
📦 Paketnutzer | 📦🖊 Paketersteller
Sie können die dotnet CLI verwenden, um alle bekannten veralteten oder anfälligen Abhängigkeiten aufzulisten, die sich möglicherweise in Ihrem Projekt oder in der Projektmappe befinden.
Sie können den Befehl dotnet list package --deprecated
oder dotnet list package --vulnerable
verwenden, um eine Liste bekannter veralteter Elemente oder Sicherheitsrisiken bereitzustellen.
NuGetAudit kann Sie vor bekannten anfälligen Abhängigkeiten warnen und ist standardmäßig aktiviert, wenn eine Quelle eine Datenbank mit Verwundbarkeiten bereitstellt.
Anfällige GitHub-Abhängigkeiten
📦 Paketnutzer | 📦🖊 Paketersteller
Wenn Ihr Projekt auf GitHub gehostet wird, können Sie die GitHub-Sicherheit nutzen, um Sicherheitsrisiken und Fehler in Ihrem Projekt zu finden. Dependabot behebt diese Fehler anschließend, indem ein Pull Request für Ihre Codebasis eröffnet wird.
Ein Ziel der „Shift Left“-Bewegung (Linksverschiebung) ist das Abfangen anfälliger Abhängigkeiten vor deren Einführung. Wenn Sie Informationen zu Ihren Abhängigkeiten wie die Lizenz, transitive Abhängigkeiten und das Alter der Abhängigkeiten haben, können Sie genau das tun.
Weitere Informationen zu Dependabot-Warnungen und -Sicherheitsupdates finden Sie in der folgenden Dokumentation.
NuGet-Feeds
📦 Paketnutzer
Nutzen Sie Paketquellen, denen Sie vertrauen. Wenn Sie mehrere öffentliche und private NuGet-Quellfeeds verwenden, kann ein Paket aus allen Feeds heruntergeladen werden. Sie sollten wissen, aus welchen Feeds Ihr Paket stammt, um sicherzustellen, dass Ihr Build vorhersagbar und sicher vor bekannten Angriffen wie einer Dependency Confusion (Abhängigkeitsverwechslung) ist. Sie können einen einzelnen Feed oder privaten Feed mit Upstreamingfunktionen für den Schutz verwenden.
Weitere Informationen zum Schützen Ihrer Paketfeeds finden Sie unter 3 Möglichkeiten zur Risikominderung mit privaten Paketfeeds.
Wenn Sie einen privaten Feed verwenden, lesen Sie die bewährten Sicherheitspraktiken für die Verwaltung von Anmeldeinformationen.
Clientvertrauensrichtlinien
📦 Paketnutzer
Es gibt Richtlinien, die Sie aktivieren können und die erfordern, dass Ihre verwendeten Pakete signiert sind. So können Sie einem Paket vertrauen, sofern es vom Ersteller signiert ist oder sich im Besitz eines bestimmten Benutzers oder Kontos ist, dessen Repository von NuGet.org signiert wurde.
Informationen zum Konfigurieren von Clientvertrauensrichtlinien finden Sie in der folgenden Dokumentation.
Sperrdateien
📦 Paketnutzer
Sperrdateien speichern den Hash des Paketinhalts. Wenn der Inhaltshash eines Pakets, das Sie installieren möchten, mit der Sperrdatei übereinstimmt, wird die Wiederholbarkeit des Pakets sichergestellt.
Informationen zum Aktivieren von Sperrdateien finden Sie in der folgenden Dokumentation.
Paketquellenzuordnung
📦 Paketnutzer
Mithilfe der Paketquellenzuordnung können Sie in Ihrer Datei „nuget.config“ zentral deklarieren, aus welcher Quelle die einzelnen Pakete in Ihrer Projektmappe wiederhergestellt werden sollen.
Informationen zum Aktivieren der Paketquellenzuordnung finden Sie in der folgenden Dokumentation.
Sichere Computer
Directory-Berechtigungen
📦 Paketnutzer
Unter Windows und Mac sowie bei einigen Linux-Verteilungen sind die Basisverzeichnisse der Benutzerkonten standardmäßig privat. Einige Linux-Verteilungen machen Benutzerverzeichnisse jedoch standardmäßig für andere Konten auf demselben Computer lesbar. Darüber hinaus gibt es mehrere Konfigurationsoptionen, um den globalen NuGet-Paketordner und den HTTP-Cache an andere Orte als die Standardspeicherorte umzuleiten. Lösungen, Projekte und Repositorys können auch außerhalb des Basisverzeichnisses des Benutzers erstellt werden.
Wenn Sie Pakete verwenden, die sich nicht auf nuget.org befinden, und ein anderes Konto auf dem Computer die globalen NuGet-Pakete, die HTTP-Cache-Verzeichnisse oder das Build-Output-Verzeichnis des Projekts lesen kann, werden diese Pakete möglicherweise Personen zugänglich gemacht, die keinen Zugriff auf diese Pakete haben sollten.
Unter Linux ändert dotnet nuget update source
die Berechtigungen für die Datei nuget.config so, dass sie nur vom Besitzer der Datei gelesen werden kann.
Wenn Sie die Datei nuget.config jedoch auf andere Weise bearbeiten und die Datei sich an einem Ort befindet, an dem andere Konten die Datei lesen können, kann es zur Offenlegung von Informationen über die Paketquellen-URL oder die Paketquellen-Anmeldedaten kommen.
Sie sollten sicherstellen, dass eine nuget.config-Datei nicht von anderen Benutzern desselben Computers gelesen werden kann.
Lösungen im Downloadverzeichnis
📦 Paketnutzer
Besondere Vorsicht ist geboten, wenn Sie an Lösungen oder Projekten in Ihrem Download-Verzeichnis arbeiten. NuGet sammelt Einstellungen aus mehreren Konfigurationsdateien, und MSBuild importiert typischerweise Directory.Build.props, Directory.NuGet.props, Directory.Build.targets und möglicherweise andere Dateien aus jedem übergeordneten Verzeichnis bis hin zum Stammverzeichnis des Dateisystems.
Der Downloads-Ordner birgt ein zusätzliches Risiko, da er in der Regel der Standardspeicherort ist, an dem Webbrowser Dateien aus dem Internet herunterladen.
Build-Agents
📦 Paketnutzer
Build-Agenten (CI-Agenten), die nicht nach jedem Build auf einen Anfangszustand zurückgesetzt werden, bergen mehrere Risiken, die berücksichtigt werden müssen.
Um mehr über sichere Methoden zur Verwaltung von Anmeldedaten zu erfahren, lesen Sie die Dokumentation zum Konsumieren von Paketen aus authentifizierten Feeds.
Informationen zum Ändern der Verzeichnisse, in denen NuGet Daten speichert, finden Sie in den Dokumenten zur Verwaltung der globalen Pakete, des Cache und der Temp-Ordner. Diese Verzeichnisse sollten auf ein Verzeichnis konfiguriert werden, das der CI-Agent nach jedem Build bereinigt.
Beachten Sie, dass alle Pakete, die von Ihrem Projekt verwendet werden, möglicherweise im Build-Ausgabeverzeichnis Ihres Projekts verbleiben. Wenn Ihr Projekt Pakete aus authentifizierten Quellen verwendet, könnten andere Benutzer desselben CI-Agenten unbefugten Zugriff auf die Paket-Assemblies erhalten. Daher sollten Sie auch ihr Repository am Ende des Builds bereinigen, auch wenn der Build fehlschlägt oder abgebrochen wird.
Überwachen der Lieferkette
Geheime Überprüfung in GitHub
📦🖊 Paketersteller
GitHub durchsucht Repositorys nach NuGet-API-Schlüsseln, um betrügerische Fälle von Geheimnisnutzung zu verhindern, die versehentlich committet wurden.
Weitere Informationen zur Geheimnisüberprüfung finden Sie in den Infos zur Geheimnisüberprüfung.
Erstellen der Paketsignierung
📦🖊 Paketersteller
Die Erstellung von Signierungen ermöglicht einem Paketersteller, ein Paket mit seiner Identität zu versehen, sodass ein Kunde nachverfolgen kann, ob es von diesem Ersteller stammt. Sie werden so vor Inhaltsmanipulation geschützt. Zudem fungiert diese Methode als „Single Source of Truth“(einziger Punkt der Wahrheit) bezüglich des Ursprungs und der Echtheit des Pakets. In Kombination mit Clientvertrauensrichtlinien können Sie so überprüfen, ob ein Paket von einem bestimmten Ersteller stammt.
Informationen zum Signieren eines Pakets als Ersteller finden Sie unter Signieren eines Pakets.
Reproduzierbare Builds
📦🖊 Paketersteller
Reproduzierbare Builds erstellen Binärdateien, die bei jeder Erstellung von Byte für Byte identisch sind, und enthalten Quellcodelinks und Compilermetadaten, die es Paketbenutzer*innen ermöglichen, die Binärdatei direkt neu zu erstellen und zu überprüfen, ob die Buildumgebung nicht kompromittiert wurde.
Weitere Informationen zu reproduzierbaren Builds finden Sie unter Erstellen von Paketen mit SourceLink und in der Spezifikation Validierung reproduzierbarer Builds.
Zweistufige Authentifizierung
📦🖊 Paketersteller
Jedes Konto auf nuget.org hat 2FA aktiviert. Dadurch wird eine zusätzliche Sicherheitsebene hinzugefügt, wenn Sie sich bei Ihrem GitHub-Konto oder Ihrem NuGet.org-Konto anmelden.
Reservierung für Paket-ID-Präfixe
📦🖊 Paketersteller
Wenn Sie die Identität Ihrer Pakete schützen möchten, können Sie ein Paket-ID-Präfix mit Ihrem Namespace reservieren, um dem Paket einen Besitzer zuzuordnen. Voraussetzung dafür ist, dass das Paket-ID-Präfix ordnungsgemäß die festgelegten Kriterien erfüllt.
Informationen zum Reservieren von ID-Präfixen finden Sie unter Reservierung von Paket-ID-Präfix.
Einstellen und Aufheben der Auflistung eines anfälligen Pakets
📦🖊 Paketersteller
Wenn Sie ein Sicherheitsrisiko in einem von Ihnen erstellten Paket erkannt haben, sollten Sie das Paket zum Schutz des .NET-Paketökosystems einstellen und die Auflistung dafür aufheben, sodass Benutzer, die nach Paketen suchen, es nicht mehr finden können. Wenn Sie ein Paket nutzen, das veraltet und nicht aufgelistet ist, sollten Sie es unbedingt außer Betrieb nehmen.
In der folgenden Dokumentation unter Als veraltet gekennzeichnete Pakete und Aufheben der Auflistung eines Pakets erfahren Sie, wie Sie ein Paket als veraltetet markieren und aus einer Auflistung entfernen.
Ziehen Sie auch in Erwägung, das bekannte Problem an die GitHub Advisories-Datenbank zu melden.
Zusammenfassung
Ihre Softwarelieferkette besteht aus allen Elementen, die in Ihren Code einfließen und sich auf diesen auswirken. Obwohl Kompromittierungen in der Lieferkette ein aktuelles Thema sind und immer öfter auftreten, sind sie noch immer selten. Es hat also höchste Priorität, Ihre Lieferkette zu schützen, indem Sie sich Ihre Abhängigkeiten bewusst machen und diese verwalten sowie Ihre Lieferkette überwachen.
Sie haben unterschiedliche Methoden kennengelernt, die von NuGet und GitHub bereitgestellt werden, mit denen Sie noch heute Ihre Einblicke, die Verwaltung und die Überwachung Ihrer Lieferkette optimieren können.
Weitere Informationen zum Schützen der weltweit eingesetzten Software finden Sie im Sicherheitsbericht von „The State of the Octoverse 2020“.