Häufige Sicherheitsprobleme im Web

Exzellenter Artikel
6 | 13 Kommentare | 4129 Aufrufe
Sie können diese Wikiseite nach der Anmeldung auf Webmasterpro bearbeiten. Helfen Sie mit und verbessern Sie "Häufige Sicherheitsprobleme im Web" mit Ihrem Wissen!

Anzeige Hier werben

Durch schlechte Praktiken in der Programmierung von Webapplikationen entstehen in diesen oft Sicherheitslücken, welche sich durch Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), SQL-Injection oder umgehen von Formularvalidierungen ausnutzen lassen. In diesem Artikel sollen gängige Sicherheitsprobleme heutiger Webapplikationen vorgestellt werden. Wir zeigen wie solche Attacken funktionieren, zeigen Beispiele auf, und geben Lösungsansätze für Programmierer, Serveradministratoren und Benutzer.

Cross-Site Scripting (XSS)

Funktionsweise

Beim Cross-Site Scripting wird in andere Webseiten meist JavaScript injiziert. Das ermöglicht es dem Angreifer, JavaScript-Applikationen im Kontext der ungesicherten Seite auszuführen. So kann er Daten manipulieren oder unbefugt auslesen um z.B. Passwörter zu ändern oder zu stehlen, Benutzer irreführen und falsche Tatsachen darstellen, Benutzer auf andere Seiten weiterleiten oder auch Browserbugs ausnutzen die sich durch den falschen Kontext ergeben.

Lösungsansätze

Um sich gegen Cross-Site Scripting zu schützen, muss dafür gesorgt werden, dass von Usern generierten Input nicht dafür verwendet werden kann gefährliche Tags (wie zum Beispiel der script-Tag) in eine Seite einschleusen können. Das lässt sich in verschiedenen serverseitigen Sprachen auf verschiedenen Arten lösen. Einerseits stellen verschiedene Frameworks oft bereits vorgefertige Implementationen von XSS-Filtern oder BBCode-Parsern, welche dazu verwendet werden können mit Input von Benutzern umzugehen. Andererseits kann man auch Funktionen (wie z.B. in PHP htmlspecialchars) verwenden, um direkt Spezialzeichen rauszufiltern. Für eine genauere Beschreibung des Problems mit Beispielen und Lösungsansätzen für PHP, siehe den Artikel PHP-Sicherheit: Cross-Site Scripting. Python-Programmierer können entweder die Funktion escape() vom cgi-Paket verwenden oder mithilfe des Pakets htmlentitydefs ihren eigenen Filter bauen.

Cross-Site Request Forgery (CSRF)

Funktionsweise

Cross-Site Request Forgery (kurz CSRF, sprich C-Surf) ist im wesentlichen dem Cross-Site Scripting sehr ähnlich. Allerdings werden keine Skripte ausgeführt, sondern nur von Seite zu Seite unbefugt Befehle verschickt. Der Angriff ist also nur dafür gut, Daten zu manipulieren, aber nicht auszulesen. Im Gegenzug dafür kann CSRF kaum (meist gar nicht) verfolgt und nur schwer verhindert werden.

Einige Beispiele

 
HTML
1
<img src="http://192.168.1.1/changedns?s1=evildns&s2=evildns"/>

In diesem Fall würde, sollte der obere Codeschnipsel in einer Seite eingebettet werden, der lokale Router aufgerufen werden. Ist der User zufällig in seinem Router eingeloggt, erhält die Funktion changedns auf dem Router als Parameter den neuen DNS-Server evildns. Der Benutzer merkt davon nichts - für ihn erscheint auf der Seite einfach irgendwo ein kaputtes Bild und er wird annehmen dass es nicht gefunden wurde. Ist der Angriff erfolgreich, kontrollieren wir den DNS-Server des lokalen Routers und können somit den unwissenden Nutzer überall hinleiten wo wir wollen. Natürlich haben nicht alle Router dieses Problem, trotzdem zeigt das Beispiel sehr schön was passieren kann wenn man in einer Webapplikation nicht an solche Probleme denkt - vorallem auch, weil der Router eines Netzwerks nur vom Netzwerk selbst aus erreichbar ist!

 
HTML
1
<img src="http://de.wikipedia.org/w/index.php?title=Spezial:Userlogout"/>

In einem anderen Beispiel können wir einen eingeloggten Benutzer der deutschen Wikipedia automatisch ausloggen. Das sind allerdings nicht nur die einzigen Möglichkeiten die wir in einem solchen Fall haben - ein cleverer Angreifer könnte auch Passwörter oder E-Mail-Adressen ändern, Änderungen an Artikeln vornehmen, oder auch noch vieles andere. Die Möglichkeiten sind ohne Schutz im Grunde unbeschränkt.

