Blog

Injections und XSS

08 Apr 21:01 - - in Sicherheit, Tutorials - 2 Kommentare

Ein Banner mit der Aufschrift Sicherheit

In letzter Zeit sind mir auf meinem Weg durchs WorldWideWeb wieder viele Internetseiten aufgefallen, die größere Sicherheitslücken aufweisen. Das hat mich dazu gebracht nun diesen Artikel zu schreiben, um euch zu helfen solche Sicherheitslücken zu vermeiden.

Der Artikel gehört mit 1200 Wörtern zwar zu der längeren Sorte, doch hoffe ich damit alle Informationen, die wichtig für euch sind, erfasst zu haben. Viel Spaß beim Lesen!

Sicherheitslücken?

Eine Sicherheitslücke ist alles, was einem Benutzer ermöglicht, die Internetseite anders zu benutzen als vorgesehen und damit möglichen Schaden zu verursachen. Dazu gehört unter Anderem das Erlangen von geheimen Daten, das nicht gewünschte Manipulieren des Seiteninhalts und das unerwünschte Umleiten andere Besucher (zum Beispiel auf seine eigene Seite).

Verschiedene Arten von Sicherheitslücken

Man kann zwischen server- und clientseitigen Sicherheitslücken unterscheiden, doch ich konzentriere mich in diesem Artikel nur auf die serverseitgen Lücken.

Diese lassen sich in vier Kategorien unterteilen:

Sql-Injections

Der Benutzer kann sich direkten Zugriff auf die Datenbank verschaffen, weil seine Eingaben ohne vorherige Kontrolle direkt an die Datenbank geschickt werden. Damit kann er zum Beispiel die Benutzer-Tabelle inklusive aller Passwörter auslesen.

Cross-Site-Scripting

Eine Benutzereingabe wird direkt wieder auf die Internetseite geschrieben, ohne dass sie vorher auf vom Browser interpretierte Syntax(html, js, css) geprüft wird. Damit hat der Benutzer direkten Zugriff auf den HTML-Code der Page und kann zum Beispiel Javascript auf der Internetseite platzieren.

System-Injections

Benutzereingaben werden direkt in Funktionen auf Systemebene verwendet. Ein Beispiel dafür ist, wenn aus der Benutzereingabe ein Pfad zu einer anzuzeigenden Datei gebastelt wird. Mit einer gezielten Eingabe ist es dem Benutzer möglich jede auf der Festplatte befindliche Datei anzuzeigen.

Header-Injections

Benutzereingaben werden ohne vorherige Kontrolle in den Antwort-Header der Internetseite geschrieben. Dem Benutzer ist es also Möglichen den Header zu manipulieren. Damit kann er z.B. eine Weiterleitung einbauen oder in E-Mail-Headern weitere Empfänger hinzufügen und damit eure Internetseite als Mailverteiler für Werbung benutzen.

Benutzereingaben

Um sich zu verteidigen muss man seinen Feind gut kennen. Wir kennen jetzt schon mal alle Angriffsmöglichkeiten. Als nächstes müssen wir alle Stellen lokalisieren an denen der Benutzer die Möglichkeit hat eigene Eingaben zu tätigen, um eben dort die Eingabewerte zu kontrollieren.

Post- und Get-Daten

Der Benutzer hat die Möglichkeit über das Senden von Formularen oder das Manipulieren der URL Daten an die Internetanwendung zu übergeben.

Cookies

Da die Cookies auf dem Computer des Benutzers gespeichert werden hat er die Möglichkeit sie zu verändern und damit auch die Möglichkeit gezielt manipulierte Daten an den Web-Server zu schicken.

Andere Header-Informationen

Wenn eine Anfrage an den Webserver gestellt wird, werden in dem Header noch weitere Informationen mitgesendet, wie der Name des Browsers oder die IP-Adresse. Da alle diese von dem Computer des Benutzers stammen, ist er auch hier in der Lage zu manipulieren und falsche Informationen zu senden. Die Möglichkeit wird leider oft vergessen und ermöglicht damit in z.B. Besucherzählern die Möglichkeit der SQL-Injection, weil IP-Adresse ohne kontrolliert zu werden an die Datenbank geschickt werden.

