Wie schütze ich das Ökosystem meines Projekts?

Kaum ein wirkliches Projekt - sei es im Bereich von .NET, Angular, Node, Java oder anderen Sprachen - kommen heutzutage ohne externe Abhängigkeiten aus.

  • In .NET ist es NuGet
  • In Java ist es Maven oder Graven
  • In Python ist es pip oder conda
  • In Angular, Node etc ist es Yarn oder NPM
  • In PHP ist es vor allem Composer

Pakete können dabei verschiedenste Inhalte besitzen:

  • Statische Ressourcen
  • Assemblies mit entsprechenden Funktionalitäten für die Entwicklung
  • Dokumentationen
  • ...

Sie reichen also ein Entwicklungsprojekt vor allem mit Funktionalitäten an, die man nicht selst entwickeln muss oder will.

Warum überhaupt ein Paket Manager?

Früher waren vor allem SDKs sehr weit verbreitet - also Software Development Kits. Diese Kits musste man meist vom jeweiligen Hersteller manuell herunterladen und installieren, bevor man die notwendigen Abhängigkeiten nutzen konnte.
Diese musste man sogar nicht nur bei sich selbst installieren, sondern bei jedem Entwickler, der an einem jeweiligen Projekt mitarbeitet und sogar meist auch auf der Maschine, auf der auch die jeweilige Software später mal läuft.

Es war also ein gewisser Aufwand notwendig, dass man überhaupt gemeinsam an einem Projekt mit Abhängigkeiten arbeiten kann - und hinzu kommt auch noch, dass man die Abhängigkeiten überall synchron halten muss; was nicht selten in entsprechenden Runtime-Fehler endete.

Paket Manager lösen prinzipiell das Problem der lokalen Abhängigkeit: es gibt keine Verweise mehr auf irgendwelche lokalen Abhängigkeiten zu SDKs, sondern dem jeweiligen Projekt wird eine Abhängigkeit durch eine entsprechende Konfiguration mitgezeilt.

Bei NuGet erfolgte dies durch die packages.config wobei diese durch das neue Projekt-Format von .NET Core / .NET Standard in die jeweilige Projektdatei verlagert hat.

<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />

Dieser Eintrag ist nichts anderes als eine Information, welche extrnen Abhängigkeiten für die Entwicklung des Projekts benötigt werden - zur Entwicklung und zur Laufzeit. Da dieser Eintrag teil des Projekts ist, ist diese Abhängigkeit synchron auch für alle Entwickler nutzbar - die notwendige Installation des Pakets übernimmt dabei die Entwicklungsumgebung. Es muss (in der Regel) nichts mehr manuell installiert werden.

Vorteile von Paketmanagern

  • Automatische, Code-seitige Konfiguration von Abhängigkeiten (und auch deren Abhängigkeiten)
  • Kompatibilitätserkennung von Paketen zu Runtimes
  • Komplette Nachverfolgbarkeit von Abhängigkeiten
  • Vereinfachung des gesamten Entwicklungsprozess

Risiken des Paket-Ökosystems

Das Risiko ist prinzipiell nicht höher als bei anderen Mechanismen wie lokal installierte SDKS; sei es jetzt durch infizierte Pakete oder durch qualitativ schlechte Pakete - es macht es jedoch einfacher.

Auch wenn sich die meisten Entwickler heute an vor allem großen, beliebten und bekannten Paketen orientierten, hat jedes Paket mal klein angefangen - und jeden Tag kommen tausende neue Projekte als Pakete auf den entsprechenden Paket-Quellen zum Vorschein.

Die Möglichkeiten für schwarze Schafe sind also durchaus gegeben - und sie waren auch schon erfolgreich: in vermeintlichen Paketen war schädlicher Quellcode enthalten.

Ein weiteres prinzipielles Risiko ist, dass man ein Paket verwendet und dies plötzlich nicht mehr existiert. Genau dieser Fall hat vor wenigen Jahren zu einem riesigen Problem im größten Paketmanager der Welt (NPM mit fast 1 Mio Pakete) geführt: ein Entwickler hat sein Paket gelöscht, auf dem viele tausende andere Pakete aufgebaut waren - und mit einem auf den anderen Tag sind viele Entwicklungsprojekte zusammengebrochen, da die notwendige Abhängigkeit nicht mehr verfügbar war.

Mittlerweile ist es bei jedem fast Paketmanager so, dass Pakete nicht mehr gelöscht werden können - auch nicht mehr bei NPM; außer man verweist direkt zum Beispiel auf ein GitHub Repository und der Entwickler löscht sein Repository.

Golden Repositories sind keine Lösung

Die Idee von Golden Repositories ist :

Pakete, die verwendet werden, werden vorher geprüft und als Kopie in eine private Paket-Datenbank (zB das Dateisystem, eigener Paketserver) abgelegt