Lösungsansätze

Das Problem lässt sich beheben (zumindest teilweise), in dem man entweder direkt mit SessionIDs oder zufällig generierten Tokens arbeitet. Cross-Site Request Forgery funktioniert im Grunde nur, wenn der Angreifer das Request dass an den Server gesendet wird vorhersagen kann. Fügt man nun aber in seiner Webapplikation in einem Formular ein verstecktes Feld mit der SessionID ein und akzeptiert die gesendeten Daten nur wenn diese auch mit der aktuellen SessionID übereinstimmt, muss der Angreifer zuerst die SessionID seines Opfers kennen um einen erfolgreichen Angriff durchzuführen. Das Ganze kann noch verbessert werden in dem man seperate, zufällig generierte Tokens in Formularen verwendet. Es muss einfach so schwierig wie möglich sein, für den Angreifer ein solches Request erraten zu können. Man kann aber sagen, dass es nie voll unmöglich sein wird CSRF zu verhindern, denn auch z.B. die SessionID kann unter gewissen Umständen von einem Angreifer in Erfahrung gebracht werden. Allerdings hat ein Client unter solchen Umständen wohl bereits grössere Probleme als durch eine erfolgreiche CSRF-Attacke verursacht werden könnten.

SQL-Injection

Funktionsweise

Durch SQL-Injection lassen sich in einer angreifbaren Webapplikation SQL-Querys modifizieren, wodurch es (je nach Umstand) möglich wird Daten entweder zu manipulieren oder einfach auszulesen. Ein Angriff über eine SQL-Injection kann nur funktionieren wenn von einem Benutzer eingegebene Daten direkt in einen Querystring eingefügt werden, ohne dass man vorher überprüft ob in den Daten des Benutzers spezielle Zeichen oder Keywords vorkommen.

Ein Beispiel

Nehmen wir an, in einer Webapplikation (geschrieben in PHP) verwenden wir folgenden Code um die Login-Daten eines Users zu verifizieren:

 
PHP
1
2
3
4
5
6
$user = $_POST['user'];
$pass = $_POST['pass'];

$r = mysql_num_rows(mysql_query("SELECT * WHERE user = '$user' AND pass = '$pass'"));

if($r > 0) echo "Login successful";

Auch wenn das Codebeispiel zugegebenermassen sehr einfach ist, zeigt es doch schön eines der grössten Probleme meister Webapplikationen: Ungefilterter Userinput. Solange Benutzer korrekt ihre Daten eingeben, ensteht zwar kein Problem. Übergibt aber ein Benutzer den String a' OR 'a' = 'a als Usernamen und Password, kann er sich unbefugten Zugriff verschaffen. Doch wie funktioniert es? Nun, setzen wir die Daten in den Querystring ein und analysieren das Ergebnis:

SELECT * WHERE user = 'a' OR 'a' = 'a' AND pass = 'a' OR 'a' = 'a'

Wir haben es geschafft, den Querystring so umzuschreiben, dass aus der Datenbank schlicht alle Reihen ausgelesen werden. Denn die jeweils zweite Kondition, dass a gleich a sein muss, bleibt bei jeder Reihe der Datenbank wahr. Folglicherweise wird in unserem Codebeispiel mysql_num_rows auch einen Wert grösser als 0 liefern. Auch wenn das Beispiel sehr simpel ist lässt sich die Logik dahinter auf jeden anderen Code ausweiten, wenn der Userinput nicht gefiltert wird.

Lösungsansätze

Um das Problem aus der Welt zu schaffen, müssen alle von einem Benutzer eingegebenen Daten die in einem Query verwendet werden, gefiltert werden. Das lässt sich heutzutage glücklicherweise relativ einfach lösen. So kann man in PHP einfach die Funktion mysql_real_escape_string() (oder andere, für die jeweilige Datenbank) verwenden, um einen String zu filtern bevor man ihn in einem Query verwendet. In Python kann man einfach über die Standard Datenbank-API ein Cursor-Objekt Querys ausführen lassen:

 
Python
1
cursor.execute("SELECT * WHERE user = '%s' AND password = '%s'", (user, password))

Man übergibt dem Cursor-Objekt als erstes Argument einen Querystring mit Platzhaltern (im printf-Format), und die Werte für diese Platzhalter als zweites Argument in einem Tupel. Python wird automatisch die im Tupel übergebenen Daten korrekt überprüfen bevor das Query ausgeführt wird.

