OWASP Top Ten und Analyse der Softwarezusammensetzung (SCA)

OWASP Top Ten und Analyse der Softwarezusammensetzung (SCA)

Die OWASP Top Ten 2017-Kategorie A9 (die in OWASP Top Ten 2021 zu A6 wurde) ist der Verwendung von Komponenten mit bekannten Schwachstellen gewidmet. Um diese Kategorie in PVS-Studio abzudecken, müssen Entwickler den Analysator in eine vollständige SCA-Lösung verwandeln. Wie sucht der Analysator nach Schwachstellen in den verwendeten Komponenten? Was ist SCA? Versuchen wir, die Antworten in diesem Artikel zu finden!

Einer der vorrangigen Bereiche für die Entwicklung von PVS-Studio ist die Abdeckung von Kategorien aus den OWASP Top Ten 2017 im C#-Analyzer. Auch die Top Ten 2021 wollen wir zukünftig abdecken. Am ungewöhnlichsten ist für uns die Kategorie A9:2017 – Using Components with Known Vulnerabilities. Diese Kategorie hat in der vorläufigen Version von OWASP 2021 die Position A6. Die Regelimplementierung für diese Kategorie ist eine wichtige Aufgabe für unseren Analysator. Es erlaubt uns, PVS-Studio als ein SCA-Tool (Software Composition Analysis) zu klassifizieren. Welchen Umsetzungsansatz wählen wir? Finden wir es heraus!

Verwendung von Komponenten mit bekannten Schwachstellen

Die Bedrohungskategorie A9 (in der vorläufigen Version von OWASP 2021 wurde sie zu A6) ist der Verwendung von Komponenten mit bekannten Schwachstellen gewidmet. Dies sind die Komponenten, die die entsprechenden Einträge in der CVE-Datenbank haben. CVE (Common Vulnerabilities and Exposures) ist eine Datenbank mit Aufzeichnungen über reale Schwachstellen in Software, Hardware, Dienstkomponenten usw.

A9 ist aus Sicht der Abdeckung in PVS-Studio ziemlich untypisch. Das liegt daran, dass die vorhandene Analyserarchitektur darauf ausgelegt ist, im Code selbst nach Fehlern zu suchen. Die Architektur verwendet Syntaxbäume, semantische Modelle, verschiedene Technologien wie Datenflussanalyse und andere. Diese Technologien waren im Allgemeinen ausreichend, um Diagnoseregeln zu implementieren, die bestimmte Kategorien aus den OWASP Top Ten 2017 abdecken würden.

Beispielsweise haben wir auf der Grundlage des bestehenden Datenflussmechanismus eine Taint-Analyse und verschiedene zugehörige Diagnoseregeln implementiert:

  • V5608 sucht nach SQL-Injection;
  • V5609 sucht nach Path Traversal/Directory Traversal;
  • V5610 sucht nach potenziellen XSS-Schwachstellen;
  • und andere.

Jede dieser Regeln sucht nach potenziellen Schwachstellen im Code und arbeitet, indem sie einen Syntaxbaum durchläuft. Gleichzeitig entsprechen sie einer oder mehreren Kategorien der OWASP Top Ten 2017. Die vollständige Liste der Korrespondenzen finden Sie hier.

Ganz anders ist die Situation bei A9. Aus Sicht von C#-Projekten ist die Regelimplementierung für A9 eine Überprüfung aller Projektabhängigkeitsbibliotheken für CVE. Mit anderen Worten, wir müssen für jede Abhängigkeit prüfen, ob es einen entsprechenden Eintrag in der CVE-Datenbank gibt.

Diese Aufgabe geht weit über das übliche Traversieren von Syntaxbäumen und das Studium der Codesemantik hinaus. Wir sind jedoch entschlossen, diese Kategorie abzudecken. Außerdem ist es sehr wichtig, dass die Implementierung der A9-Regel es PVS-Studio ermöglichen würde, den Analysator als SCA-Lösung zu positionieren.

Analyse der Softwarezusammensetzung

Im Allgemeinen sind SCA-Tools darauf ausgelegt, das Projekt auf problematische Abhängigkeiten zu prüfen.

Wenn ein Projekt beispielsweise von einer Open-Source-Bibliothek abhängt, ist es äußerst wichtig, die Lizenz zu berücksichtigen, unter der diese Bibliothek vertrieben wird. Verstöße gegen die Nutzungsbedingungen können dem Unternehmen großen Schaden zufügen.

