25 gefährlichste Programmierfehler

Wahrscheinlich programmiert ihr genauso gern wie ich. Allerdings ist nicht alles, was auf den ersten Blick funktioniert, wirklich gute Software. Nicht umsonst benehmen sich Software-Tester oft besonders rüde, denn fehlerhafte Eingaben, überlange Strings, nicht initialisierte Variablen können unvorhersehbare Zustände hervorrufen – und diese sind nicht selten von großer wirtschaftlicher Bedeutung.

Das SANS Institute hat nun mal mehr als 30 Firmen befragt, die sich mit der Sicherheit von Software beschäftigen. Herausgekommen ist eine Top 25 der häufigsten Programmierfehler. Damit ihr euch nicht durch den riesigen Artikel wühlen müsst (es sei denn, ihr wollt das), habe ich die Liste hier kurz übersetzt und auf die Webentwicklung übertragen:

  1. Unsaubere / keine Input-Validierung: Eingaben müssen geprüft werden (und nicht nur Formulare sondern auch $_GET-Parameter), damit sie korrekt verarbeitet werden können.
  2. falsche Kodierung / kein Escapen bei der Ausgabe: fast genauso schlimm wie 1., denn dadurch werden vor allem XSS- und CSRF-Angriffe möglich.
  3. fehlendes Escaping bei SQL-Abfragen: jede Variable in einer SQL-Abfrage sollte vorher mit mysql_real_escape_string() behandelt werden, damit SQL Injections vermieden werden.
  4. XSS-Angriffe nochmal – habe ich bei 2. schon mit abgefrühstückt
  5. Validierung von Aufrufen von OS-Befehlen: wenn von Programm 1 ein anderes Programm aufgerufen wird, geschieht dies normalerweise auch mit den Rechten von Programm 1. Wer bei der Rechtevergabe sehr großzügig war und / oder den Aufruf über (ungeprüfte) Variablen parameterisiert, kann dem Betriebssystem und auch dem Server schnell Schaden zufügen.
  6. Klartext-Übertragung sensibler Informationen: Sollte man nicht tun, dafür gibts im WWW Dinge wie SSL und TLS. Aber es sei trotzdem darauf verwiesen, dass auch heute noch viele Klartextprotokolle im Einsatz sind. Ein Beispiel dafür ist FTP – immer, wenn ihr euch über normales FTP mit eurem Server verbindet, kann jedermann die Zugangsdaten mitlesen.
  7. CSRF nochmal – hatte ich ja auch bei 2. schon
  8. Race Conditions: wenn das Ergebnis einer Operation von mehreren Einzeloperationen, die (pseudo-)parallel ausgeführt werden, abhängig ist, besteht eine Wettbewerbssituation (engl. Race Condition). Fehler dieser Art sind sehr schwer zu beheben, da die Symptome manchmal auftreten und ein anderes Mal nicht. Gerade dieser Umstand macht sie so gefährlich.
  9. informationsreiche Fehlermeldungen: Wenn in einem Produktivsystem Fehlermeldungen zu viele Informationen enthalten, kann dies Hackern helfen, eure Architektur bzw. euer Script zu rekonstruieren und so auch auf Schwachstellen zu treffen. Während der Entwicklung ist ein Debug-Modus deshalb hilfreich, in der Produktion sollte er aber dringend deaktiviert werden. Überhaupt sollte einem Angreifer möglichst wenig verraten werden. Dazu zählt beispielsweise die eingesetzte Server-Software (Apache, PHP, MySQL), eingesetzte Verschlüsselungsverfahren usw. Je mehr ein Angreifer weiß, desto leichter ist ein Angriff. Wenn ein Angreifer eine liegen gelassene Seite mit dem Befehl phpinfo() findet, sollte man sich Sorgen machen.
  10. Buffer Overflow: Ein Speicherüberlauf geschieht dann, wenn für eine Variable weniger Speicher reserviert wurde, als ihr zugewiesener Inhalt benötigt. Das ist das Grundproblem von Anwendungen, die auf der Von-Neumann-Architektur basieren (da dort per Definition Variableninhalte und Befehle im gleichen Speicher sind – vgl. Harvard-Architektur)
  11. Speicherort für kritische Daten: sensible Daten sollten immer dort gespeichert werden, wo ein Angreifer möglichst schwer herankommt. Dies kann zum Beispiel ein Verzeichnis sein, das über dem htdocs-Verzeichnis des Apache liegt – also auf jeden Fall außerhalb des öffentlich zugänglichen Bereiches.
  12. parameterisierter Dateiname: Wenn eine Datei eingelesen wird und der Dateiname über eine Variable gesteuert wird, kann ein Angreifer diesen möglicherweise verändern. Noch schlimmer ist dies bei Schreiboperationen. Wenn der Dateiname einer Schreiboperation (neue Datei erstellen) anfällig ist, kann ein Angreifer leicht Tausende solcher Dateien erstellen – bis die Festplatte voll ist und erstmal gar nichts mehr geht.
  13. relativer, parameterisierter Verzeichnis-Pfad: wenn man eine Datei über einen relativen Pfad einliest und diesen Pfad mit einer Nutzereingabe parameterisiert, kann das dazu führen, dass der Nutzer zu jedem Pfad gelangen kann, wo er hin möchte (und die Rechte der Anwendung es nicht einschränken). Wenn man also so etwas hat:
    include($username."/datei.xyz");
    

    Wenn der Angreifer nun einen Weg findet, den Usernamen beispielsweise „../../“ zu nennen, ist er auf einmal ganz woanders. Hier spielt also auch die Input-Validierung wieder mit hinein.

  14. Dynamisch generierter Code: Aus Bequemlichkeit (SANS nennt es „weil es cool ist“) bauen manche Entwickler dynamisch generierten Code in ihre Anwendungen ein und führen ihn dann beispielsweise per eval() aus. Darüber freuen sich natürlich auch Angreifer, denn nun müssen sie nur noch versuchen den auszuführenden Code in ihrem Sinne zu verändern.
  15. Programme / Code downloaden ohne Integritätscheck: jeder Download, der besonders tolle Dinge verspricht, sollte geprüft werden – auf Viren sowieso, aber auch aber per Hash-Code der Datei. Dieser muss übereinstimmen mit dem vom Anbieter angegebenen Hash-Wert. Tut er dies nicht, wurde die Software verändert und ihr solltet die Finger davon lassen.
  16. unsauberes / fehlendes Freigeben von Ressourcen: wenn Ressourcen nicht mehr benötigt werden, sollten sie ordnungsgemäß wieder freigegeben werden. Dazu gehören Filehandles, Datenbank-Verbindungen, temporäre Variablen usw. Heutzutage kümmert sich meistens die Programmiersprache selbst darum (Garbage Collection), allerdings sollte man vorher prüfen, ob dem auch wirklich so ist.
  17. fehlende Initialisierung von Variablen: Ein großes Problem bei PHP-Anwendungen. Deshalb während der Entwicklung immer auch Fehler vom Typ E_NOTICE anzeigen lassen (in der Produktion dann natürlich nicht mehr – siehe Punkt 9).
  18. falsche Berechnungen: Berechnungsfehler können weitreichende Folgen haben. Die Ursachen sind oft Rundungsfehler, nicht selten durch die Wahl des falschen Datentyps. SANS zählt hierunter auch nicht abgefangene Division-durch-Null-Fehler und zu geringe Speicherreservierung. Blöd werden solche Fehler dann, wenn sie von Hackern ausgenutzt werden. Dann entstehen schon mal negative Preise oder es werden tausende Überweisungen hin und her getätigt, um Rundungsfehler auszunutzen.
  19. Unsaubere Rechtevergabe: Rechte sind eine tolle Sache, um ein System abzusichern. Allerdings müssen sie auch korrekt gesetzt und gepflegt werden! Ansonsten hilft das schönste Rechtekonzept nichts.
  20. Nutzen eines unsicheren Verschlüsselungsalgorithmus: Nunja, das fällt wohl eher in die Richtung hochsensibler Anwendungen wie Banken- oder Regierungssoftware. Wenn nachgewiesen wird, dass ein Algorithmus mit sonstwievielen Tausend Rechnern geknackt werden kann, braucht man sich wohl erst Sorgen machen, wenn man seeehr bekannt ist und es für die Angreifer auch einen Nutzen gibt. Lieschen Müllers Privatseite wird deswegen wohl nicht angegriffen. Allerdings sollte man es unbedingt vermeiden, einen eigenen Algorithmus zu nutzen, nur weil man den selbst nicht knacken kann. Moderne Kryptosysteme wurden jahrelang von Experten auf Schwachstellen durchleuchtet und gelten nur deshalb als sicher.
  21. Festes Passwort: Wer für alle User ein und dasselbe Passwort im Code fest verdrahtet, weil es ja aus Sonderzeichen und Zahlen besteht und jeder Wörterbuchattacke standhält, hat etwas falsch verstanden. Ein nicht wechselndes Passwort ist nicht viel besser als kein Passwort. Übrigens sollte man das auch beherzigen, wenn man mal Fremden Zugriff zum System gewährt hat – beispielsweise einem Programmierer seine FTP-Zugangsdaten gegeben hat. Man sollte nicht darauf vertrauen, dass er diese nach getaner Arbeit wieder vergisst…
  22. nochmal, dass sensible Programme und Dateien mit korrekten Rechten versehen werden sollten – sodass eben nicht irgendwelche Kontodaten von zig Tausend Leuten übers Web abgerufen werden können.
  23. Nutzung unbefriedigender Zufallszahlen: Zufallszahlengeneratoren im Computer sind nie wirklich zufällig, aber immerhin schaffen sie meist eine Gleichverteilung im gewählten Zahlenbereich. Sie dürfen also gern dazu genutzt werden, einen bestimmten Werbebanner zufällig zu rotieren. Für kritischere Dinge sollte man aber vorsichtig sein. Wenn dazu noch der Seed-Wert beeinflusst werden kann und somit eine Vorhersagbarkeit der nächsten Zufallszahl besteht, nutzt die schönste Zahl nix mehr.
  24. Berechtigungen pflegen: Es kann ja durchaus passieren, dass der Admin ein einziges Mal einem Programm mehr Rechte geben muss, um eine bestimmte Operation durchzuführen. Wichtig ist es dann, dass er nach getaner Arbeit diese Rechte auch wieder zurücksetzt. Wenn man sein Auto aufschließt, um damit zu fahren, muss man es nach der Fahrt ja auch wieder zuschließen…
  25. clientseitige Input-Validierung: Ein Problem vieler AJAX-Anwendungen ist es, dass die Validierung von Eingaben per JavaScript auf dem Clientsystem gemacht wird. Das ist sehr problematisch, denn wenn ein Angreifer den HTML-Code der Seite speichert, verändert (beispielsweise den Event-Handler onsubmit entfernt) und dann erneut die gewünschte Eingabe tätigt, wird sie diesmal an den Server gesendet. Validiert dieser nicht noch einmal, kann das böse ausgehen! Ich schreibe mir deshalb bei AJAX-Anwendungen immer eine Prüffunktion und rufe diese sowohl per AJAX auf als auch nochmal nach dem endgültigen Abschicken eines Formulars oder sonstigem.

So, ist ein schöner Roman geworden, aber ihr solltet die Dinge wirklich Schritt für Schritt mal durchgehen. Wen das Thema Sicherheit im Zusammenhang mit PHP noch mehr interessiert, dem empfehle ich das Buch PHP-Sicherheit: PHP/MySQL-Webanwendungen sicher programmieren (von dem ich damals leider nur die erste Auflage gekauft habe – also wer einem eifrigen Blogger mal etwas Gutes tun möchte…). Darin werden die häufigsten Security-Probleme von Webanwendungen analysiert und konkrete Empfehlungen zur Vermeidung dieser Sicherheitslecks gegeben.



Deprecated: Directive 'allow_url_include' is deprecated in Unknown on line 0