Benutzereingaben ihrem Weg durch die Applikation

In folgender Grafik seht ihr typische Wege, auf denen Benutzereingaben verarbeitet werden. Dabei ist markiert wo Sicherheitslücken entstehen können:

Eine Schema, das den Weg von Benutzereingaben durch die Internetanwendung darstellt

Natürlich lassen sich die Wege auch anders kombinieren, zum Beispiel ein System-Befehl der mit Daten aus der Datenbank ausgeführt wird. Wichtig ist einfach, ob die Daten ursprünglich von einem Benutzer kommen oder nicht.
Eine Sicherheitslücke besteht dann, wenn eine Benutzereingabe mit einem Befehl, z.B. einem SQL-Query kombiniert wird und damit selbst zu einem Befehl wird, ohne vorher auf seine Schädlichkeit kontrolliert zu werden.

Möglichkeiten der Kontrolle

Die Benutzereingaben müssen also Kontrolliert werden. Die Möglichkeiten dazu lassen sich wieder in zwei verschieden Kategorien einordnen:

Blacklisting

Hierbei werden die Benutzereingaben mit einer Liste von nicht erlaubten Eingaben kontrolliert. Alles was auf der Blacklist steht darf nicht in der Benutzereingabe vorkommen.

Whitelisting

Die Benutzereingaben werden hier nicht nach verbotenen Sachen durchsucht, sondern nach erlaubten. Eine Eingabe darf nur aus erlaubten Teilen bestehen.

Die Whitelisting-Methode ist um weites sicherer als das Blacklisting, weil nicht die Gefahr besteht, beim Erstellen der Blacklist etwas zu vergessen.

Optimist oder Pessimist?

Es gibt bei der Prüfung der Eingabe wieder zwei Möglichkeiten zu verfahren: Entweder man gibt einen Fehler aus, sobald eine Eingabe nicht erlaubt ist (pessimistisch) oder man korrigiert die Eingabe und benutzt die korrigierte Version um damit weiterzuarbeiten(optimistisch).

Wenn also ein Benutzer HTML-Code in ein Gästebuch schreibt:

<div>blub

kann man entweder dem Benutzer einen Fehler anzeigen, dass seine Eingabe nicht erlaubt ist:

Ein Fehler ist aufgetreten: HTML-Code ist hier nicht erlaubt

Oder man kann den HTML-Code in normalen Text umwandeln, indem man die spitzen Klammern “escaped“ oder auf Deutsch „maskiert“, sodass sie nicht mehr interpretiert werden.
Dann steht später im Gästebuch einfach:

<div>blub

genau wie der Benutzer es geschrieben hat.

Wie maskiert man eine Eingabe?

SQL-Injections

Wenn eine Eingabe des Benutzers zusammen mit einem SQL-Befehl an die Datenbank geschickt wird, müssen in der Eingabe unter Anderem alle Anführungszeichen und Semikolons maskiert werden, weil die zum SQL-Syntax-Repertoire gehören und von der Datenbank interpretiert werden.
In Php gibt es hierfür die Funktion mysql_real_escape_string($string)

Cross Site Scripting (XSS)

Wenn Benutzereingaben in den Quelltext der Seite geschrieben werden, müssen vorher alle spitzen Klammern, Anführungszeichen und geschwungenen Klammern maskiert werden, damit der Browser die Eingabe nicht als HTML oder Javascript interpretiert. Dafür gibt es in Php die Funktion htmlentities($string, ENT_QUOTES).

Header-Injections

In Headern werden Zeilenumbrüche benutzt um Daten voneinander zu trennen. Also müssen alle Zeilenumbrüche aus der Benutzereingabe gefiltert werden bevor sie in den Header geschrieben werden. Dafür kann man die Php-Funktion preg_replace($pattern,$replace,$string) und einem passenden regulären Ausdruck machen.
Eine weitere Sicherheitsmaßnahme ist es, die Benutzereingabe auch noch als URI zu codieren. In Php gibt dafür die Funktion urlencode($string).

