Dienstag, 15. Juni 2010


Topthema

Donnerstag, 2. Juni 2005 | Topthema

About Security #8: Vorbeugung — Pufferüberläufe verhindern

(Link zum Artikel: http://www.entwickler.de/entwicklerde/kolumnen/022002)

Wie Entwickler Pufferüberlaufschwachstellen in ihren Programmen verhindern können, erfahren Sie in dieser Folge.

N E U ! Security aktuell
Täglich aktuelle Security-Infos!

Ursache eines Pufferüberlaufs ist das ungeprüfte Kopieren von vom Benutzer gelieferten Daten in Puffer fester Größe. Um einen Pufferüberlauf zu verhindern, müssen also "nur" alle von außen kommenden Daten vor dem Schreiben auf ihre Größe geprüft werden. Und zwar wirklich alle Daten, unabhängig davon, wie sie an das Programm übergeben wurden. Nur die innerhalb des eigenen Programms geprüften Daten sind sicher.

Einige Beispiele:
  • Oft werden Eingaben in Webformulare bereits auf dem Client über JavaScript geprüft. Dadurch können zwar falsche Eingaben des Benutzers vor dem Absenden an den Server korrigiert werden, als Schutz vor unerwünschten Eingaben taugt diese Prüfung jedoch nicht. Ein Angreifer kann die Prüffunktion manipulieren oder die gewünschten Daten problemlos direkt an den Webserver senden.
  • Bei manchen Dateiformaten enthält ein Header Größeninformationen für die in der Datei gespeicherten Daten. Auch diesen darf nicht vertraut werden, da ein Angreifer sie manipuliert haben kann. Dabei ist es unerheblich, ob das Format öffentlich dokumentiert wurde oder eine Eigenentwicklung ist.
  • Daten, die vom Programm in eine Datenbank geschrieben wurden, darf beim Abfragen nicht vertraut werden. Ein Angreifer könnte diese Daten z.B. über SQL-Injection (siehe About Security #11 ff) manipuliert haben.
  • Auch Daten, die von einem anderen Programm stammen, darf nicht vertraut werden. Selbst dann nicht, wenn es sich um ein selbst geschriebenes, absolut vertrauenswürdiges Programm handelt. Ein Angreifer könnte die Daten z.B. durch einen Man-in-the-Middle-Angriff manipulieren oder das andere Programm durch eine eigene Version ersetzen.
  • Auch unverdächtige Daten wie z.B. Dateinamen können gefährlich sein. Dass die maximale Länge eines Dateinamens vom Betriebssystem vorgegeben ist, bedeutet nicht, dass ein Angreifer das Programm nicht mit einem überlangen Dateinamen als Parameter aufrufen kann.
  • Wird die Größe der zu lesenden Daten einem übergebenen Parameter entnommen, muss auf dessen Vorzeichen geachtet werden. Ein Angreifer könnte einen negativen Wert übergeben, der nach der Umwandlung in einen vorzeichenlosen Wert zu einem Pufferüberlauf führt.
Pufferüberläufe verhindern

Die erste Maßnahme besteht darin, keine Funktionen zu verwenden, die Daten ungeprüft kopieren. In einigen Sprachen, z.B. in Java, wird die Größe automatisch während der Laufzeit überprüft. In C sollte man z.B. beim Kopieren eines Strings statt der Funktion strcpy() die Funktion strncpy() verwenden. Während strcpy() alle übergebenen Daten an die Zieladresse kopiert und dabei bei einem zu kleinen Puffer einen Überlauf verursacht, kann bei strncpy() die Größe der zu kopierenden Daten angegeben werden. Alle weiteren Hinweise beziehen sich speziell auf C.

About Security: Die komplette Serie

Die nächste Möglichkeit besteht im Austausch gefährlicher Funktionen durch sichere Versionen. Diesen Ansatz verfolgt die Linux-Bibliothek Libsafe: Die gefährdeten Funktionen der Bibliothek libc werden durch Versionen ersetzt, die die Größe der kopierten Daten überwachen. Dadurch werden alle Programme, die diese Funktionen verwenden, ohne weitergehende Anpassung geschützt. Die aktuelle Version von Libsafe ist allerdings von 2002, und in der Zwischenzeit wurden Schwachstellen in der Bibliothek gefunden, z.B. im April 2005 eine Möglichkeit, die Schutzfunktion in bestimmten Fällen zu umgehen.

Eine weitere Möglichkeit besteht in der Modifikation des Compilers. StackGuard (PDF), ein Patch für den C-Compiler gcc, schützt die Rücksprungadresse. Unter der Rücksprungadresse wird ein Kontrollzeichen, genannt Canary, gespeichert. Dessen Wert wird vor dem Rücksprung aus der Funktion überprüft. Wurde es verändert, wird eine Warnmeldung ins Syslog geschrieben und das Programm beendet. Inzwischen wurde StackGuard durch das von IBM aus dessen Prinzipien weiterentwickelte ProPolice ersetzt. IBM nennt das Verfahren auch "GCC extension for protecting applications from stack-smashing attacks", kurz "stack-smashing protector (ssp)".

Für Linux gibt es auch die gcc-Erweiterung StackShield. Dabei wird bei jedem Funktionsaufruf die Rücksprungadresse am Anfang des Datensegments gesichert und vor dem Rücksprung mit der auf dem Stack gespeicherten Version verglichen. Stimmen die Adressen nicht überein, wird das Programm beendet oder die ursprüngliche Adresse restauriert. Der dazu notwendige Code wird am Anfang und Ende jedes Funktionsaufrufs eingefügt.

Am einfachsten lassen sich Pufferüberläufe bzw. allgemein Schwachstellen verhindern, wenn dies gleich beim Entwurf der Software berücksichtigt wird. Es besteht aber auch die Möglichkeit, später noch nach möglichen Schwachstellen zu suchen. Diese Audit-Verfahren sind 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!

Carsten Eilers

About Security – Übersicht zum aktuellen Thema "Eine typische Schwachstelle: Der Pufferüberlauf"

Kommentare

Folgende Links könnten Sie auch interessieren