Unsicheren C-Code mit Valgrind erkennen und mit Snyk Code beheben
24. September 2024
0 Min. LesezeitC und C++ sind nach wie vor grundlegend für die Entwicklung kritischer Software. Diese Programmiersprachen kommen in einer Vielzahl von Systemen zum Einsatz – von eingebetteten Geräten bis hin zu Hochleistungsanwendungen in der Fertigung, der Betriebstechnik (OT) und der Industrie. Ihre Effizienz, die Kontrolle über Systemressourcen und ihre Leistungsfähigkeit machen sie für Entwicklerinnen und Entwickler unverzichtbar, die an geschäftskritischen Projekten arbeiten.
C und C++ sind besonders in Japan weit verbreitet, wo die Fertigungs- und Industriesektoren wichtige Wirtschaftsmotoren sind. Japanische Entwicklerinnen und Entwickler setzen auf diese Programmiersprachen, um robuste und effiziente Software zu entwickeln, die alles von Fahrzeugsystemen bis zur Fabrikautomatisierung unterstützt. Die Präzision und Zuverlässigkeit von C und C++ sind entscheidend, um die hohen Standards dieser Branchen einzuhalten.
Die Bedeutung von Code-Sicherheit in C und C++
C und C++ bieten zwar beispiellose Kontrolle und Leistung, stellen aber auch erhebliche Sicherheitsherausforderungen dar. Da integrierte Sicherheitsfunktionen wie die automatische Speicherverwaltung fehlen, sind diese Programmiersprachen anfällig für Schwachstellen wie Pufferüberläufe, Use-after-free und Speicherlecks. Diese Schwachstellen mögen zunächst harmlos und einfach erscheinen, können jedoch schwerwiegende Folgen haben – insbesondere in kritischer Software, bei der Zuverlässigkeit und Sicherheit oberste Priorität haben.
Anfälliger C-Code verursacht ein Speicherleck
Sehen wir uns ein Beispiel für anfälligen C-Code an, den Entwicklerinnen und Entwickler schreiben könnten und der eine Sicherheitslücke durch ein Speicherleck verursacht.
Hier sehen Sie unseren C-Programmcode. Erkennen Sie die Sicherheitslücke?
Die Datei program1.c enthält ein Beispiel für eine Schwachstelle bei der dynamischen Speicherzuweisung (MISRA Dir 4.12, MISRA Rule 21.3). Die Sicherheitslücke in der Funktion allocateMemory() besteht darin, dass sie mit malloc() Speicher reserviert, ihn aber nicht wieder freigibt. Dadurch entsteht ein Speicherleck. Dies lässt sich verhindern, indem Sie die MISRA-Richtlinien befolgen, die die dynamische Speicherzuweisung einschränken.
Das ist ein häufiger Fehler bei der C-Programmierung und kann dazu führen, dass Ihr Programm mit der Zeit immer mehr Speicher belegt. Irgendwann kann der Speicher ausgehen, sodass Ihr Programm abstürzt oder anderen Programmen auf Ihrem System kein Speicher mehr zur Verfügung steht.
Warum verwenden wir nicht einfach eine statische Speicherzuweisung wie int arr[10]? In manchen Situationen lässt sich Speicher nicht auf dem Stack zuweisen. Angenommen, Sie schreiben eine Funktion, die eine Datei in den Speicher einliest. Die Dateigröße ist erst zur Laufzeit bekannt, daher können Sie kein Array mit fester Größe verwenden. Stattdessen können Sie mit malloc genau die benötigte Speichermenge reservieren, sobald Sie die Dateigröße kennen.
Kompilieren Sie das Programm und führen Sie es anschließend aus:
Enthält das Programm ein Speicherleck? Wie können Sie es beheben?
C-Sicherheitslücken mit Valgrind finden
Valgrind ist ein leistungsstarkes Tool, mit dem Sie Speicherlecks in Ihrem Programm finden können. Wir können das Programm mit Valgrind ausführen und prüfen, ob Speicherlecks vorhanden sind.
Installieren Sie Valgrind auf Ihrem System. Wenn Sie ein Linux-basiertes System verwenden, können Sie es über den Paketmanager installieren. Hier ein Beispiel für ein Debian-basiertes System:
Hinweis: Wenn Sie macOS mit ARM-basierten Chips verwenden, wird Valgrind nicht unterstützt. Daher überspringen wir diesen Schritt und führen Valgrind in einem Docker-Container aus:
Starten Sie anschließend den Container und binden Sie das aktuelle Verzeichnis in das Verzeichnis /tmp des Containers ein:
Kompilieren Sie dann das Programm program1.c im Container:
Anschließend können wir das Programm mit Valgrind ausführen, um nach Speicherlecks zu suchen:
Anschließend sollte Valgrind eine Ausgabe mit dem Speicherleck anzeigen:
Valgrind ist ein großartiges Tool. Doch für die tägliche Arbeit in der C-Entwicklung ist dieser Workflow nicht skalierbar, da das vollständige Programm für die Analyse erst kompiliert und erstellt werden muss.
Mit Snyk Code können Sie diese Schwachstelle in Ihrer Codebasis erkennen, ohne den Code kompilieren zu müssen. Installieren Sie einfach die Erweiterung und öffnen Sie die Datei – schon wird die Schwachstelle angezeigt. Snyk Code ist ein Tool zur statischen Codeanalyse, das Machine-Learning-Techniken einsetzt, um statischen Code zu untersuchen, ohne dass dafür ein Build- und Kompilierungsschritt erforderlich ist. So erhalten Sie schnelles und zuverlässiges Feedback mit wenigen falsch positiven Ergebnissen, wenn Snyk Ihren Code auf Sicherheitslücken untersucht.