Ein weiteres mögliches Problem ist das Vorhandensein von Schwachstellen in der Bibliothek. Im Zusammenhang mit SCA sprechen wir über bekannte Schwachstellen – CVE. Es ist fast unmöglich, die Verwendung einer Abhängigkeit zu bestimmen, die eine nicht aufgezeichnete Schwachstelle enthält :) Es ist nicht schwer zu erraten, dass wir ein Produkt für verschiedene Angriffe anfällig machen können, wenn wir eine Bibliothek mit einer (öffentlich bekannten) Schwachstelle verwenden.

Außerdem ist die Verwendung von Bibliotheken, deren Wartung eingestellt wurde, ein gefährlicher Ansatz. Möglicherweise enthalten diese Abhängigkeiten auch Schwachstellen. Entwickler wissen jedoch höchstwahrscheinlich nichts davon. Das Beheben solcher Schwachstellen kommt nicht in Frage – das wird niemand tun.

SCA und PVS-Studio

Wir kommen allmählich zur Hauptfrage – wie implementiert man die SCA-Funktionalität? Zunächst müssen wir sagen, dass wir diese Funktionen im Rahmen der Kategorie A9:2017 (Using Components with Known Vulnerabilities) entwickeln werden. Daher suchen wir zunächst nach Abhängigkeiten mit bekannten Schwachstellen. Der PVS-Studio-Analyzer verfügt jedoch bereits über Diagnoseregeln, die Entwickler vor Copyleft-Lizenzen warnen:

  • V1042 für C++;
  • V3144 für C#;
  • V6071 für Java.

Es ist möglich, dass wir im Laufe der Zeit weitere SCA-Funktionen implementieren.

Das Erkennen von Komponenten mit bekannten Schwachstellen besteht aus zwei Teilen. Der erste Schritt besteht darin, alle (sowohl direkten als auch transitiven) Projektabhängigkeiten zu erhalten und dann nach den passenden CVEs zu suchen. Der erste Teil dieses Plans scheint einfach. Der zweite Teil ist jedoch schwieriger.

Im Moment planen wir, die angegebene Funktionalität für den C#-Analyzer zu implementieren. Es ist einfach, die Liste der Abhängigkeiten für ein C#-Projekt abzurufen. Roslyn hilft uns sehr – unser Analysator baut auf seiner Basis auf. Genauer gesagt, der Hauptfaktor ist die Verwendung derselben Build-Plattform (MSBuild) und eines Compilers für alle C#-Projekte. Gleichzeitig ist Roslyn eng mit MSBuild verwandt. Dies macht das Abrufen der Abhängigkeitsliste trivial.

Da das Ökosystem von C++ und Java viel vielfältiger ist, wird es schwieriger, die Liste der Abhängigkeiten zu erhalten. Das machen wir ein andermal :).

Nun, wir haben die Abhängigkeiten aus dem Projekt. Wie können wir verstehen, welche von ihnen Schwachstellen aufweisen? Außerdem müssen wir bedenken, dass die Schwachstelle möglicherweise nur für bestimmte Bibliotheksversionen relevant ist. Offensichtlich brauchen wir eine Art Datenbank, in der die Abhängigkeiten, Versionen und die entsprechenden CVEs gespeichert werden.

Die Hauptfrage der Implementierung:Wie kann man eine Datenbank finden (oder vielleicht erstellen), die es uns ermöglicht, die verfügbaren Informationen über Projektabhängigkeiten mit bestimmten CVE zu vergleichen? Die Antwort auf diese Frage hängt von den verwendeten Tools ab.

Verwendung einer offenen CPE-Datenbank

Die erste Option, die wir untersucht haben, ist der Ansatz, der in OWASP Dependency Check verwendet wird. Der Ansatz ist einfach – für jede Abhängigkeit sucht dieses Dienstprogramm nach einer entsprechenden Kennung in der CPE-Datenbank (Common Platform Enumeration). Tatsächlich ist die CPE-Datenbank eine Liste mit Informationen über Produkte, ihre Versionen, Anbieter und so weiter. Um SCA zu implementieren, müssen wir CPE- und CVE-Korrespondenzen erhalten. Daher ist das Abrufen einer CVE-Liste lediglich eine Suche nach dem entsprechenden Eintrag in der CPE-Datenbank.