Vor zwei Wochen war ich auf einem IoT Security Konferenz eines der größten IT-Sicherheitsunternehmen in Europa und genau diese Art und Weise wurde als der "beste Weg" auch angepriesen - was mich etwas erschrocken hat.

Seit Jahren ist der allgemeine Konsent, dass Golden Repositories keine Lösung sind. So gut die Idee sein mag; sie funktioniert nicht und bringt am Ende mehr Risiko als Nutzen:

  • Durch die "Kopie" kann die Versionierung des Ursprungs nicht mehr getrackt werden, was dazu führt, dass Inhalte im Golden Repository meist veraltet sind
  • Verschiedene Entwicklerteams haben verschiedene Anforderungen in Sachen Securitiy und Risk Management - ein gemeinsames Golden Repository kann dies niemals erfüllen
  • Das Management eines Golden Repository kostet enorm viel Zeit, da Entwickler meist jedoch nicht wirklich Zeit haben führt dies dazu, dass Entwickler das Repository oder Policies, wie die Prüfung, umgehen
  • Golden Repository mögen zwar die Policy haben, dass ein Paket geprüft wird, bevor es hinzugefügt wird - dies schützt aber nicht vor Risiken, die erst später entdeckt werden
  • Das Golden Repository ist nur so sicher, wie der Prozess es zulässt: menschlicher Wille und menschliche Fehler können Prozesse schnell umgehen

Die Alternativen: Complience Management Systeme

Die derzeit einzig wirklich sinnvolle Lösung Abhängigkeiten aller Art - und dazu gehören nicht nur die Pakete selbst sondern auch die Lizenzen etc - sind sogenannte Complience Management Systeme.

Diese Systeme überwachen Open Source Projekte, Pakete, Container, Applikationen und tausende von Abhängigkeiten und überprüfen diese nach Schwachstellen, Risiken, Viren, Lizenzproblemen - jedoch keine Golden Repositories, auf die die Systeme keinen Zugriff haben.

Die Funktionsweise der bekanntesten Systeme (WhiteSource, Snyk, Veracode) sind dabei relativ ähnlich:

  • Quellcode und Pakete werden von den Systemen kontinuierlich analysiert
  • Schwachstellen werden in Datenbanken getrackt
  • Entsprechende System-Tools informieren während der Entwicklung und auch während des Betriebs

Beispiel WhiteSource, Azure DevOps und .NET

WhiteSource bietet sowohl kostenpflichtige wie auch mit WhiteSource Bolt kostenlose Möglichkeiten seine Entwicklungsumgebung und deren Abhängigkeiten zu überwachen.

Dabei wird WhiteSource sehr einfach in den DevOps-Prozess integriert. Bei jedem Build der Software - egal ob es sich dabei selbst um ein Paket, ein Container oder eine Anwendung handelt - analysiert ein WhiteSource-Task die Abhängigkeiten und vergleicht diese sowohl mit der WhiteSource-Datenbank wie auch mit öffentlichen Datenbanken wie NVD und verschiedenen Issue Trackern.

steps:

- task: WhiteSource [email protected]
  displayName: "Whitesource Analysis"
  inputs:
    cwd: ${{ parameters.sourceDirectory }}

Innerhalb von wenigen Sekunden erhält man dabei - direkt in Azure DevOps integriert - einen Report mit potentiellen Risiken.

  • Lizenzprobleme
  • Alerts und Warnungen zu Security Vulnerabilities
  • Überwachung von veralteten Paketen und/oder Containern und anderen Abhängigkeiten

WhiteSource

Vorteile von Complience Management Systemen

  • Öffentliche Quellen werden dauerhaft und kontinuierlich überwacht
  • Es wird die gesamte Abhängigkeits-Kette überwacht
  • Informationen zu Risiken erfolgen in Echtzeit bereits zur Entwicklungszeit
  • Bei Risiko-Verletzung kann aktiv in den DevOps-Prozess eingegriffen und so im Sinne von Fail-Fast Probleme minimiert werden
  • Die Risiken können pro Projekt im Rahmen des DevOps-Prozesses verwaltet werden

Fazit

Es gibt genug Möglichkeiten - auch kostenlos - seine Projekte vor Risiken durch Überwachung schützen zu können, ohne sich eigene Risiken wie Golden Repositories zu bauen, die nur das Gefühl von Schutz vermitteln.

Ich bzw. wir verwenden in jedem Projekt mittlerweile die Möglichkeiten der verschiedenen Complience Management Systemen um das Risiko zu minimieren. Ein 100%tiger Schutz ist - wie in den meisten Lebensbereichen - leider jedoch auch hier nicht möglich; aber wir kommen mit Complience Management Systemen schon nahe ran.