Erstellen von zuverlässigen und sicheren C++-Programmen
Die Veröffentlichung der US-Regierung NISTIR 8397: Guidelines on Minimum Standards for Developer Verification of Software (Richtlinien für die Mindeststandards für die Überprüfung von Software durch Entwickler) enthält hervorragende Anleitungen zum Erstellen von zuverlässiger und sicherer Software in jeder Programmiersprache.
Dieses Dokument folgt der gleichen Struktur wie NISTIR 8397. Jeder Abschnitt:
- fasst zusammen, wie Sie Microsoft-Entwicklerprodukte für C++ und andere Sprachen verwenden, um die Sicherheitsanforderungen dieses Abschnitts zu erfüllen, und
- enthält Anleitungen zum Abrufen des größten Werts in den einzelnen Bereichen.
2.1 Erstellen von Gefahrenmodellen
Zusammenfassung
Die Gefahrenmodellierung ist ein wertvoller Prozess, insbesondere bei skalierter Anwendung, um Ihren Entwicklungsanforderungen gerecht zu werden und Rauschen zu reduzieren.
Empfehlungen
Die Gefahrenmodellierung sollte ein Teil Ihres dynamischen Security Development Lifecycle (SDL) sein. Wir empfehlen Folgendes für Ihr Produkt als Ganzes, für ein bestimmtes Feature oder für eine wesentliche Design- oder Implementierungsänderung:
- Einen soliden, dynamischen SDL, der eine frühzeitige Bindung mit Entwicklerteams und eine entsprechende Anpassung des Ansatzes ermöglicht.
- Gezielte Anwendung der Gefahrenmodellierung. Anwendung der Gefahrenmodellierung auf alle Features, jedoch taktisch beginnend mit zur Verfügung gestellten, komplexen oder kritischen Features. Stattdessen regelmäßige Anwendung als Teil einer Top-Down-Produktüberprüfung.
- Frühzeitige Anwendung der Gefahrenmodellierung (wie bei allen Sicherheitsanforderungen), wenn noch die Möglichkeit besteht, den Entwurf zu ändern. Außerdem dienen Gefahrenmodelle als Eingabe für andere Prozesse, z. B. zur Verringerung der Angriffsfläche oder für Entwürfe für die Sicherheit. Gefahrenmodelle, die später erstellt werden, sind die besten „Umfragen“ für Penetrationstests oder Bereiche, die Sicherheitstests wie Fuzzing erfordern. Nachdem Sie ein grundlegendes Gefahrenmodell erstellt haben, planen Sie die Fortsetzung der Iteration, während sich die Angriffsfläche ändert.
- Verwenden Sie Ressourcenbestand und Compliance, um das Produkt entsprechend nachzuverfolgen, und verfolgen Sie Sicherheitsartefakte (einschließlich Gefahrenmodellen) zusammen mit den Ressourcen nach, auf die sie angewendet werden. Dieser Ansatz ermöglicht eine bessere automatisierte Risikobewertung und Konzentration der Sicherheitsanstrengungen auf die spezifischen Komponenten oder Features, die sich ändern.
- In Azure wurde das Microsoft Threat Modeling Tool 2022 für die Azure-Entwicklung aktualisiert. Weitere Informationen finden Sie unter Übersicht über das Microsoft Threat Modeling Tool – Azure
Unterstützende Faktoren und Praktiken
Um die Gefahrenmodellierung ordnungsgemäß anzuwenden und eine übermäßige bzw. zu geringe Verwendung zu vermeiden, haben wir festgestellt, dass zuerst die folgenden Kernkonzepte berücksichtigt werden müssen.
Entwicklungsansatz
Verstehen Sie zunächst den Entwicklungsansatz des Teams. Für Teams mit agilen Entwicklungsworkflows, die täglich Dutzende von Änderungen an die Produktion pushen, ist es nicht praktisch oder sinnvoll, für jede funktionale Änderung ein Gefahrenmodellupdate zu verlangen. Stattdessen sollten Sie beim Schreiben der funktionalen Anforderungen eines Features von Anfang an einen Fragebogen zu Sicherheitsanforderungen berücksichtigen. Der Fragebogen sollte sich auf spezifische Fragen zum Feature konzentrieren, um zu bestimmen, welche zukünftigen Aspekte Ihres SDL zutreffen. Zum Beispiel:
- Ändert das Feature grundlegend die Art und Weise des Entwurfs, wie wir die Kundenisolation in einer mehrinstanzenfähigen Umgebung bereitstellen? Wenn ja, erwägen Sie, ein vollständiges Gefahrenmodell auszuführen.
- Lässt ein neues Feature Dateiuploads zu? Wenn ja, ist vielleicht eine Sicherheitsbewertung der Webanwendung besser geeignet.
- Ist diese Änderung in erster Linie nur eine funktionale Änderung der Benutzeroberfläche? Wenn ja, ist vielleicht außer den herkömmlichen automatisierten Tools nichts erforderlich.
Die Ergebnisse des Sicherheitsfragebogens informieren, welche SDL-Techniken an welche Entwicklungseinheit gebunden werden sollen. Sie informieren auch Entwicklungspartner über die SDL-Zeitachsen des Features, damit sie zu den richtigen Zeiten zusammenarbeiten können.
Produktbestand
Zweitens: Halten Sie einen starken Ressourcenbestand der Produkte aufrecht, die Sie bewerten sollen. Produkte werden immer komplexer. Häufig wird Software für verbundene Geräte geschrieben, die Folgendes haben:
- Sensoren (z. B. Schienenfahrzeuge und Fahrzeuge für Passagiere),
- Bus-basierte Netzwerke, die mit anderen Komponenten im Fahrzeug kommunizieren (z. B. CANBUS oder PROFIBUS),
- Drahtlos/Mobilfunk/Bluetooth für die Kommunikation mit Kundengeräten und Cloud-Back-Ends,
- Machine Learning in der Cloud mit Feedback an das Gerät oder eine Flottenverwaltungsanwendung.
- und mehr
Bei solch komplexen Produkten ist die Gefahrenmodellierung von entscheidender Bedeutung. Wenn Sie einen starken Ressourcenbestand haben, können Sie den gesamten Produktstapel anzeigen, um einen Überblick zu erhalten, und die wichtigsten Stellen anzeigen, die ausgewertet werden müssen, um zu ermitteln, wie sich ein neues oder geändertes Feature auf die Produktsicherheit auswirkt.
Granularität und Integration
Richten Sie Systeme ein, um die Compliance mithilfe eindeutiger Metriken zu messen.
- Messen Sie regelmäßig die Compliance für die Entwicklung auf Featureebene. Die Featurecompliance sollte in der Regel häufiger und weniger detailliert gemessen werden, manchmal sogar auf dem System des Entwicklers oder zur Code-Commit-/Zusammenführungszeit.
- Bewerten Sie regelmäßig die Sicherheit für das breitere Produkt, in dem ein Feature oder eine Komponente verbraucht wird. Breitere Auswertungen erfolgen in der Regel weniger häufig und detailliert, z. B. zur Modul- oder Systemtestzeit.
Skalierung
Unterhalten Sie ein ordnungsgemäßes Ressourcenbestandssystem, das Sicherheitsartefakte und die Ausgabe von Gefahrenmodellüberprüfungen erfasst und bewahrt. Wenn Sie einen klaren Bestand haben, können Sie die Ergebnisse der Überprüfung für Muster auswerten und intelligente Entscheidungen treffen, um das Produktsicherheitsprogramm regelmäßig zu verfeinern.
Versuchen Sie, Sicherheitsfragebögen der Anforderungsphase, Ergebnisse der Gefahrenmodellierung, Ergebnisse der Sicherheitsbewertung und Ergebnisse aus automatisierten Tools zu kombinieren. Wenn Sie sie kombinieren, können Sie einen Standpunkt des relativen Risikos eines bestimmten Produkts automatisieren, idealerweise als „Dashboard“, um Ihre Sicherheitsteams darüber zu informieren, worauf sie sich konzentrieren müssen, um den besten Nutzen aus der Gefahrenmodellierung zu erzielen.
2.2 Automatisiertes Testen
Zusammenfassung
Automatisierte Tests sind eine wichtige Möglichkeit, um die Qualität und Sicherheit Ihres Codes sicherzustellen. Sie sind ein integraler Bestandteil der Unterstützung anderer in diesem Dokument erwähnter Bereiche, z. B. Threat Modeling. Wenn sie mit anderen Methoden für sicheres Codieren gekoppelt sind, können sie die Codebasis davor schützen, dass Fehler und Sicherheitsrisiken eingeführt werden.
Schlüsselattribute
Tests sollten zuverlässig, konsistent und isoliert sein. Diese Tests sollten so viel Code wie möglich abdecken. Alle neuen Features und Fehlerkorrekturen sollten über entsprechende Tests verfügen, um die langfristige Sicherheit und Zuverlässigkeit des Codes möglichst sicherzustellen. Führen Sie automatisierte Tests regelmäßig und in möglichst vielen Umgebungen, um sicherzustellen, dass sie ausgeführt werden und alle Bereiche abdecken:
- Sie sollen zuerst auf dem Computer ausgeführt werden, auf dem die Änderungen vorgenommen werden. Das Ausführen von Tests erfolgt am einfachsten innerhalb der IDE, die für die Bearbeitung verwendet wird, oder als Skript in der Befehlszeile, während der Entwickler die Änderungen vorgibt.
- Danach sollten sie als Teil des Commit-/Zusammenführungsprozesses der Pull Request ausgeführt werden.
- Der letzte Ort zum Ausführen von Tests ist Teil einer Continuous Integration and Continuous Deployment (CI/CD)-Pipeline oder Ihre Release Candidate-Builds.
Der Umfang der Tests sollte bei jedem Schritt erhöht werden, wobei der letzte Schritt die vollständige Abdeckung dafür bietet, was bei den anderen Schritten versäumt wurde.
Kontinuierliche Nutzung und Wartung
Die Zuverlässigkeit von Tests ist ein wichtiger Bestandteil der Aufrechterhaltung der Effektivität der Testsuite. Testfehler sollten zugewiesen und untersucht werden, wobei potenzielle Sicherheitsprobleme hohe Priorität erhalten und innerhalb einer Eingabeaufforderung und eines vorbestimmten Zeitrahmens aktualisiert werden. Das Ignorieren von Testfehlern sollte keine gängige Praxis sein, sondern eine starke Begründung und Genehmigung erfordern. Testfehler aufgrund von Problemen innerhalb der Testsuite selbst sollten genauso behandelt werden wie andere Fehler, um Deckungslücken zu verhindern, durch die ihnen Probleme mit Produkten entgehen können.
Arten von Tests, insbesondere Komponententests
Es gibt mehrere Arten von automatisierten Tests, und obwohl nicht alle auf alle Anwendungen anwendbar sind, enthält eine gute Testsuite eine Auswahl verschiedener Typen. Codebasierte Testfälle wie Komponententests werden am häufigsten verwendet und sind am grundlegendsten, da sie für alle Anwendungen gelten und aus Gründen der Richtigkeit bewusst möglichst viele Codepfade abdecken. Diese Tests sollten klein und schnell sein und den Zustand des Computers nicht beeinträchtigen, damit die gesamte Testreihe schnell und häufig ausgeführt werden kann. Führen Sie nach Möglichkeit Tests auf vielen Computern mit unterschiedlichen Hardwaresetups aus, um Probleme abzufangen, die auf einem einzelnen Computertyp nicht reproduzierbar sind.
Visual Studio
Visual Studio Test Explorer unterstützt nativ viele der beliebtesten C++-Testframeworks und bietet Optionen zum Installieren von Erweiterungen für weitere Frameworks. Diese Flexibilität ist hilfreich für die Ausführung einer Teilmenge von Tests, die den Code abdecken, an dem Sie arbeiten, und erleichtert das Debuggen von Testfehlern, sobald sie auftreten. Visual Studio erleichtert auch das Einrichten neuer Testreihen für vorhandene Projekte und bietet hilfreiche Tools wie CodeLens, um diese Tests einfacher zu verwalten. Weitere Informationen zum Schreiben, Ausführen und Verwalten von C/C++-Tests mit Visual Studio finden Sie unter Schreiben von Komponententests für C/C++ – Visual Studio (Windows).
In Azure und GitHub CI/CD
Tests, bei denen eine detailliertere Überprüfung durchgeführt und diese länger ausgeführt werden muss, z. B. statische Analysen, Komponentenerkennung usw., eignen sich gut für Pull Request-Tests oder Continuous Integration-Tests. Azure DevOps und GitHub Actions vereinfachen die automatische Ausführung von Validierungen und Blockcodeüberprüfungen, wenn eine Überprüfung fehlschlägt. Durch die automatisierte Durchsetzung wird sichergestellt, dass der gesamte eingecheckte Code basierend auf den ausgeführten strengeren Überprüfungen sicher ist. Azure Pipelines und die Azure DevOps-Buildüberprüfung werden hier beschrieben:
- Richtlinien und Einstellungen für den Git-Branch – Azure Repos
- Defining the mergeability of pull requests | GitHub Docs
2.3 Codebasierte oder statische Analyse
Zusammenfassung Statische Code-/Binäre Analyse sollte standardmäßig aktiviert sein, um standardmäßig sicher zu sein. Statische Analysen analysieren ein Programm für erforderliche Sicherheitsrichtlinien zum Zeitpunkt der Erstellung, nicht zur Ausführungszeit, wenn ein Exploit auf dem Computer des Kunden auftreten kann. Statische Analysen können das Programm im Quellcodeformular oder in kompilierter ausführbarer Form analysieren.
Empfehlungen Microsoft empfiehlt Folgendes:
- Aktivieren Sie die statische Analyse für alle C++-Programme sowohl für den eingegebenen Quellcode (vor der Kompilierung) als auch für die ausführbaren Binärdateien (nach der Kompilierung). „Aktivieren“ kann bedeuten, während jedes Builds auf dem Computer des Entwicklers eine Analyse auszuführen, als separater Build, um den Code später zu prüfen, oder als Checkin-Anforderung.
- Integrieren Sie statische Analysen in CI-Pipelines als Form von Tests.
- Statische Analysen enthalten per Definition falsch positive Ergebnisse und sind bereit, diese Tatsache in Ihre Qualitätsfeedbackschleife zu integrieren. Lassen Sie sich schnell alle Warnungen mit wenigen falsch-positiven Warnungen im Vorfeld aktivieren. Seien Sie dann proaktiv, um die Anzahl der Regeln schrittweise zu erhöhen, für die Ihre Codebasis warnungsbereinigt kompiliert, während Sie regelmäßig weitere Regeln hinzufügen, die wichtige Fehler auf Kosten von allmählich mehr falsch-positiven Ergebnissen kennzeichnen (zunächst, bevor die Codebasis für diese Regeln bereinigt wurde).
- Verwenden Sie immer die neuesten unterstützten Versionen von Visual Studio, und richten Sie Ihre Entwicklungsumgebung so ein, dass Sie die neuesten Patchversionen schnell nutzen können, sobald sie verfügbar sind, ohne dass sie in die nächste Entwicklungsstufe/den nächsten Zyklus verschoben werden.
Schlüsseltools Beachten und verwenden Sie Folgendes:
- Dokumentation zur Codeanalyse – C++ und .NET
/analyze
- Visual C++-Compiler/W4
und/WX
- Visual C++-Compiler- Verwenden der Überprüfungen für C++ Core Guidelines
- CodeQL | GitHub
- Binskim-Benutzerhandbuch | GitHub
- Siehe auch (nur Windows): SAL-Anmerkungen
Hinweise:
/analyze
ermöglicht die statische Analyse von C++-Code zur Kompilierungszeit, um kritische Sicherheits- und Zuverlässigkeitscoderisiken zu identifizieren. Sie sollte während der gesamten Entwicklungszeitachse eines C++-Programms aktiviert sein. Beginnen Sie, indem Sie zumindest „Von Microsoft für eigene Projekte empfohlen“ standardmäßig als minimale Baseline aktivieren. Lesen Sie dann in der Dokumentation, wie Sie weitere Regeln angeben, insbesondere die Regeln der C++ Core Guidelines, wie in den Engineeringrichtlinien verlangt. Die statische Analysefunktion des Quellcodes ist sowohl in der Visual C++-IDE als auch in den Befehlszeilen-Buildtools verfügbar./W4
und/WX
sollten nach Möglichkeit aktiviert werden, um sicherzustellen, dass Sie ihren Code sauber auf hohen Warnstufen (W4
) kompilieren und Warnungen als Fehler behandeln, die behoben werden müssen (WX
). Diese Optionen ermöglichen das Auffinden nicht initialisierter Datenfehler, die andere statische Analysetools nicht überprüfen können, da die Fehler erst sichtbar werden, nachdem das Compiler-Back-End eine Analyse während des Vorgangs und Inlining ausführt.- Die BinSkim-Binäranalyse stellt sicher, dass Projekte eine breite Palette von Sicherheitsfeatures ermöglichen. BinSkim generiert PDBs und andere Ausgaben, die es einfacher machen, die Aufbewahrungskette zu überprüfen und effizient auf Sicherheitsprobleme zu reagieren. Microsoft empfiehlt, das BinSkim-Tool auszuführen, um alle ausführbaren Binärdateien (
.sys
,.dll
oder.exe
) zu analysieren, die für Ihre Programme erstellt oder genutzt werden. Das BinSkim-Benutzerhandbuch enthält eine Liste der unterstützten Sicherheitsstandards. Microsoft empfiehlt, alle vom BinSkim-Tool als „Fehler“ gemeldeten Probleme zu beheben. Probleme, die als „Warnungen“ gemeldet werden, sollten selektiv ausgewertet werden, da die Lösung Auswirkungen auf die Leistung haben kann oder nicht erforderlich ist.
In Azure und GitHub CI/CD Microsoft empfiehlt, Quellcode- und binäre statische Analysen immer in Release-CI/CD-Szenarien zu aktivieren. Führen Sie die Quellanalyse sofort auf dem Computer des lokalen Entwicklers oder zumindest für jeden Commit und jede Pull-Anforderung aus, um Quellfehler so früh wie möglich zu erkennen und die Gesamtkosten zu minimieren. Fehler auf binärer Ebene werden tendenziell langsamer eingeführt, daher kann es ausreichen, binäre Analysen in weniger häufigen CI/CD-Szenarien (z. B. nächtliche oder wöchentliche Builds) auszuführen.
2.4 Überprüfung auf hartcodierte Geheimnisse
Zusammenfassung
Codieren Sie keine Geheimnisse innerhalb der Software. Sie können Geheimnisse aus dem Quellcode effizient finden und entfernen, indem Sie zuverlässige Tools verwenden, mit denen Ihre gesamte Quellcodebasis überprüft werden kann. Sobald Sie Geheimnisse gefunden haben, verschieben Sie sie an einen sicheren Ort, der der Richtlinie für sicheren Speicher und der Verwendung von Geheimnissen folgt.
Problem
„Geheimnisse“ bezeichnet Entitäten, die Identität schaffen und Zugriff auf Ressourcen gewähren oder zum Signieren oder Verschlüsseln vertraulicher Daten verwendet werden. Beispiele hierfür sind Kennwörter, Speicherschlüssel, Verbindungszeichenfolgen und private Schlüssel. Es ist verlockend, Geheimnisse im Softwareprodukt zu bewahren, damit sie bei Bedarf einfach von der Software abgerufen werden können. Diese hartcodierten Geheimnisse können jedoch zu schwerwiegenden oder katastrophalen Sicherheitsvorfällen führen, da sie leicht entdeckt werden und verwendet werden können, um Ihren Dienst und Ihre Daten zu kompromittieren.
Prävention
Geheimnisse, die im Quellcode (als Nur-Text oder verschlüsseltes Blob) hartcodiert sind, sind eine Sicherheitslücke. Hier sind allgemeine Richtlinien zum Vermeiden von Geheimnissen im Quellcode:
- Verwenden Sie ein Precheckin-Tool, um nach potenziellen hartcodierten Geheimnissen im Code zu suchen und diese zu erkennen, bevor Sie die Quellcodeverwaltung übermitteln.
- Fügen Sie keine Anmeldeinformationen in Klartext in Quellcode- oder Konfigurationsdateien ein.
- Speichern Sie keine Anmeldeinformationen in Klartext in SharePoint, OneNote, Dateifreigaben usw. Teilen Sie sie auch nicht per E-Mail, Chat usw.
- Verschlüsseln Sie kein Geheimnis mit einem leicht auffindbaren Entschlüsselungsschlüssel. Speichern Sie z. B. keine PFX-Datei zusammen mit einer Datei, die ihr Kennwort enthält.
- Verschlüsseln Sie kein Geheimnis mit einer schwachen Entschlüsselung. Verschlüsseln Sie z. B. keine PFX-Datei mit einem schwachen oder allgemeinen Kennwort.
- Vermeiden Sie verschlüsselte Anmeldeinformationen im Quellcode. Verwenden Sie stattdessen Platzhalter in Ihrer Quelle, und lassen Sie sie von Ihrem Bereitstellungssystem durch Geheimnisse aus genehmigten Stores ersetzen.
- Wenden Sie dieselben Prinzipien auf Geheimnisse in Umgebungen an, z. B. Tests, Staging usw. wie bei Produktionsbereitstellungen. Angreifer zielen häufig auf Nichtproduktionssysteme ab, da sie weniger gut verwaltet werden, und verwenden diese dann, um in die Produktionsumgebung einzudringen.
- Teilen Sie Geheimnisse nicht zwischen Bereitstellungen (z. B. Tests, Staging, Produktion).
Auch wenn sie nicht direkt mit hartcodierten Geheimnissen verbunden sind, denken Sie daran, Geheimnisse für Ihren Test, Ihre Entwicklung und Produktion zu schützen:
- Ändern Sie Ihre Geheimnisse regelmäßig und immer, wenn sie offengelegt wurden. Die nachgewiesene Möglichkeit, Geheimnisse zu rotieren/erneut bereitzustellen, ist ein Beweis für ein sicheres System. Vor allem das Fehlen dieser Funktion ist ein noch stärkerer Beweis für eine unvermeidliche Sicherheitsanfälligkeit.
- Lenken Sie bei dem allgemeinen Entwicklerprinzip nicht ein, dass „meine Testanmeldeinformationen kein Risiko darstellen“. In der Praxis tun sie das fast immer.
- Ziehen Sie in Betracht, bei RBAC-/identitätsgesteuerten Lösungen vollständig von Geheimnissen (z. B. Kennwörtern, Bearerschlüsseln) als gute technische Lösung abzusehen, bei der eine falsche Verwaltung von Geheimnissen vollständig umgangen werden kann.
Erkennung
Ältere Komponenten Ihres Produkts enthalten möglicherweise versteckte hartcodierte Geheimnisse im Quellcode. Manchmal können Geheimnisse von den Desktopcomputern der Entwickler sich in Remote-Verzweigungen schleichen und in der Release-Verzweigung zusammengeführt werden, wobei Geheimnisse unbeabsichtigt offengelegt werden. Um Geheimnisse zu entdecken, die sich möglicherweise in Ihrem Quellcode verbergen, können Sie Tools verwenden, mit denen Sie Ihren Code auf hartcodierte Geheimnisse überprüfen können:
Wartung
Wenn Anmeldeinformationen in Ihrem Quellcode gefunden werden, müssen Sie den offengelegten Schlüssel sofort ungültig machen und basierend auf der Gefährdung eine Risikoanalyse durchführen. Auch wenn Ihr System weiterhin ausgeführt werden muss, können Sie zur Behebung anhand folgender Schritte einen Geheimnis-Manager aktivieren:
- Wenn die Wartung den Wechsel zu verwalteten Identitäten ermöglicht oder das Ablegen in einem Geheimnis-Manager wie Azure Key Vault (AKV) erfordert, führen Sie dies zuerst aus. Führen Sie dann die erneute Bereitstellung mit der aktualisierten Identität oder dem aktualisierten Schlüssel durch.
- Machen Sie das offengelegte Geheimnis ungültig.
- Führen Sie die Überwachung/Risikobewertung potenzieller Schäden durch, die auf Kompromittierung zurückzuführen sind.
Um kryptografische Schlüssel und andere Geheimnisse zu schützen, die von Cloud-Apps und -Diensten verwendet werden, verwenden Sie Azure Key Vault mit einer entsprechenden Zugriffsrichtlinie.
Wenn bei einer Offenlegung bestimmte Kundendaten/PII kompromittiert werden, sind möglicherweise andere Compliance-/Berichterstellungsanforderungen erforderlich.
Entfernen Sie die jetzt ungültigen Geheimnisse aus dem Quellcode, und ersetzen Sie sie durch alternative Methoden, bei denen die Geheimnisse nicht direkt im Quellcode offengelegt werden. Suchen Sie nach Möglichkeiten, Geheimnisse nach Möglichkeit mithilfe von Tools wie Azure AD zu beseitigen. Sie können Ihre Authentifizierungsmethoden aktualisieren, um verwaltete Identitäten über Azure Active Directory zu nutzen. Verwenden Sie nur genehmigte Stores zum Speichern und Verwalten von Geheimnissen wie Azure Key Vault (AKV). Weitere Informationen finden Sie unter:
Azure DevOps (AzDO)
AzDO-Benutzer können ihren Code über GitHub Advanced Security für Azure DevOps (GHAzDO) scannen. GHAzDO ermöglicht es Benutzern auch, Offenlegungen von Geheimnissen zu verhindern, indem Push-Schutz für ihre Repositorys aktiviert wird, um potenzielle Offenlegungen zu erkennen, bevor sie überhaupt auftreten. Weitere Informationen zum Erkennen hartcodierter Geheimnisse im Code in Azure DevOps finden Sie unter Geheimnisüberprüfung für GitHub Advanced Security für Azure DevOps in jedem der folgenden Links:
- GitHub Advanced Security für Azure DevOps
- Geheimnisüberprüfung für GitHub Advanced Security für Azure DevOps
- Microsoft Defender für DevOps – Vorschau
In GitHub
Die Überprüfung auf Geheimnisse ist bei GitHub.com in zwei Formen verfügbar:
- Warnungen zur Geheimnisüberprüfung für Partner. Wird automatisch für alle öffentlichen Repositorys ausgeführt. Alle Zeichenfolgen, die mit Mustern übereinstimmen, die von Partnern für die Geheimnisüberprüfung angegeben wurden, werden direkt an den jeweiligen Partner gemeldet.
- Warnungen zur Geheimnisüberprüfung für Benutzer. Sie können zusätzliche Überprüfungen für Repositorys aktivieren und konfigurieren, die im Besitz von Organisationen sind, die GitHub Enterprise Cloud verwenden und über eine Lizenz für GitHub Advanced Security verfügen. Diese Tools unterstützen auch private und interne Repositorys.
GitHub bietet bekannte Muster von Geheimnissen für Partner und Benutzer, die für Ihre Anforderungen konfiguriert werden können. Weitere Informationen finden Sie unter:
Hinweis
GitHub Advanced Security für Azure DevOps bietet die gleichen geheimen Scan-, Abhängigkeitsscan- und CodeQL-Codescanlösungen, die bereits für GitHub-Benutzer verfügbar sind, und integriert sie nativ in Azure DevOps, um Ihre Azure Repos und Pipelines zu schützen.
Weitere Ressourcen
- Credential Scanning | Microsoft Code With Engineering Playbook.
- detect-secrets: Credential scanning tool | GitHub – ein passend benanntes Modul zum Erkennen von Geheimnissen innerhalb einer Codebasis.
- Running detect-secrets in Azure Pipelines.
- Git-secrets | GitHub awslabs – verhindert, dass Sie Kennwörter und andere vertrauliche Informationen in ein Git-Repository übernehmen.
- Secrets Management | Microsoft Code with Engineering Playbook – enthält allgemeine Richtlinien dazu, wie Geheimnisse verwaltet werden sollen.
2.5 Ausführen mit Sprach- und vom Betriebssystem bereitgestellten Prüfungen und Schutz
Zusammenfassung
Die binäre Härtung erfolgt durch Anwenden von Sicherheitssteuerelementen zur Kompilierungszeit. Dazu gehören vorbeugende Maßnahmen, wie etwa:
- Verhindern von ausnutzbaren Sicherheitsrisiken im Code,
- Aktivieren von Laufzeiterkennungen, die Abwehrmaßnahmen bei Ausnutzung auslösen, und
- Aktivieren von Datenproduktion und -archivierung, um den Schaden zu begrenzen, der durch Sicherheitsvorfälle verursacht wird.
Binäre Verbraucher müssen sich für Windows-Sicherheitsfeatures entscheiden, um den vollen Vorteil der Härtung zu erzielen.
Microsoft bietet eine Reihe von spezifischen Einrichtungen für C++-Projekte, mit denen Entwickler sichereren Code schreiben und versenden können. C++-Entwickler sollten auch Sicherheitsstandards einhalten, die für Sprachen gelten, die ausführbaren Code generieren. Microsoft verwaltet BinSkim, eine öffentliche OSS-Binärprüfung, die die Verwendung vieler Schutzmechanismen erzwingt, die in diesem Abschnitt beschrieben werden. Weitere Informationen zu BinSkim finden Sie in Binskim user guide | GitHub
Steuerelemente auf binärer Ebene unterscheiden sich je nach Anwendung im Engineeringprozess. Sie sollten zwischen Optionen für Compiler und Linker unterscheiden, die die Zeit strikt kompilieren, die Codegenerierung mit Laufzeitaufwand ändern und die Codegenerierung ändern, um Kompatibilität mit Betriebssystemschutz zu erzielen.
Entwicklereinstellungen sollten möglichst viele statische Analysen ermöglichen, die Produktion privater Daten ermöglichen, um das Debuggen zu beschleunigen, usw. Releasebuilds sollten auf eine geeignete Kombination aus Sicherheits-, Leistungs- und anderen Problemen bei der Codegenerierung abgestimmt werden. Releaseprozesse müssen so konfiguriert werden, dass öffentliche und private Builddaten ordnungsgemäß generiert und verwaltet werden (z. B. öffentliche oder private Symbole).
Bleiben Sie auf dem neuesten Stand: Verwenden Sie immer aktuelle Compiler und Tools
Kompilieren Sie den gesamten Code mit aktuellen Toolsets, um von aktueller Sprachunterstützung, statischer Analyse, Codegenerierung und Sicherheitssteuerelementen zu profitieren. Da Compiler sich auf jede generierte Komponente auswirken, ist das Potenzial für Regressionen bei der Toolaktualisierung relativ hoch. Die Verwendung veralteter Compiler verursacht ein bestimmtes Risiko für Korrekturmaßnahmen, während sie auf einen Sicherheitsvorfall reagieren, da Teams möglicherweise nicht genügend Zeit zum Upgrade von Compilern haben. Microsoft empfiehlt Teams, die Einrichtung zu entwickeln, um Compilerupdates regelmäßig zu aktualisieren und zu testen.
Verwenden sicherer Entwicklungsmethoden, Sprachversionen, Frameworks/APIs
Code sollte Entwicklungsmethoden, Sprachversionen, Frameworks, APIs usw. verwenden, die Risiken minimieren, indem Sicherheit und Einfachheit in C++ gefördert werden, einschließlich:
- Unter C++ Core Guidelines' Guideline Support Library (GSL) finden Sie Anleitungen zum Schreiben von modernem, sicherem und konsistentem C++-Code, der bewährten Methoden folgt, und Sie vermeiden häufige Fehlerquellen.
- Unter Microsoft GSL implementation finden Sie Funktionen und Typen, die von den C++ Core Guidelines empfohlen werden.
- Ressourcensichere C++-Container, CRT-Speicherüberlaufschutz (C-Runtime Library): bevorzugt
std::vector
undstd::string
, die ressourcensicher sind. Wenn Sie C-Daten verwenden müssen, verwenden Sie die sicheren Versionen von CRT-Funktionen, die zur Verhinderung von Speicherschäden aufgrund von Puffermissbrauch und nicht definiertem Sprachverhalten dienen sollen. - Die SafeInt-Bibliothek schützt vor Ganzzahlüberlauf in mathematischen und Vergleichsvorgängen.
Sichere Abhängigkeiten nutzen
Binärdateien sollten nicht mit unsicheren Bibliotheken und Abhängigkeiten verknüpft werden. Entwicklungsteams sollten alle externen Abhängigkeiten nachverfolgen und CVEs/identifizierte Sicherheitsrisiken in diesen Komponenten beheben, indem sie auf sicherere Versionen aktualisieren, wenn diese Sicherheitsrisiken unterliegen.
Maximieren von Code-Herkunftsgarantien und Effizienz der Sicherheitsreaktion
Die Kompilierung sollte starken Code-Herkunftsgarantien ermöglichen, die Einführung von Hintertüren und anderem schädlichen Code zu erkennen und zu verhindern. Die resultierenden Daten, die auch für das Debuggen und die Untersuchung wichtig sind, sollten für alle Softwareversionen archiviert werden, um eine effiziente Sicherheitsreaktion zu erzielen, wenn sie kompromittiert werden. Die folgenden Compilerswitche generieren Informationen, die für eine Sicherheitsreaktion von entscheidender Bedeutung sind:
/ZH:SHA_SHA256
in Visual C++ – Stellt sicher, dass ein kryptografisch sicherer Algorithmus verwendet wird, um alle PDB-Quelldateihashes zu generieren./Zi
,/ZI
(Debuginformationsformat) in Visual C++ – Zusätzlich zum Veröffentlichen von entfernten Symbolen zum Sammeln von Absturzdaten und anderen Szenarien für die öffentliche Verwendung stellen Sie sicher, dass Builds private PDBs für alle veröffentlichten Binärdateien erstellen und archivieren. Binäre Analysetools erfordern vollständige Symbole, um zu überprüfen, ob viele Risikominderungen zur Kompilierungszeit aktiviert wurden. Private Symbole sind bei der Sicherheitsreaktion kritisch und senken die Debugging- und Untersuchungskosten, wenn Ingenieure versuchen, Schäden im Missbrauchsfall schnell zu bewerten und zu begrenzen./SOURCELINK
in Visual C++-Linker – Sourcelink-Datei in PDB einschließen: Der Quelllink ist ein von der Sprache und Quellcodeverwaltung unabhängiges System, das das Quelldebugging für Binärdateien bereitstellt. Das Quelldebugging erhöht die Effizienz des Bereichs der Sicherheitsüberprüfungen vor der Veröffentlichung und der Reaktion auf Vorfälle nach der Veröffentlichung.
Compilerfehler aktivieren, um Probleme bei der Codeerstellungszeit zu verhindern
Die Kompilierung sollte sicherheitsrelevante Compilerprüfungen als gravierende Fehler aktivieren, z. B.:
/sdl
in Visual C++ – Zusätzliche Sicherheitsüberprüfungen aktivieren erhebt viele sicherheitsrelevante Warnungen zu Fehlern und ermöglicht erweiterte Features der sicheren Codegenerierung.- BinSkim BA2007.EnableCriticalCompilerWarnings | GitHub verwaltet eine Liste der von Microsoft empfohlenen C/C++-Compilerwarnungen, die immer aktiviert und zu Fehlern erhoben werden sollten.
Kennzeichnen von Binärdateien als kompatibel mit Risikominderungen der Betriebssystemlaufzeit
Compiler- und Linkereinstellungen sollten Codegenerierungsfeatures verwenden, die die Ausführung bösartiger Codes erkennen und mindern, einschließlich:
- Verhinderung von Stapelbeschädigungen
/SAFESEH
– Das Image verfügt über sichere Ausnahmehandler – Erstellt eine Tabelle der sicheren Ausnahmehandler des Image für x86-Binärdateien.- –
/GS
Puffersicherheitsüberprüfung – Erkennt einige Pufferüberläufe, welche die Rückgabeadressen, Ausnahmehandleradressen oder bestimmte Typen von Parametern überschreiben.
- Ausführung von positionsunabhängigem Code
/DYNAMICBASE
– Address Space Layout Randomization verwenden – Generiert ausführbare Images, für die zur Ladezeit nach dem Zufallsprinzip ein Rebase ausgeführt werden kann./HIGHENTROPVA
und/LARGEADDRESSAWARE
– Unterstützen von 64-Bit-ASLR und Verarbeiten umfangreicher Adressen – Ermöglicht die Verwendung des gesamten 64-Bit-Adressraums für Image-Rebases.
- Codeflussintegrität
/guard:cf
– Ablaufsteuerungsschutz aktivieren – Fügt Laufzeitüberprüfungen für indirekte Anrufziele ein./CETCOMPAT
– CET-Schattenstapel kompatibel – Markiert ein ausführbares Bild als kompatibel mit der Implementierung der Schattenstapel-Funktion Control-Flow Enforcement Technology (CET) von Intel./guard:ehcont
– Aktivieren von EH-Fortsetzungsmetadaten – Generiert eine Liste sicherer relativer virtueller Adressen (RVA) aller Fortsetzungsziele für die Ausnahmebehandlung.
- Datenausführungsverhinderung
/NXCOMPAT
– Kompatibel mit der Datenausführungsverhinderung – Kennzeichnet ein ausführbares 32-Bit-Image als kompatibel mit dem Feature Windows-Datenausführungsverhinderung (Data Execution Prevention; DEP). 64-Bit-Builds sind standardmäßig mit DEP kompatibel.)
Verhindern der Offenlegung vertraulicher Informationen
Die Compilereinstellungen sollten so gewählt werden, dass vertrauliche Informationen nicht erkannt werden können. In den letzten Jahren haben Forscher unbeabsichtigte Informationslecks in Hardwarefeatures wie der spekulativen Ausführung entdeckt.
Auf Softwareebene können vertrauliche Daten an Angreifer übertragen werden, wenn sie unerwartet offengelegt werden. Durch fehlendes Initialisieren von Puffern mit Null und anderen Puffermissbrauch können private vertrauliche Daten an Angreifer durchsickern, die eine vertrauenswürdige API aufrufen. Diese Problemklasse wird am besten behandelt, indem zusätzliche statische Analysen aktiviert und sichere Ressourcencontainer verwendet werden, wie zuvor beschrieben.
/Qspectre
– Abmildern von Seiten-Kanal-Angriffen bei spekulativer Ausführung – Fügt Anweisungen für Barrieren ein, mit denen verhindert wird, dass vertrauliche Daten, die durch spekulative Ausführung erzeugt werden, offengelegt werden. Diese Entschärfungen sollten für Code aktiviert werden, der vertrauliche Daten im Arbeitsspeicher speichert und über eine Vertrauensgrenze hinweg ausgeführt wird. Microsoft empfiehlt immer, leistungsrelevante Auswirkungen auf geeignete Benchmarks zu messen, wenn Spectre-Entschärfungen aufgrund der Möglichkeit aktiviert werden, Laufzeitüberprüfungen in leistungskritische Blöcke oder Schleifen einzuführen. Diese Codepfade können Entschärfungen über den Modifiziererspectre(nomitigation)
declspec
deaktivieren. Projekte, für die/Qspectre
aktiviert ist, sollten auch mit Bibliotheken verknüpft werden, die ebenfalls mit diesen Entschärfungen kompiliert wurden, einschließlich der Microsoft-Laufzeitbibliotheken.
2.6 Testfälle für Blackbox
Zusammenfassung
Bei Blackboxtests sind die inneren Abläufe der getesteten Komponente nicht bekannt. Bei Blackboxtests soll die End-to-End-Funktionalität der Features im Produkt auf jeder Schicht oder Ebene getestet werden. Blackboxtests können funktionale Tests, UI-Tests, Leistungstests und Integrationstests sein. Blackboxtests sind wertvoll zum Messen der allgemeinen Zuverlässigkeit und der Richtigkeit der Funktionen. Zudem gewährleisten sie, dass sich das Produkt wie erwartet verhält.
Beziehung zu anderen Abschnitten
Diese Arten von anforderungsbasierten Tests sind nützlich, um die Annahmen im Gefahrenmodell zu validieren und potenzielle Bedrohungen abzudecken, wie in diesem Abschnitt beschrieben. Diese Tests sind nützlich, um die Integration zwischen separaten Komponenten des Produkts zu testen, insbesondere solche, die sich über vertrauenswürdige Grenzen erstrecken, wie im Bedrohungsmodell beschrieben. Blackbox-Testfälle sind zudem hilfreich zum Testen aller Arten von Grenzfällen bei der Überprüfung der Benutzereingabe. Das Testen von bekannten Grenzfällen und Fehlerfällen ist gleichermaßen hilfreich. Fuzzing ist auch nützlich, um weniger offensichtliche Fälle zu testen.
Automatisierung und Regression
Führen Sie diese Tests regelmäßig aus, und vergleichen Sie die Ergebnisse mit früheren Ausführungen, um wichtige Änderungen oder Leistungsabnahmen zu erkennen. Außerdem kann das Ausführen dieser Tests auf vielen verschiedenen Computern und Installationssetups dazu beitragen, alle Probleme zu behandeln, die sich aus verschiedenen Architekturen oder Setupänderungen ergeben können.
Absturzabbilder
Diese Tests helfen beim Erkennen von Problemen mit der Zuverlässigkeit, da sie viele verschiedene Szenarien testen können, die zu Abstürzen, Hängenbleiben, Deadlocks usw. führen können. Durch das Sammeln von Absturzabbildern als Teil von Testfehlern können Sie die Abbilder direkt in Visual Studio importieren, um weiter zu untersuchen, welche Teile des Codes auf diese Probleme stoßen. Wenn Sie Funktionstests in Visual Studio ausführen, können Sie Fehler auf einfache Weise replizieren und debuggen, da Sie genau sehen, wo innerhalb der Blackbox der Test fehlschlägt, und Sie können Korrekturen schnell testen.
Informationen zu den ersten Schritten mit Debuggingtests finden Sie unter Debuggen von Komponententests mit dem Test-Explorer – Visual Studio (Windows)
In Azure
Azure DevOps kann auch bei der Verwaltung und Überprüfung dieser Tests mit der Verwendung von Testplänen helfen. Diese Tests können verwendet werden, um die Genehmigung mit manueller Überprüfung sicherzustellen und automatisierte Tests auszuführen, die den Produktanforderungen zugeordnet sind. Weitere Informationen zu Azure Test Plans und deren Verwendung zum Ausführen automatisierter Tests finden Sie hier:
- Was ist Azure Test Plans? Manuelle, explorative und automatisierte Testtools. - Azure Test Plans
- Weitere Informationen finden Sie unter Durchführen von automatisierten Tests aus Testplänen – Azure Test Plans
2.7 Codebasierte Testfälle
Zusammenfassung
Codebasierte Testfälle sind ein integraler Bestandteil der Aufrechterhaltung der Sicherheit und Zuverlässigkeit Ihres Produkts. Diese Tests sollten klein und schnell sein und sich nicht gegenseitig beeinflussen, damit sie parallel ausgeführt werden können. Entwickler können codebasierte Tests einfach lokal auf ihrem Entwicklungscomputer ausführen, wenn sie Änderungen am Code vornehmen, ohne sich Gedanken darüber machen zu müssen, ihren Entwicklungszyklus zu verlangsamen.
Typen und Beziehung zu anderen Abschnitten
Zu den gängigen Typen von codebasierten Testfällen gehören:
- Komponententests,
- parametrisierte Tests zur Abdeckung von Funktionen mit mehreren Eingabetypen,
- Komponententests, um die einzelnen Testkomponenten zu separieren, und
- Pseudotests, um Teile des Codes zu überprüfen, die mit anderen Diensten kommunizieren, ohne den Umfang des Tests auf diese Dienste zu erweitern.
Diese Tests basieren auf dem internen Code, der geschrieben wurde, während Blackboxtests auf den externen funktionalen Anforderungen des Produkts basieren.
Ziel
Bei diesen Tests ist es das Ziel, eine hohe Testabdeckung für Ihren gesamten Code zu erreichen. Sie sollten diese Abdeckung und eventuelle Lücken aktiv nachverfolgen. Wenn Sie weitere Tests hinzufügen, die mehr Codepfade ausführen, steigt das Gesamtvertrauen in die Sicherheit und Zuverlässigkeit Ihres Codes.
Visual Studio
Mit den Test-Explorer-Tools in Visual Studio können Sie diese Tests häufig ausführen und schnell Feedback zu Pass-/Fail-Raten und Fehlerorten erhalten. Viele der Testframeworks unterstützen auch CodeLens-Features, um den Teststatus am Ort des Tests selbst zu sehen, wodurch das Hinzufügen und Verwalten der Testreihe vereinfacht wird. Der Test-Explorer erleichtert auch die Verwaltung dieser Tests, sodass Testgruppen, benutzerdefinierte Testlisten, Filtern, Sortieren, Suchen und mehr möglich sind.
Weitere Informationen finden Sie unter:
- Grundlagen von Komponententests – Visual Studio (Windows) – Einführung und Übersicht
- Ausführen von Komponententests mit dem Test-Explorer – Visual Studio (Windows) – ein tieferer Einblick in die verfügbaren Komponententests, um die potenziell große Reihe an Komponententests mit dem Test-Explorer zu verwalten.
Visual Studio bietet außerdem Tools zum Nachverfolgen der Code Coverage. Mit diesen Tools können Sie sicherstellen, dass Codeänderungen, die Sie vornehmen, von vorhandenen Tests abgedeckt werden, oder neue Tests hinzufügen, um neue und ungetestete Codepfade abzudecken. Die Tools zeigen auch den Prozentsatz der Code Coverage an, um sicherzustellen, dass die gesamte Codequalität stets über einem Konfidenz-Zielwert bleibt.
Informationen zu diesen Tools finden Sie unter Code Coverage-Tests – Visual Studio (Windows)
In Azure
Azure DevOps kann auch bei der Nachverfolgung von Code Coverage-Ergebnissen für das gesamte Produkt als Teil des Buildpipelineprozesses helfen. Weitere Informationen finden Sie unter Überprüfen der Code Coverage – Azure Pipelines.
2.8 Historische Testfälle
Zusammenfassung
Historische Testfälle, auch Regressionstestfälle genannt, verhindern, dass alte Probleme wieder auftauchen, und erhöhen die gesamte Testabdeckung des Produkts. Sie sollten sicherstellen, dass beim Beheben eines Fehlers vom Projekt auch ein entsprechender Testfall hinzugefügt wird. Im Laufe der Zeit wird die gesamte Stabilität der Testreihe verbessert, da Korrekturen vorgenommen werden, wodurch eine bessere Zuverlässigkeit und Sicherheit gewährleistet wird.
Wichtige Qualitäten und Beziehung zu anderen Abschnitten
Da sie auf Fehlerregressionen testen, sollten diese Tests schnell und einfach ausgeführt werden, damit sie zusammen mit den [Codebasierten Testfällen] ausgeführt werden und zur gesamten Codeabdeckung des Produkts beitragen können. Dazu ist die Verwendung reeller Beispiele von Kunden als Inspiration für neue Testfälle eine hervorragende Möglichkeit, die Abdeckung und Qualität von Tests zu verbessern.
Visual Studio
Mit Visual Studio können Sie der Suite problemlos Tests hinzufügen, während Sie die Änderungen vornehmen, um den Fehler zu beheben, und die Tests und Codeabdeckung schnell ausführen, um sicherzustellen, dass alle neuen Fälle berücksichtigt werden. Das Verweisen auf die Fehler-ID aus Ihrem Problemverfolgungssystem in Ihrem Code, in dem Sie den Test schreiben, ist eine gute Möglichkeit, Regressionstests mit den entsprechenden Problemen zu verbinden. Verwenden Sie Azure Boards und Test Plans zusammen mit Visual Studio:
- um Tests, Testfälle und Probleme zuzuordnen; und
- um alle Aspekte eines Problems und der entsprechenden Tests nachzuverfolgen.
Weitere Informationen finden Sie unter:
- Zuordnen von automatisierten Tests zu Testfällen – Azure Test Plans
- Verknüpfen von Arbeitselementen mit anderen Objekten – Azure DevOps
Schließlich hilft die Integration dieser Tests in den Komponententestbereich, der den Codeabschnitt abdecken soll, die Testreihe zu organisieren und einfacher zu verwalten. Sie können die Testgruppierung des Test-Explorers verwenden, um die zusammengehörenden Tests effektiv nachzuverfolgen. Weitere Informationen finden Sie unter Ausführen von Komponententests mit dem Test-Explorer – Visual Studio (Windows).
2.9 Fuzzing
Zusammenfassung Fuzzing (auch als Fuzz-Testing bezeichnet) ist eine automatisierte Softwaretesttechnik, bei der ungültige, unerwartete oder zufällige Daten als Eingabe für ein Programm bereitgestellt werden. Das Programm wird dann auf Ausnahmen wie Abstürze, ausgefallene integrierte oder vom Compiler injizierte Codeassertionen und potenzielle Speicherverluste überwacht.
Leitfaden
Verwenden Sie Fuzzing für jegliche Software, die möglicherweise nicht vertrauenswürdige Eingaben verarbeitet, die ein Angreifer kontrollieren könnte. Wenn Sie eine neue Anwendung und die zugehörige Testreihe erstellen, beziehen Sie Fuzzing für wichtige Module so früh wie möglich mit ein. Das erstmalige Ausführen von Fuzzing an ein Software deckt fast immer tatsächliche bislang unbekannte Sicherheitslücken auf. Wenn Sie einmal mit dem Fuzzing begonnen haben, hören Sie nicht mehr damit auf.
Beziehung zu anderen Abschnitten
Wenn beim Fuzzing ein Fehler gemeldet wird, wird immer ein reproduzierbarer Testfall bereitgestellt, der den Fehler veranschaulicht. Dieser Testfall kann reproduziert, aufgelöst und dann zu den historischen Testfällen hinzugefügt werden.
Bei Verwendung von Sanitizern wie Address Sanitizer (ASan) und Fuzzing:
- Führen Sie zuerst Ihre normalen Tests mit aktiviertem Sanitizer aus, um festzustellen, ob Probleme bestehen, und starten Sie das Fuzzing, nachdem der Code mit Sanitizer bereinigt wurde.
- Für C oder C++ gibt es Compiler, die das Einfügen von Laufzeitassertionen und ASan-fähigen Metadaten automatisieren. Bei der Kompilierung für ASan verlinken die resultierenden Binärdateien auf eine Laufzeitbibliothek, die mehr als 15 Kategorien von Speichersicherheitsfehlern ohne falsch positive Ergebnisse genau diagnostizieren kann. Verwenden Sie für C oder C++ bei Verwendung der Quelle LibFuzzer, wobei jedoch ASan zuerst aktiviert werden muss.
- Verwenden Sie für Bibliotheken, die in Java, C#, Python, Rust usw. geschrieben wurden, das AFL++-Framework.
Schlüsselqualitäten
- Fuzzing findet Sicherheitsrisiken, die von der statischen Programmanalyse, umfassenden Featuretests und manueller Codeüberprüfung häufig übersehen werden.
- Fuzzing ist eine effektive Möglichkeit, Sicherheits- und Zuverlässigkeitsfehler in der Software zu finden, sodass der Microsoft Security Development Lifecycle Fuzzing an jeder nicht vertrauenswürdigen Schnittstelle jedes Produkts erfordert (siehe auch Gefahrenmodellierung).
- Verwenden Sie Fuzzing stets für Software, die möglicherweise nicht vertrauenswürdige Eingaben verarbeitet.
- Fuzzing ist für eigenständige Anwendungen mit großen Datenparsern effektiv.
Azure und GitHub CI/CD
Ändern Sie Ihre Builds, um die kontinuierliche Erstellung von ausführbaren Dateien zu unterstützen, die LibFuzzer oder AFL++ verwenden. Sie können zusätzliche Computerressourcen hinzufügen, die für Fuzzing bei Diensten wie OSS-Fuzz oder OneFuzz erforderlich sind.
2.10 Scannen von Webanwendungen
Zusammenfassung
Im Rahmen von Microsoft Visual C++ unter Windows empfiehlt Microsoft Folgendes:
- Bevorzugt TypeScript, JavaScript und ASP.NET für Webanwendungen.
- Schreiben Sie keine Weberweiterungen in C++. Microsoft weist ein veraltetes ActiveX auf.
- Wenn Code in Emscripten/WASM kompiliert wird, gilt er nicht mehr C++ und andere Tools.
- Microsoft stellt RESTler, einen zustandsbehafteten REST-API-Fuzzer bereit.
Übersicht und wichtige Qualitäten
Ein Webanwendungsscanner durchsucht eine Webanwendung, indem er ihre Webseiten durchforstet und auf Sicherheitsrisiken untersucht. Diese Durchforstung umfasst die automatische Generierung schädlicher Eingaben und die Auswertung der Antworten der Anwendung. Wichtig ist, dass das Scannen von Webanwendungen Folgendes abdecken/unterstützen muss:
- Katalogisiert alle Webanwendungen in Ihrem Netzwerk, einschließlich neuer und unbekannter Anwendungen, und skaliert von wenigen Anwendungen auf tausende Anwendungen.
- Umfassende Suche nach Softwareversionen, SOAP- und REST-API-Diensten und APIs, die von mobilen Geräten verwendet werden.
- Einfügen von Sicherheitsgrundtypen in die Anwendungsentwicklung und -bereitstellung in DevOps-Umgebungen. Diese Grundtypen funktionieren mit dem Crawler.
- Schadsoftwareerkennung.
2.11 Überprüfen der enthaltenen Softwarekomponenten
Zusammenfassung
Behandeln Sie Ihren C++-Code genauso wie Code, der in anderen Programmiersprachen geschrieben wurde, und wenden Sie sämtliche Softwarekompositionsanalyse (SCA)- and Ursprungsanalyse (OA)-Tools an, die von Ihrem Unternehmen für Ihren C++-Code eingesetzt werden. Workflow- und Sicherheitsscans sollten als Teil von CI/CD-Systemen (Continuous Integration und Continuous Delivery) entworfen werden.
Upstream-Verteidigung
Um das Risiko von Angriffen auf Upstreamabhängigkeiten zu verringern, sollten Quellen/Komponenten von Drittanbietern auf einer vom Unternehmen gesteuerten Ressource gespeichert werden, für die SCA- und OA-Tools ausgeführt werden.
- Tools sollten überprüfen und melden, wenn Sicherheitsrisiken (einschließlich öffentlicher Datenbanken) erkannt werden, z. B.: Home | CVE
- Führen Sie statische Analysen für alle Softwarekomponenten aus, die in Ihrer Anwendung/Ihrem Repository enthalten sind, um anfällige Codemuster zu identifizieren.
Abhängigkeitsverteidigung
Führen Sie eine Überprüfung der Abhängigkeiten durch, um zu überprüfen, ob alle diese Vorkommen von Ihren SCA- und OA-Tools berücksichtigt und abgedeckt werden.
- Komponenten sollten regelmäßig überwacht und auf die neuesten überprüften Versionen aktualisiert werden.
- Paketfeedabhängigkeiten
- SCA/OA-Tools umfassen und überwachen alle Paketabhängigkeiten, die aus einem einzigen Feed stammen.
SBOM
Erstellen Sie eine Stückliste für Software (Software Bill of Materials, SBOM) mit Ihrem Produkt, in der alle Abhängigkeiten aufgeführt sind, z. B.:
- Ursprung (Beispiel: URL (Uniform Resource Locator))
- version
- Konsistenz (Beispiel: SHA-256-Source-Hash) und andere Mittel zur Überprüfung der Konsistenz wie deterministische Builds.
- Verlangen und überwachen Sie SBOM-Dateien in Softwareabhängigkeiten oder erstellt als Teil eines Builds, einschließlich OSS (Open-Source-Software).
- Microsoft standardisiert und empfiehlt SPDX (Software Package Data Exchange) Version 2.2 oder höher | Linux Foundation als SBOM-Dokumentformat.
- Builddeterminismus kann verwendet werden, um bitweise identische Binärdateien unabhängig zu produzieren und unabhängige Überprüfungen der Integrität bereitzustellen:
- Nachweis der Reproduzierbarkeit von Erstanbietern oder Drittanbietern
- Andere Techniken wie die binäre Signatur über eine vertrauenswürdige Zertifikatquelle können auch Zusicherungen der binären Integrität bieten.
Weitere Ressourcen
Microsoft-Lösungen umfassen die folgenden Leitfäden und Produkte:
- Microsoft Supply Chain Platform | Microsoft
- Schutz Ihrer Software-Lieferkette | GitHub-Sicherheit
- vcpkg – Private vcpkg-Registrierungen ermöglichen die Umleitung von OSS-Akquisitionen auf unternehmensgesteuerte Ressourcen zum Akquirieren von Quellen für eine Abhängigkeit, um das Risiko von Upstream- oder Over-the-Wire-Angriffen zu minimieren.