System-Injections

Für System-Injections gibt es kein allzweck Prüfverfahren. Hier muss von Fall zu Fall entschieden werden, was für eine Prüfung notwendig ist.

Wann in der Anwendung sollen die Daten geprüft werden?

Wenn man sich die obere Grafik nochmal anschaut, kann man natürlich auf die geniale Idee kommen, einfach alle Benutzereingaben ganz zu Anfang, also bei der Entgegennahme zu prüfen, zu filtern und zu maskieren. Damit wäre man tatsächlich sehr sicher vor Angriffen. Es gibt in Php sogar eine Option namens „MagicQuotes“, die genau das zumindest zum Schutz vor SQL-Injections übernimmt, wenn sie aktiviert ist.
Doch die Sache hat einen Haken: Eine bereits maskierte Eingabe lässt sich nicht so gut handhaben und nicht so gut für mehrere verschiedene Zwecke benutzen.

Um die Anführungszeichen in einer Eingabe zu maskieren wird zum Beispiel ein Backslash vor jedes Anführungszeichen gesetzt. Dadurch wird aber auch die Anzahl der Zeichen erhöht. Das ist nicht praktisch, wenn man vor dem Speichern in die Datenbank mit der Eingabe noch andere Dinge anstellen möchte.

Wir wollen Testen ob der Benutzername mindestens 4 Zeichen lang ist, MagicQuotes ist aktiviert:

$benutzername = $_POST['name'];
if(strlen($benutzername) > 4) { echo „alles ok“; }

Wenn der Benutzer jetzt aber nur zwei Anführungszeichen als Namen eingibt, wird auch „alles ok“ gemeldet, weil von der Maskierung vor jedes Anführungszeichen noch ein Backslash gesetzt wurde.

Aus diesem Grund gilt die Regel:
Gefährlich Eingaben erst unmittelbar vor der „Gefahrenzone“ maskieren, um sie vorher so flexibel wie möglich zu halten.

Man muss seine Eintrittskarte fürs Kino ja auch erst beim betreten des Kinos vorzeigen und noch nicht, wenn man vor dem Kino noch auf Freunde wartet.

Ich hoffe ihr habt hiermit einen guten Überblick über die gängigen Sicherheitslücken auf Internetseiten bekommen, um in der Lage zu sein, sie bei euren Internetseiten gar nicht erst entstehen zu lassen. Wie genau man die Benutzereingaben absichert hängt letztendlich von der Anwendungsstruktur im Einzelfall ab, aber ihr solltet euch merken:

  1. Vor jedem SQL-Query die dafür benutzten Daten, welche vom Benutzer kommen, maskieren.
  2. Vor jeder Ausgabe von Benutzereingaben HTML und Javascript aus ihnen entfernen.
  3. Vor jedem Senden von Headern und/oder E-Mails überprüfen, ob Benutzereingaben direkt verwendet werden und gegebenenfalls maskieren.
  4. Bei jeder anderen Verwendung der Benutzereingaben überlegen, ob der Benutzer durch gezielte Falscheingabe etwas von euch nicht erwünschtes erreichen kann.

Kommentare

FeedDiskussion abonnieren: RSS | Atom

1. egli

09 Apr 06:20

Sehr gut erklärt etc. bin vollkommen mit dir einverstanden. Super Tut. :)

2. Lennart

13 Apr 18:47

Jaja, ein wunderbarer Seitenhieb… aber gut, er ist ja berechtigt. Schon besser mit Websitebau etwas Erfahrung zu haben um sowas zu programmieren…
Dein Designvorschlag finde ich übrigends sehr gut, hast du den nur als jpg oder auch noch anders?

Lennart

Kommentar schreiben

Alle Felder mit dem Stern(*) müssen ausgefüllt werden.

(Nicht Ausfüllen! Dieses Feld dient nur dem Schutz gegen Bots.)

*

*

(Mit http://)

*