Sie finden die CPE-Datenbank und die CVE-Konformität auf der offiziellen Website der National Vulnerability Database. Eine der Möglichkeiten, die erforderlichen Informationen zu erhalten, ist die Verwendung der Rest-API. Hier ist es beschrieben. Die folgende Abfrage ermöglicht es uns beispielsweise, die ersten 20 Elemente der CPE-Datenbank einschließlich der entsprechenden CVEs abzurufen:

https://services.nvd.nist.gov/rest/json/cpes/1.0?addOns=cves

Unten ist ein Beispiel für CPE für ActivePerl:

{
  "deprecated": false,
  "cpe23Uri": "cpe:2.3:a:activestate:activeperl:-:*:*:*:*:*:*:*",
  "lastModifiedDate": "2007-09-14T17:36Z",
  "titles": [
              {
                "title": "ActiveState ActivePerl",
                "lang": "en_US"
              }
            ],
  "refs": [],
  "deprecatedBy": [],
  "vulnerabilities": [ "CVE-2001-0815", "CVE-2004-0377" ]
}

Der wichtigste Teil hier ist der Wert "cpe23Uri". Es enthält wichtige Informationen für uns in einem bestimmten Format und natürlich "Schwachstellen" (obwohl sie nicht Teil der CPE-Liste sind). Der Einfachheit halber lesen wir den "cpe23Uri"-String als

cpe:2.3:a:<vendor>:<product>:<version>:<update>:...

Gemäß der Spezifikation bedeutet ein Bindestrich anstelle eines der Fragmente einen logischen "NA"-Wert. Soweit ich verstehe, kann dies als "der Wert ist nicht festgelegt" interpretiert werden. Das Zeichen "*" anstelle eines Fragments bedeutet "ANY".

Wenn wir eine CPE-basierte Lösung implementieren, besteht die Hauptschwierigkeit darin, das richtige Element für jede Abhängigkeit zu finden. Das Problem hierbei ist, dass der Bibliotheksname (erhalten, als wir die Projektverknüpfungen analysierten) möglicherweise nicht mit dem entsprechenden CPE-Eintrag übereinstimmt. Beispielsweise enthält die CPE-Liste Einträge mit dem folgenden „cpe23Uri“:

cpe:2.3:a:microsoft:asp.net_model_view_controller:2.0:*:*:*:*:*:*:*
cpe:2.3:a:microsoft:asp.net_model_view_controller:3.0:*:*:*:*:*:*:*
cpe:2.3:a:microsoft:asp.net_model_view_controller:4.0:*:*:*:*:*:*:*
cpe:2.3:a:microsoft:asp.net_model_view_controller:5.0:*:*:*:*:*:*:*
cpe:2.3:a:microsoft:asp.net_model_view_controller:5.1:*:*:*:*:*:*:*

Nach der Verarbeitung der Einträge kommt der Analysator zu dem Schluss, dass sie sich alle auf verschiedene Versionen eines Produkts mit dem Namen „asp.net_model_view_controller“ beziehen, das von einer Firma namens Microsoft herausgebracht wurde. All diese Einträge entsprechen einer Schwachstelle mit der Kennung CVE-2014-4075. Die Bibliothek, in der die Schwachstelle entdeckt wurde, heißt jedoch "System.Web.Mvc". Höchstwahrscheinlich erhalten wir diesen Namen aus der Liste der Abhängigkeiten. In CPE lautet der Name des Produkts "Microsoft ASP.NET Model View Controller".

Außerdem müssen wir den Anbieter berücksichtigen, dessen Kennung ein wesentlicher Bestandteil der CPE-Einträge ist. Auch hier gibt es Probleme – die eigentliche Abhängigkeit liefert nicht immer die notwendigen Informationen in irgendeiner für das Parsing geeigneten Form. Ganz zu schweigen von der Übereinstimmung dieser Informationen mit allen Einträgen von CPE.

Sie können sich vorstellen, dass ähnliche Probleme mit der Bibliotheksversion auftreten.

Ein weiteres Problem besteht darin, dass viele Datensätze in der Datenbank nicht relevant sind, wenn wir nach Übereinstimmungen suchen. Nehmen wir als Beispiel den Eintrag am Anfang dieses Abschnitts:

cpe:2.3:a:activestate:activeperl

ActivePerl ist eine Distribution der Sprache Perl von ActiveState. Die Wahrscheinlichkeit, dass so etwas eine Abhängigkeit von einem C#-Projekt wäre... Nun, ist gering. Es gibt viele "unnötige" (im Zusammenhang mit der Analyse von C#-Projekten) Einträge. Es ist schwer zu sagen, wie wir dem Analysator beibringen können, sie von den nützlichen zu unterscheiden.

