ITS-5.4
Transcription
ITS-5.4
5.4 Schwachstellenanalyse Typische Beispiele für Schwachstellen (vulnerabilities): Pufferüberlauf Skript-Manipulation (SQL-Injektion) ungeschützte kritische Abschnitte Bisweilen hilft Datenflussanalyse des verdächtigen Codes. ITS-5.4 1 5.4.1 Pufferüberlauf Das Problem (2.5): Unsichere Programmiersprachen (wie C, C++, ...) lassen zu, dass beim Beschreiben eines Feldes jenseits der Feldgrenzen geschrieben wird. Die Effekte solcher Programmfehler sind undefiniert - üblicherweise werden benachbarte Daten in Mitleidenschaft gezogen. ITS-5.4 2 Wenn Eingabedaten direkt oder indirekt in gefährdete Felder fließen, können Angreifer solche Programmfehler ausnutzen: mit gezielt gewählten Eingabedaten können Sicherheitsverletzungen bewirkt werden. Mehr als die Hälfte aller Sicherheitswarnungen des CERT betreffen Angriffe, die mit Pufferüberlauf arbeiten! Der Schaden: Gezieltes Einschleusen von Daten in andere Variable - oder gar Einschleusen von eigenem Code. Voraussetzung: Kenntnis des Codes (und des Übersetzers) (aber: security by obscurity ist keine Lösung!) ITS-5.4 3 Beachte: „Is it a bug or a feature?“ Die Schwachstelle kann ein unbeabsichtigter Qualitätsmangel sein (Mangel an Stabilität/Robustheit gegenüber falschen Eingaben), oder es handelt sich um eine absichtlich eingebaute Geheimtür (Hintereingang, backdoor). ITS-5.4 4 Die Lösung: am besten: nur sichere Programmiersprachen benutzen (Notbehelf: Keller-Manipulation entdecken: 2.6, so auch mit MS Visual C++ /GS *) am zweitbesten: Felder, insbesondere Zeichenketten, nur mit sicheren Bibliotheksfunktionen bearbeiten sonst: extreme Vorsicht, extensive Code Reviews, werkzeuggestützte Code-Analyse Literatur: M. Howard, D. LeBlanc: Writing Secure Code. Microsoft Press 2003 * Compiler option /GS: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vclrfGSBufferSecurity.asp ITS-5.4 5 5.4.1.1 Angriffs-Varianten gezielte Änderung einer benachbarten Variablen (zur Erinnerung: Aufgabe 2.2) Zerstörung der Keller-Organisation (Rücksprungadresse!) und damit Abschießen eines Servers ( denial of service) (2.6) gezielte Einschleusung von eigenem Code, der durch gezielte Manipulation der Rücksprungadresse im Keller aktiviert wird Mutation eines Servers oder SUID-Programms zum Schadprogramm ähnliches auf der Halde (erheblich schwieriger, kommt aber vor) ITS-5.4 6 5.4.1.2 Vorsicht beim Kopieren von Zeichenketten! (2.6) gets, fgets string, strcasecmp, strncasecmp, strcat, strncat, strlcat, strchr, strrchr, strcmp, strncmp, strcpy, strncpy, strlcpy, strcspn, strspn, strdup, strlen, strpbrk, strstr, strtok, strtok_r printf, fprintf, sprintf, snprintf (Windows:) StringCchCopy, StringCchCat, ... ITS-5.4 count characters (!) 7 Vorsicht mit Unicode-Zeichen: 1 Zeichen = 2 Bytes ! // WCHAR = wide character = Unicode character WCHAR src[] = "To be or not to be"; // 18 chars WCHAR dest[16]; // 32 bytes ... StringCchCopyW(dest,sizeof(dest),src); 32 ! kopiert maximal 32 Unicode-Zeichen, nicht nur 16 ! Merkregel: Makro verwenden #define Length(x) = sizeof(x)/sizeof(x[0]) ... StringCchCopyW(dest,Length(dest),src); ITS-5.4 8 5.4.1.3 Verwandtes Problem: printf ... bedingt durch drei Schwächen des Formatierers von C/C++ : printf("... %s ... %i ... %n ...", string, number, &count); speichere Anzahl bisher verarbeiteter Zeichen übernimm Zeichenkette bzw. Ganzzahl Variable Parameterliste ohne Längenüberprüfung ! printf greift ins Leere - d.h. irgendwo in den Keller - , wenn weniger Argumente als vom Formatierer gewünscht printf(string); ITS-5.4 ist erlaubt (Konsequenz von ) 9 printf("%s", text); ist in Ordnung printf(text); ist Schwachstelle! Vermeiden! (wenn char *text aus der Eingabe kommt) Strategie des Angreifers: statt Text einen langen Formatierer eingeben, der wie folgt konstruiert ist: an geeigneter Stelle ist ein %n enthalten an geeigneter Stelle ist die Adresse einer Zelle enthalten, auf die sich das %n beziehen soll vor dem %n wird mit hinreichend vielen % gesteuert, welcher Wert in diese Zelle gelangen soll Damit prinzipiell jede Umwandlung zum Schadprogramm möglich: ITS-5.4 10 Der Trick dabei: Der Formatierer wird von printf abgearbeitet; dabei wird für die vielen % auf den Keller zugegriffen und damit irgendwann auch auf den Formatierer selbst und damit werden Teile von ihm als Argumente interpretiert, und damit wird die Adresse für das %n untergeschoben: ..... %x %x angewandt auf ......... %x%x %x (ohne Leerzeichen) %x%n Ausgabe:...78257825 78256e25 Knifflig: ITS-5.4 %n \xC0\x2A\xF5\x01 \xC0\x2A\xF5\x01 ?*? richtig beginnen mit ..... , und Adresse i.a. an anderer Stelle plazieren (Bekannt - zunächst im Untergrund - seit den 90er Jahren) 11 5.4.1.4 Verwendung sicherer Bibliotheksfunktionen Typ string in der Standard Template Library von C++: #include <string> using namespace std; int main() { string s; ..... ähnlich dem String in Java (aber Werttyp, nicht Verweistyp) StringCchCopy, StringCchCat, ... sind etwas sicherer als gets, strcpy, ... ITS-5.4 12 5.4.1.5 Eingaben vollständig überprüfen! Spezifikation (!): Präzise spezifizieren, welche Eingaben erlaubt sind! Korrekte Implementierung: Alle nicht erlaubten Eingaben sofort zurückweisen! ITS-5.4 13 5.4.1.6 Werkzeuggestützte Code-Analyse Mustererkennung (etwas besser als mit grep strcpy) J. Viega et al.: ITS4: A Static Vulnerability Scanner for ... www.acsac.org/2000/papers/78.pdf [2000], www.cigital.com/its4 integer range constraints D. Wagner et al.: A First Step towards Automated Detection ... www.cs.berkeley.edu/~daw/papers/overruns-ndss00.pdf [2000] Erweiterung von LCLint: semantisch annotierte Bibliotheksfunktionen D. Larochelle et al.: Statically Detecting Likely Buffer Overflow ... www.cs.virginia.edu/~evans/usenix01-abstract.html [2001] Erweiterung des Übersetzers: Regelmenge zur Code-Prüfung K. Ashcraft et al.: Using Programmer-Written Compiler Extensions ... http://portal.acm.org/citation.cfm?id=830533 zur [2002] Beachte: ITS-5.4 Weder schließen diese Ansätze Fehlalarme aus noch entdecken sie alle Fehler ! 14 Artikel der Woche: D. Wagner et al.: A First Step towards Automated Detection of Buffer Overrun Vulnerabilities. Proc. 10. ACM Conf. on Computer and Communications Security, 2003 www.cs.berkeley.edu/~daw/papers/overruns-ndss00.pdf ITS-5.4 15 5.4.1.7 Testen kann eingesetzt werden, um Pufferüberläufe nachzuweisen Fuzzing: Programm wird mit Zufallseingaben bombardiert, je verrückter, desto besser. Reaktionen des Programms: kein Absturz Absturz, also Programmfehler sicherheitskritisch?! http://sourceforge.net/projects/sharefuzz http://www.cs.wisc.edu/~bart/fuzz/fuzz.html ITS-5.4 16 Gezieltere Vorgehensweise: E. Haugh, M. Bishop: Testing C Programs for Buffer Overflow Vulnerabilities http://seclab.cs.ucdavis.edu/papers/HaughBishopNDSS2003.ps Dynamische Variante der statischen Analyse von D. Wagner et al. Werkzeug STOBO (Systematic Testing of Buffer Overflows): char dst[256]; wird durch STOBO instrumentiert: char dst[256]; __STOBO_stack_buf(dst, sizeof(dst)); Damit wird die vereinbarte Puffergröße dynamisch in einer Tabelle festgehalten. ITS-5.4 17 Bei den Testläufen werden die Längen der jeweils beteiligten Puffer und Zeichenketten überprüft. Auch wenn die Testdaten keinen Pufferüberlauf verursachen, können eventuell mögliche Pufferüberläufe erkannt werden ... ... und es werden entsprechende Warnungen ausgegeben. Die entsprechenden Programmstellen sind dann zu prüfen. ITS-5.4 18 5.4.2 SQL-Injektion Allgemeines Szenario mit Skriptsprache: Programm kooperiert mit Interpretierer für eine Skriptsprache Die zu interpretierenden Skripte werden aus vordefinierten Teilen und Benutzereingaben zusammengesetzt Bei unzureichender Überprüfung der Eingaben können irreguläre Eingaben die Skripte zu Schadcode machen Beispiel: ITS-5.4 SQL ist eine Skriptsprache für Datenbanken, die vom Datenbanksystem interpretiert wird (4.4.2) 19 Beispiel: SQL in Java-Programm mit JDBC (java.sql): ( Statement ist Schnittstelle zu objektifizierter SQL-Abfrage) Statement s = connection.createStatement(); s.execute(“SELECT title FROM books WHERE author=‘Joyce’;”); ResultSet r = s.getResultSet(); String userid = getInput(); // from some input stream s.execute(“SELECT * FROM accounts WHERE user=‘” + userid + “’;”); gebräuchlich, aber riskant: ITS-5.4 20 Szenario: Normalbenutzer hat keine Rechte an accounts (4.4.2) setuid- oder Server-Prozess hat select-Recht an accounts* String userid = getInput(); // from some input stream s.execute(“SELECT * FROM accounts WHERE user=‘” + userid + “’;”); ResultSet r = s.getResultSet(); ..... // output results reguläre Eingabe z.B. “lohr” liefert eine Zeile der Tabelle irreguläre Eingabe z.B. “lohr’ OR ‘x’=‘x” injizierter SQL-Code WHERE user= ‘lohr’ OR ‘x’=‘x’; liefert Inhalt der gesamten Tabelle! ITS-5.4 * connection als DB-Verwalter hergestellt (Passwort!) 21 … und viel schlimmer: s.execute(“SELECT * FROM accounts WHERE user=‘” + userid + “’;”); mit folgender Eingabe für userid : “lohr’; DROP TABLE accounts; SELECT * FROM bla WHERE attr1=‘?” bewirkt SELECT * FROM accounts WHERE user=‘lohr’; DROP TABLE accounts; SELECT * FROM bla WHERE attr1=‘?’; und damit das Löschen der Tabelle accounts ! (Vor.: mehrfache SQL Statements werden unterstützt) ITS-5.4 22 … und viele andere Angriffe! Schutzmaßnahme: Parametrisierte SQL-Befehle verwenden, z.B. so in Java: PreparedStatement s = connection.prepareStatement( "SELECT * FROM accounts WHERE user = ?"); s.setString(1,userid); ResultSet r = s.executeQuery(); ITS-5.4 23 5.4.3 Vorsicht mit kritischen Abschnitten! Gefahr: Programmierer geht irrigerweise davon aus, dass während der Ausführung seines Programms keine Änderungen in der Umgebung stattfinden z.B. im Dateisystem. Angreifer nutzt dies aus. Szenario: Programm Angreifer prüfe Datei x ändere x bearbeite x ITS-5.4 24 if(!access(file,W_OK) ) { // write access ok // gap for attack is here int fd = open(file,O_WRONLY,0); write(fd,text,sizeof(text)); printf("written alright\n"); } else printf("no write access\n"); "TOCTOU" : time of check - time of use Wo könnte dieser Code stehen? In einem setuid-Programm von root, das in eine vom Aufrufer übergebene Datei schreibt. Um nicht aus Versehen in eine für den Aufrufer nicht schreibbare Datei zu schreiben - denn root kann überallhin schreiben! - wird zuvor geprüft, ob der Aufrufer das Schreibrecht hat (access legt die real UID zugrunde!). [! Professionell wäre, die EUID umzusetzen anstatt access zu verwenden!] ITS-5.4 25 Was macht der Angreifer? Er bringt es fertig, in der gefährdeten Lücke die Datei, die sich hinter file verbirgt, durch eine andere zu ersetzen, z.B. durch die Passwort-Datei - die dann überschrieben wird! $ ln -s myWritableFile link $ setuidprog link & ..... if(!access(file,W_OK) ) { $ rm link; ln -s /etc/passwd link // gap for attack int fd = open(file,O_WRONLY,0); Timing überlegen! Automatisiert wiederholt versuchen! (Mehr zum Thema z.B. Viega/McGraw: Building Secure Software) ITS-5.4 Und Garfinkel/Spafford S. 122 ?! 26