Path Traversal, Pufferüberläufe und weitere C-Schwachstellen erkennen
Die SAST-Engine hinter Snyk Code erkennt mehr Schwachstellentypen als nur Speicherlecks durch malloc.
Sehen wir uns ein komplexeres Beispiel an, das mehrere unsichere Programmierpraktiken in C vereint und Sicherheitslücken verursacht:
Das obige C-Programm ist voller Schwachstellen. Es ist jedoch ein sehr knappes und vereinfachtes Beispiel für unsicheren Code, das vor allem der Kürze halber dient. Einige der subtileren Programmierpraktiken könnten dennoch leicht in realen Codebasen auftauchen.
Nach der Kompilierung können Sie das Programm ausführen:
Wenn sich im selben Verzeichnis eine Datei namens text.txt befindet und sie nicht leer ist, liest das Programm die Datei ein und gibt ihren Inhalt aus.
Zum Beispiel:
Sieht gut aus. Was passiert, wenn Sie eine Datei übergeben, die die Verzeichnisstruktur durchläuft?
Das Programm weist eine Path-Traversal-Schwachstelle auf, die Angreifenden das Lesen vertraulicher Dateien auf dem System ermöglicht.
Um weitere Schwachstellen zu testen, versuchen Sie Folgendes:
Übergeben Sie eine Datei, die nicht existiert
Übergeben Sie eine leere Datei
Übergeben Sie einen Dateinamen oder vollständigen Pfad, der zu lang ist (mehr als 50 Zeichen)
Einige dieser Sicherheitsprobleme gehen weit über die C-Kenntnisse von Entwicklerinnen und Entwicklern hinaus. Path Traversal erfordert beispielsweise mehr Bewusstsein für Anwendungssicherheit als für sichere Speicherverwaltung und fundierte C-Entwicklung.
Zum Glück analysiert die Snyk-Erweiterung den C-Code auf unsichere Programmierkonventionen und häufige Probleme der Anwendungssicherheit, sobald Sie den Programmcode in die IDE einfügen. Sie meldet diese schnell und zeigt den jeweiligen Codekontext direkt inline an:

Schützen Sie Ihren C- und C++-Code mit Snyk
Ein Sicherheitsvorfall in der Fertigungs- und Industriebranche kann katastrophale Folgen haben – darunter Betriebsunterbrechungen, Sicherheitsrisiken und finanzielle Verluste. Die Sicherheit von C- und C++-Code zu gewährleisten, ist nicht nur eine Best Practice, sondern notwendig. Snyk unterstützt Entwicklerinnen und Entwickler dabei, Schwachstellen früh im Entwicklungsprozess zu erkennen und zu beheben.
Sichern Sie Ihren Code mit modernsten Erkenntnissen
Lernen Sie in nur 30 Minuten das gesamte Funktionsspektrum von Snyk Code SAST kennen.