Trotz der erwähnten Probleme kann der CPE-basierte Ansatz immer noch effektiv sein. Seine Implementierung sollte viel kniffliger sein als ein einfacher Zeichenfolgenvergleich. Beispielsweise funktioniert der OWASP Dependency Check auf interessante Weise. Für jede Abhängigkeit sammelt dieses Tool Nachweiszeichenfolgen, die den Hersteller-, Produkt- und Versionswerten des gewünschten CPE entsprechen können.

GitHub Advisory verwenden

Wir haben einen anderen Ansatz für die Suche nach CVEs gefunden. Wir untersuchen GitHub Advisory, um die Einträge zu finden, die der Abhängigkeit entsprechen, die wir überprüfen müssen. GitHub Advisory ist eine Schwachstellendatenbank (CVE), die in Open-Source-Projekten entdeckt wurde, die auf GitHub gespeichert sind. Die vollständige Liste der Positionen finden Sie hier.

Nachdem wir CPE kennengelernt haben, haben wir verstanden, dass die Methode der Datenerfassung bei der Auswahl der Datenquelle äußerst wichtig ist. Wir müssen zugeben, dass GitHub Advisory in diesem Fall viel bequemer ist als CPE. Möglicherweise wurde diese Datenbank ursprünglich für die Verwendung durch verschiedene SCA-Tools erstellt. Jedenfalls verwenden verschiedene Lösungen wie GitHub SCA und SCA von Microsoft diese Datenbank.

Für den programmgesteuerten Zugriff auf GitHub Advisory müssen wir GraphQL verwenden. Es ist eine leistungsstarke Technologie, aber wir müssen beachten, dass es viel einfacher ist, die Rest-API zu verstehen. Trotzdem gelang es mir, erschöpft von GitHubs GraphQL Explorer, endlich eine Abfrage zu machen, die fast das ausgibt, was ich wollte. Es gibt nämlich eine Liste von Paketen und entsprechenden CVEs aus. Hier ist eines der Elemente, die ich erhalten habe:

{
  "identifiers": [
    {
      "value": "GHSA-mv2r-q4g5-j8q5",
      "type": "GHSA"
    },
    {
      "value": "CVE-2018-8269",
      "type": "CVE"
    }
  ],
  "vulnerabilities": {
    "nodes": [
      {
        "package": {
          "name": "Microsoft.Data.OData"
        },
        "severity": "HIGH",
        "vulnerableVersionRange": "< 5.8.4"
      }
    ]
  }
}

Offensichtlich habe ich nicht die optimale Abfrage gemacht, also habe ich ein paar zusätzliche Informationen bei der Ausgabe erhalten.

Wenn Sie ein Experte für GraphQL sind, schreiben Sie bitte in die Kommentare, wie Sie eine Abfrage erstellen würden, die es Ihnen ermöglicht, eine Liste von Übereinstimmungen dieser Form zu erhalten:(Paketname, Version) => CVE-Liste.

Wie auch immer, das Abfrageergebnis gibt eindeutig den Paketnamen an – denjenigen, der dieser Abhängigkeit in NuGet entspricht. Der Paketname entspricht CVE und Versionen, für die die Schwachstellen relevant sind. Ich bin sicher, dass wir mit einem besseren Verständnis dieses Themas leicht ein Dienstprogramm erstellen könnten, das automatisch alle erforderlichen Informationen herunterlädt.

Wir müssen sagen, dass die Auswahl von Paketen speziell für NuGet eine nützliche Funktion ist. In vielen Fällen (wenn nicht allen) möchten wir nach Einträgen suchen, die einer bestimmten Abhängigkeit zwischen diesen Paketen entsprechen. Genauer gesagt möchten wir auf all das Zeug für Composer, Pip usw. verzichten.

Leider hat diese Lösung ihre Mängel. Zum Zeitpunkt der Erstellung dieses Artikels hatte das GitHub Advisory 4753 Einträge und nur 140 NuGet-Pakete. Im Vergleich zur CPE-Datenbank, die mehr als 700.000 Einträge enthält, sieht diese Sammlung nicht besonders beeindruckend aus. Allerdings müssen wir beachten, dass nicht alle CPEs entsprechende CVEs haben. Außerdem impliziert die Beschreibung, dass die GitHub Advisory-Datenbank nur Informationen über Schwachstellen von GitHub-gespeicherten Projekten enthält . Dadurch wird die Stichprobe erheblich eingeschränkt.