Formularvalidierungsprobleme

Funktionsweise

Die Funktionsweise ist simpel: Findet die Validierung der Formulardaten im Client statt, kann er diese umgehen. Will man beispielsweise in einem Online-Shop verhindern dass ein Kunde eine negative Anzahl von Produkten bestellt, geschieht dies heute oft über JavaScript. Das Problem bei diesem Ansatz ist aber, dass ein Client ohne Probleme dieses JavaScript modifizieren oder umgehen kann um dem Server dann trotzdem eine negative Variable schicken kann.

Lösungsansätze

Die Validierung von Formularen über JavaScript kann zwar nützlich sein, da sie oft schneller ist und die Seite nicht neu geladen werden muss, allerdings ist sie kein Ersatz für eine erneute Validierung der Daten auf der Seite des Servers. Sind die Daten nicht serverseitig validiert worden, kann man davon ausgehen dass sie überhaupt nicht validiert wurden.

Andere Schutzmöglichkeiten

Schutz auf dem Server

Es gibt verschiedene Möglichkeiten, sich gegen die oben genannten Probleme serverseitig abzusichern. Die wohl bekannteste Methode in diesem Bereich dürften die Magic quotes in PHP sein, welche versucht hatten SQL-Injection zu verhindern. Die Methode verändert jedoch ohne Zutun des Autors die Daten und ist ständiger Kritik ausgesetzt. Dies führte dazu, dass Magic quotes in der kommenden Version PHP 6 entfernt wird. Ein anderer Ansatz versucht auch, mithilfe des Mod_rewrite Moduls in Apache verdächtige Requests abzublocken. Siehe dazu zum Beispiel The Hacker Webzine: My Webapplication Firewall Tutorial. Auch interessant dürfte Modsecurity für Apache sein.

Schutz im Client

Es gibt auch als Benutzer Möglichkeiten sich gegen solche Angriffe zu schützen. Die bekannteste dürfte wohl die NoScript-Extension für den Firefox-Browser sein, welche Mögliche XSS-Attacken direkt im Browser verhindert. Gegen das oben genannte Beispiel mit den DNS-Server im Router kann man sich zum Beispiel schützen, in dem man auf dem Computer direkt die DNS-Server seines Providers angibt und den Router überspringt (sollte der Router auch tatsächlich ein solches Problem haben).


Wikiseite bearbeiten

Diese Seite kann von jedem registrierten Benutzer bearbeitet werden. Bisher haben 4 Personen an der Seite "Häufige Sicherheitsprobleme im Web" mitgewirkt.

Sie haben einen Fehler entdeckt oder möchten etwas ergänzen? Dann können Sie nach der Anmeldung "Häufige Sicherheitsprobleme im Web" hier bearbeiten.

Mitarbeiter
  • Ich bin ein Informatik-Student aus der Schweiz. Meine Interessen liegen hauptsächlich in den Bereichen Sicherheit, Entwicklung und Serververwaltung.
  • Student der Biochemie und seit einigen Jahren im Hobby-Entwicklerbereich tätig. Stärken in XHTML/CSS und PHP, alles was mit Grafik zu tun hat, gehört nicht dazu.
  • Meine Schwerpunkte liegen im Bereich Grafikdesign, SEO und Management. Seit sieben Jahren bin ich als Geschäftsführer der Team23 GbR tätig, die Webdesign in Augsburg anbietet, sowie Webmasterpro.de betreut.
  • hat keine Beschreibung angegeben. Eine Beschreibung kann man unter dem Punkt "Profil bearbeiten" im Kontrollzentrum eintragen.

Kommentare: Häufige Sicherheitsprobleme im Web

Neuen Kommentar schreiben
CSRF
Beantworten

Kann man das Problem nicht auch mit htmlspecialchars() bei php lösen?

Verstehe leider nicht ganz, wie das durch sessions gelöst werden kann.

Denn der Code ist auf der Seite ja weiterhin vorhanden und wird ausgeführt, egal welche Session ein User halt.

Also meiner Sicht aus funktionierts ja ähnlich wie XSS und müsste durch diese oben genannte Funktion gelöst werden können, oder irre ich mich da?

Danke schonmal,

Ninos :)

Ninos Ego am 02.10.2010 um 22:22
gängig
Beantworten

klingt total komisch irgendwie.. als wäre das alltäglich und was positives

häufige würde eher passen soll ichs ändern?

meggs am 31.07.2008 um 21:07
Re: gängig
Beantworten

