Wie Entwickler Pufferüberlauf-Schwachstellen in ihren Programmen finden können, erfahren Sie in dieser und der nächsten Folge von About Security.
Wo suchen?
Bei der Suche nach Pufferüberlauf-Schwachstellen bzw. allgemein nach Schwachstellen gibt es zwei Möglichkeiten: Die Suche im Sourcecode und die Analyse der Binaries. Entwickler werden meist die Suche im Sourcecode vorziehen, da ihnen dieser ja vorliegt. Unter Umständen ist für sie aber auch eine Analyse der Binaries sinnvoll, z.B. wenn Schwachstellen in eingebundenen Bibliotheken vermutet werden.
N E U ! Security
aktuell
Täglich aktuelle Security-Infos!
Sourcecode Audit
Prinzipiell wird beim Sourcecode Audit der Sourcecode Zeile für Zeile nach verdächtigen Codestellen durchsucht. Wird nur nach Pufferüberlauf-Schwachstellen gesucht, werden erst alle Puffer fester Größe ermittelt und danach wird deren weitere Verarbeitung untersucht. Diese manuelle Suche ist zwar die aufwändigste Methode, aber auch die sicherste. Automatisierte Werkzeuge sind zwar beim Finden offensichtlicher Fehler sehr schnell, stoßen bei komplexen Problemen wie zusammengesetzten Schwachstellen aber an ihre Grenzen.
Für automatische Werkzeuge gibt es zwei Ansätze: Die syntaktische oder lexikalische und die semantische Analyse. Bei der syntaktischen Analyse wird nach potenziell gefährlichen Funktionen gesucht, während bei der semantischen Analyse der Datenfluss analysiert wird.
Syntaktische Analyse
Die einfachsten Hilfsmittel zur Suche nach gefährlichen Funktionsaufrufen sind die Suchfunktion des verwendeten Editors und das Tool grep. Da der Entwickler dabei nach jeder Funktion einzeln suchen muss, ist ihre Verwendung zur syntaktischen Analyse jedoch sehr mühsam. Sehr viel besser geeignet sind spezielle Programme wie z.B. flawfinder für C und C++ und RATS für C, C++, Perl, PHP und Python. Beide verwenden eine Datenbank mit potenziell gefährlichen Funktionen und geben zu den gefundenen Schwachstellen Hinweise zu möglichen Auswirkungen und Abhilfen.
Ein Beispiel
Test-Programm test.c
#include <string.h>
int main (int argc, char *argv[])
{
char puffer[8];
if (argc > 1)
strcpy (puffer, argv[1]);
return 0;
}
Ausgabe von flawfinder
ceilers flawfinder test.c
Flawfinder version 1.26, (C) 2001-2004 David A. Wheeler.
Number of dangerous functions in C/C++ ruleset: 158
Examining test.c
test.c:6: [4] (buffer) strcpy:
Does not check for buffer overflows when copying to destination.
Consider using strncpy or strlcpy (warning, strncpy is easily misused).
test.c:4: [2] (buffer) char:
Statically-sized arrays can be overflowed. Perform bounds checking,
use functions that limit length, or ensure that the size is larger than
the maximum possible length.
Hits = 2
[...]
Not every hit is necessarily a security vulnerability.
There may be other security vulnerabilities; review your code!
Da bei der syntaktischen Analyse auch alle Funktionsaufrufe ausgegeben werden, bei denen die Parameter vorher auf die korrekte Länge geprüft werden, gibt es viele Fehlalarme.
Semantische Analyse
Bei der semantischen Analyse wird der Datenfluss analysiert.
Dies ist ein
Teil des Kompiliervorgangs. Der gcc-Compiler gibt beispielsweise bei
Angabe
der Option -Wall auch Warnungen bei der
Verwendung unsicherer
Funktionen aus. Es gibt aber auch eigenständige Programme für die
semantische Analyse. Ein Beispiel für ein derartiges Tool ist
Splint.
Splint überprüft, ob bestimmte Annahmen, die als "Annotations" im
Sourcecode spezifiziert wurden, zutreffen. Die Annotations für die
Funktion strcpy(s1, s2) sehen z.B.
folgendermaßen aus:
void /*@alt char * @*/strcpy
(/*@unique@*/ /*@out@*/ /*@returned@*/ char *s1, char *s2)
/*@modifies *s1@*/
/*@requires maxSet(s1) >= maxRead(s2) @*/
/*@ensures maxRead(s1) == maxRead (s2) @*/;
Die requires-Klausel verlangt, dass der als s1
übergebene
Puffer groß genug sein muss, um s2 aufzunehmen. Die
ensure-Klausel legt fest, dass die Anzahl
gelesener Zeichen von
s1 und s2 nach dem Aufruf
gleich groß sein muss. In
Fällen, in denen die Größe von s2 unbekannt ist,
sollte die Funktion strncpy(s1, s2, n)
verwendet werden. Ihre
Annotations sehen folgendermaßen aus:
void /*@alt char * @*/ strncpy
(/*@unique@*/ /*@out@*/ /*@returned@*/ char *s1, char *s2, size_t n)
/*@modifies *s1@*/
/*@requires maxSet(s1) >= ( n - 1 ); @*/
/*@ensures maxRead (s2) >= maxRead(s1) /\ maxRead (s1) <= n;@*/;
Die requires-Klausel verlangt, dass der als s1 übergebene Puffer groß genug sein muss, um die Anzahl zu kopierender Zeichen aufzunehmen. Die ensure-Klausel legt fest, dass nach dem Aufruf maximal n Zeichen aus s1 nach s2 kopiert wurden.
Die Methoden der Sourcecode-Analyse reichen in den meisten Fällen aus, um Schwachstellen zu finden. Liegt der Sourcecode nicht vor, hilft nur eine Analyse der Binaries. Dies ist das Thema der nächsten Folge.
Wenn Sie Fragen oder Themenvorschläge haben, können Sie diese gerne an die angegebene E-Mail-Adresse senden oder im Security-Forum einbringen!
About Security – Übersicht zum aktuellen Thema "Eine typische Schwachstelle: Der Pufferüberlauf"
- About Security #5: Der Pufferüberlauf
- About Security #6: Ausnutzung von Pufferüberlauf-Schwachstellen
- About Security #7: Gegenwehr – Pufferüberläufe verhindern
- About Security #8: Vorbeugung – Pufferüberläufe verhindern
- About Security #9: Sourcecode-Audit – Pufferüberläufe finden
- About Security #10: Software-Audit – Schwachstellensuche in Binaries




















Kommentare