Dennoch lässt uns die Bequemlichkeit, Schwachstellen in dieser Datenbank darzustellen, zumindest darüber nachdenken, sie zu verwenden, wenn nicht als Hauptdatenquelle, dann zumindest als eine der Hilfsdatenquellen.

Unsere eigene Datenbank

Leistungsstarke SCA-Tools wie Black Duck und Open Source Lifecycle Management bilden und verwenden ihre eigenen Datenbanken. Diese Datenbanken enthalten, der Beschreibung nach zu urteilen, noch mehr Informationen als die National Vulnerability Database. Offensichtlich präsentieren solche Datenbanken Informationen in der bequemsten Form für die entsprechenden Tools.

Wenn wir in diese Richtung arbeiten, müssen wir die öffentlichen Daten, die über anfällige Komponenten gefunden wurden, in eine Form umwandeln, die für unseren Analysator geeignet ist. Wir müssen nur Daten finden, die für eine solche Transformation geeignet sind. Höchstwahrscheinlich haben alle SCA-Tools ihre eigenen Datenbanken mit anfälligen Komponenten. Allerdings enthalten nicht alle Informationen zu Schwachstellen, die nicht in NVD oder einer anderen öffentlichen Quelle enthalten sind. Eines der wichtigen Unterscheidungsmerkmale leistungsstarker SCA-Lösungen besteht darin, dass sie ihre benutzerdefinierte Basis aufbauen, die ähnliche Basen anderer Tools übertrifft. Daher werden wir bei der Arbeit an der SCA-Implementierung in PVS-Studio die Notwendigkeit berücksichtigen, unsere Schwachstellenbasis in Zukunft zu erweitern.

Orte, an denen anfällige Komponenten verwendet werden

Es mag den Anschein haben, dass die Implementierung der SCA-Funktionalität in PVS-Studio die Schaffung von etwas grundlegend Neuem erfordert, ohne die Möglichkeit, eine unserer bestehenden Entwicklungen zu verwenden. Und ehrlich gesagt nicht umsonst. Tatsache ist, dass die Abhängigkeitsanalyse eine brandneue Funktionalität ist und PVS-Studio derzeit nichts dergleichen hat.

Wir haben jedoch eine Idee, wie wir die vorhandene Architektur nutzen können, um unsere SCA-Implementierung zu verbessern. Anstatt den Analysator einfach beim Vorhandensein eines Links zu einer unsicheren Bibliothek auslösen zu lassen, werden wir versuchen, nach seiner Verwendung im Code zu suchen. Dafür haben wir viele fertige Mechanismen :).

Wenn die Bibliothek nicht einmal verwendet wird, sollte der Analysator meiner Meinung nach immer noch vor ihrer Anwesenheit unter den Abhängigkeiten warnen. Und wenn die Bibliotheksfunktionen irgendwie im Code angewendet werden, sollte der Analysator eine Warnung der höchsten Ebene ausgeben. Bisher sind das nur Gedanken.

Wie Sie sehen, haben wir uns noch nicht entschieden, welchen Implementierungsansatz wir verwenden sollen. Wir haben auch einige Probleme damit nicht gelöst. Zum Beispiel:Wenn wir eine Bibliothek mit einer Schwachstelle viele Male im Projekt verwenden, sollte der Analysator dann eine Warnung für jede Verwendungsstelle ausgeben? Oder wird der Benutzer in Warnungen ertrinken? Sollte der Analysator eine Warnung pro Datei ausgeben oder sollten wir einfach die Stufe erhöhen, wenn er die Verwendung einer solchen Bibliothek erkennt?

Wir haben viele solcher Fragen zu dieser Lösung. Deshalb würden wir gerne wissen — wie möchten SIE SCA in PVS-Studio sehen? Wie sollte ein effektives Tool zum Auffinden problematischer Schwachstellen funktionieren? Welche Stufe sollten Warnungen haben? Sollten wir versuchen, andere Informationsquellen zu Schwachstellen zu finden? Soll der Analysator bei transitiven (indirekten) Abhängigkeiten triggern?

Wie auch immer, wir warten auf Ihre Kommentare. Vielen Dank für Ihre Aufmerksamkeit!