Finde häufig auch besser. Aber vielleicht kann man auch noch einen besseren Titel finden...

Thomas H am 01.08.2008 um 10:04
Re: gängig
Beantworten

Naja, es ist alltäglich. Leider.

Cedric Staub am 31.07.2008 um 21:14
Re: gängig
Beantworten

trotzdem klingt total seltsam

meggs am 31.07.2008 um 21:16
Magic Quotes Diskussion?
Beantworten

Mich würde ein Link zu diesem Thema sehr interessieren. Mir war nicht bekannt dass es damit sonderliche Probleme geben kann. Danke für den Artikel.

Benutzer gelöscht am 21.07.2008 um 11:07
Re: Magic Quotes Diskussion?
Beantworten

Das Problem ist halt, dass dir PHP ohne dein Zutun da die Slashes reinsetzt. Wenn man hier nicht auf die Serverkonfiguration im Skript achtet, kann das dazu führen, dass die Daten nicht mehr stimmen und so weiter. Um die Ausgangsdaten zu erhalten, muss man also erstmal wieder mit stripslashes, aber auch nur, wenn magic quotes an ist und alles nur um wieder die Ausgangsdaten zu erhalten. Die Konfiguration ist dahingehend auch nicht immer eindeutig auf allen Servern, will man also ein Skript schreiben, welches auf allen Servern sicher ist, muss man erstmal die Daten wieder in den Ausgangszustand versetzen und dann nochmal mit entsprechenden Funktionen drüber, so dass auch die Server ohne magic quotes berücksichtigt werden. Außerdem braucht man die Slashes an sich nur, wenn man mit Datenbanken arbeitet, sonst sind sie sinnfrei.

Meiner Meinung nach: Mehraufwand > Nutzen

Holger V am 21.07.2008 um 11:28
Re: Magic Quotes Diskussion?
Beantworten

verstehe, aber der erwähnte mehraufwand entsteht ja nur bei entsprechend-"schlecht" konfiguriertem server, korrekt? daher für mich nicht ganz nachvollziehbar, da ich die zahl derartiger server eher für gering halte. ich bin jeden falls noch auf keinen gestoßen. dass magic quotes nur mit dbs genutzt werden sollen bzw. können ist klar.

vllt sollte man dann eher einen anderen server nutzen, da ja evtl noch weitere versteckte probleme vorhanden sein könnten, anstatt sich die mühe zu machen magic quotes auszutauschen. aber nichtsdestotrotz ist der mehraufwand bei einem gut geschriebenem cms minimal. man müsste ja nur die entsprechende methode/funktion bearbeiten.

Benutzer gelöscht am 22.07.2008 um 11:34
Re: Magic Quotes Diskussion?
Beantworten

"schlecht konfiguriert" ist dann wieder eine Frage des persönlichen Geschmacks. Wenn ich es lieber mag, dass all meine Daten so im Skript ankommen, wie sie der Benutzer eingibt, dann wäre magic quotes aus für richtig, wenn ich möglichst wenig Arbeit haben will, magic quotes an.

Auch sind die escape-Funktionen der entsprechenden Datenbanken deutlich besser als ein allgemein gehaltenes addslashes, da noch datenbankspezifische Zeichen escaped werden.

Fakt ist jedenfalls, dass es mit PHP6 rausfliegt und man dann endgültigt wieder um seine Daten kümmern muss.

Holger V am 22.07.2008 um 14:16
Re: Magic Quotes Diskussion?
Beantworten

"schlecht konfiguriert" war vllt auch nicht ganz fair ausgedrückt. letztendlich ist es natürlich eine geschmackssache. aber ich stelle soeben nach erneutem nachprüfen auch fest dass die mysql_real_escape_string() ja weiterhin erhalten bleibt und gar nicht auf magic quotes setzt.

das war ein fakt der mir so nicht klar war. freut mich immer dazu zu lernen ^^

Benutzer gelöscht am 22.07.2008 um 14:46
Besten Dank
Beantworten

Der Artikel ist wirklich sehr informativ. Einige Dinge im Artikel waren mir selbst auch noch nicht bekannt. Du hast das Thema wirklich gute von allen Seiten beleuchtet.

Fabian Ziegler am 21.07.2008 um 10:12
Re: Besten Dank
Beantworten

Da kann ich mich nur anschliessen, ein wirklich sehr gelungener Artikel.

Danke

halfmoon am 21.07.2008 um 18:40
Re: Besten Dank
Beantworten

Danke für die gute Übersicht, sehr hilfreich!

Philipp Gérard am 15.11.2008 um 11:36