Sicherheit im Login-Feld

webber

Aktives Mitglied
Hallo Ayomer,

das Thema Sicherheit im Web wird ja immer wichtiger und nichts ist schlimmer wenn der Server gehackt wurde und alle Daten zu nichte sind.

Ich habe in einigen Themen hier im Forum gelesen, dass man auf einfache Weise die Benutzerangaben im Login-Feld "überwachen" kann und schädlichen Code fernhalten kann. Sicher gibt es einige php-Befehle dafür die html-code rausfiltern die aber auch Standard sind.

Was habt Ihr für Erfahrungen, wurde Euer Server schon mal angegriffen?
Wie habt Ihr Euch geschützt bzw. welcher Schutz hat bei Euch funktioniert?
Wie einfach und sicher kann der Code aussehen in php?

Wäre sehr Dankbar für Eure Erfahrungen und sicherlich können auch andere Webmaster Ihre Datenbanken bzw. Login-Systeme besser schützen.


Gruß webber
 
Sehr interessante Frage!

Ich hoffe mir ist keiner sauer wenn ich eine Fragee ergänze:
Mit welchen Angriffen kann oder sollte man rechnen?

Gruß, Dariy.
 
Ich glaube es gibt zwei Antworten, die deutlicher nicht sein können:

1. Jeder Server wird angegriffen
2. Man sollte mit allen Angriffen rechnen
 
Du darfst dich nicht nur auf Login Formulare beschränken mit der Sicherheit. Alle Formulare sind anfällig für Schadcode, also Kontaktformulare, Registration, Newsletter abonnieren, etc.

 
QUOTE Du darfst dich nicht nur auf Login Formulare beschränken mit der Sicherheit. Alle Formulare sind anfällig für Schadcode, also Kontaktformulare, Registration, Newsletter abonnieren, etc.


das ist mir schon klar ... meine Frage ist wenn jetzt jemand zB über ein <input>-Feld schadhaften Code einträgt - sei es im Login-Feld oder Kontaktformular - der aber nicht aus html-Anweisungen besteht, den auch zu Kontrollieren bzw. abzufangen.

wenn ich mir die folgende Code-Zeile anschaue, weiss ich nicht ob man diesen so einfach rausfischen kann:

aus einem aktuellen Thema von jAuer

CODE DECLARE%20@S%20NVARCHAR(4000);SET%20@S=CAST(0x4400450043004C0041005200450020004


was besagt eigentlich diese Codezeile?

 
Genau kann ich dir nicht sagen, was die Zeile bedeutet. Sieht für mich nach SQL aus. Ich schätze mal es bewirkt einen Speicherüberlauf, so siehts für mich aus. Ist aber eher geraten...

Sich gegen sowas zu schützen ist nicht so schwer. Man muss eben sorgfältig programmieren, d.h. für PHP z.B. register_globals OFF setzen und auf die Formularfelder nur mit $_GET oder $_POST zugreifen. Diese Felder natürlich mit den entsprechenden Funktionen filtern.

 
Was jAuer da angesprochen hat nennt sich (wie auch in dem Thread genannt) SQL Injections und dazu gibts bei weitem genug Informationen im Netz.

Achte einfach darauf, dass die Benutzereingaben nur die von Dir erlaubten Zeichen beinhalten dürfen und Du NIEMALS eine Benutzereingabe 1:1 in einem SQL Befehl oder System-Aufruf verwendest. Sicherstellen, dass Zahlenfelder auch nur Zahlen beinhalten, Strings richtig escaped (hmmm "maskiert"?) sind etc. etc.
 
QUOTE (deetee @ Mo 2.06.2008, 23:13)Alle Formulare sind anfällig für Schadcode, also Kontaktformulare, Registration, Newsletter abonnieren, etc.

Alle Formulare heißt wirklich alle.

Auch ein Suchformular auf einer Domain, bei der es keinerlei Anmeldungs/Registrierungs/Bestellmöglichkeit gibt, genügt, um den in dem anderen Thread erwähnten Schadenscode einzuspielen / zu injizieren.


QUOTE (webber @ Di 3.06.2008, 09:13)wenn ich mir die folgende Code-Zeile anschaue, weiss ich nicht ob man diesen so einfach rausfischen kann:

aus einem aktuellen Thema von jAuer

CODE DECLARE%20@S%20NVARCHAR(4000);SET%20@S=CAST(0x4400450043004C0041005200450020004


was besagt eigentlich diese Codezeile?


Sql-Code ist 'Klartext-Code', also ein String. So ein String kann binär gespeichert werden. Wenn ich das mit meinem eigenen Code aus dem anderen Thread


CODE Declare @catalog nvarchar(255),
@schema nvarchar(255),
@table nvarchar(255),
@column nvarchar(255),
@cmd nvarchar(Max)


mache, dann kommt das dabei raus (eigentlich ohne Returns, aber das sprengt hier Browser).


CODE 0x4400650063006C00610072006500200040006300610074
0061006C006F00670020006E00760061007200630068006100720
0280032003500350029002C0020000D000A00400073006300680
065006D00610020006E007600610072006300680061007200280
032003500350029002C0020000D000A0040007400610062006C
00650020006E0076006100720063006800610072002800320035
00350029002C0020000D000A00400063006F006C0075006D006
E0020006E0076006100720063006800610072002800320035003
50029002C000D000A00400063006D00640020006E0076006100
7200630068006100720028004D00610078002900



Das kann man natürlich rückgängig machen. Und das macht der obige Schadcode: Er deklariert eine Textvariable, weist dieser per SET die per CAST zurückcodierte Sql-Zeichenfolge zu und führt diese anschließend aus.

Im Prinzip ist der Schadenscode also ein Dreizeiler:


CODE Declare @cmd nvarchar(4000)
Set @cmd = Cast(0x4400650063006C0061007200650020 ... As nvarchar(4000))
Exec (@cmd)


Der Rest sind einfache Url-Maskierungen (%20 für Leerzeichen). Man sieht: Der Code enthält keine einfachen Hochkommata mehr. Und wenn bei einer Suche eine Kategorie aus einer Pulldown-Liste ausgewählt werden kann und beim zurückgesendeten Wert nicht geprüft wird, ob das eine Zahl ist, sondern der Wert 1:1 übernommen wird, dann kann man den obigen Schadcode ausführen.

Da es Cast / Exec auch bei mySql in der Version 5 gibt, müßte das da prinzipiell auch gehen.


QUOTE (Yosh @ Di 3.06.2008, 13:07)Achte einfach darauf, dass die Benutzereingaben nur die von Dir erlaubten Zeichen beinhalten dürfen und Du NIEMALS eine Benutzereingabe 1:1 in einem SQL Befehl oder System-Aufruf verwendest. Sicherstellen, dass Zahlenfelder auch nur Zahlen beinhalten, Strings richtig escaped (hmmm "maskiert"?) sind etc. etc.

Ersteres ist explizit falsch. Ich kann nach jemandem namens O'Neill suchen. Wenn dann


QUOTE Ihre Suche nach ONeill erbrachte ... Ergebnisse


wie ich das schon gesehen habe, dann ist das peinlich für die Entwickler. Ähnliches gilt für Schlüsselwörter.

Das Rezept gegen Sql-Injektionen ist einfach: Ausschließlich gespeicherte Prozeduren verwenden. Keinen Sql-Code dynamisch zusammenbauen. Dann kann die Logik nicht verändert werden. Nur: Das ist ziemlich viel Arbeit.
 
Wird dieses Vorgehen irgendwo beschrieben, so dass wir die von solch fragwürdingen Manipulationen keine Ahnung haben auch verstehen, wie die Formulare geschützt werden können?

Meine Formulare sind dazu da, um einfach Buchstaben und Zahlen in eine DB zu schreiben, mit einfachem INSERT und UPDATE. Besteht denn da auch schon Gefahr? Reich es da nicht wenn ich mit REPLACE Zeichenfolgen die SQL-Befehlen entsprechen eliminiere?

Gruss René
 
@jAuer
Danke für die ausführliche Erklärung.

Du meinst also, kein dynamisches zusammenbauen der Sql-Befehle? Ich dachte gerade das ist sicherer
huh.gif


QUOTE Keinen Sql-Code dynamisch zusammenbauen. Dann kann die Logik nicht verändert werden. Nur: Das ist ziemlich viel Arbeit.

Viel Arbeit, ist fast noch untertrieben und manchmal bis meistens gar nicht machbar. Wehe dem es muss etwas verändert werden (bei > 300 Dateien, viel Spass).


Bis hierhin schon mal Danke für Eure Anworten. Ich sehe es ist doch ein Thema über das gesprochen werden sollte, da doch noch einige Unklarheiten.


Gruß webber

 
QUOTE (webber @ Mi 4.06.2008, 15:11)Du meinst also, kein dynamisches zusammenbauen der Sql-Befehle? Ich dachte gerade das ist sicherer
huh.gif



Gerade das ist ja das Problem, weil man damit durch 'hinreichend geschickte Eingaben' neue, eigene Logik einfügen kann.


QUOTE (webber @ Mi 4.06.2008, 15:11)
QUOTE Keinen Sql-Code dynamisch zusammenbauen. Dann kann die Logik nicht verändert werden. Nur: Das ist ziemlich viel Arbeit.

Viel Arbeit, ist fast noch untertrieben und manchmal bis meistens gar nicht machbar. Wehe dem es muss etwas verändert werden (bei > 300 Dateien, viel Spass).


Deshalb ist es bei größeren Projekten entscheidend, eine zusätzliche Logik zu entwickeln, mit der man (1) die benötigten gespeicherten Prozeduren automatisiert erstellen kann und bei der man (2) eine Art Metalogik hat, wie man beim Abfragen und Ändern von Daten die Prozeduren so automatisiert mit Werten bestückt, daß man nicht jedesmal manuell programmieren muß.

Ich hatte so etwas vor Jahren das erste Mal bei einem größeren Offline-Projekt entwickelt. server-daten besteht jetzt im Kern auch aus so etwas: Ein Nutzer (oder ich) definiert eine Tabelle, die benötigten gespeicherten Prozeduren werden automatisch erzeugt. Der dafür benötigte Job läuft asynchron und hat stärkere Rechte als die Verbindung zwischen Web- und Datenbankserver, deren Berechtigung lediglich ausreicht, die Daten (Spaltennamen, Datentypen, RegEx-Einschränkungen für Spalten) einzutragen.

Da man allerdings zusätzlich Tabellen miteinander verknüpfen und eigene Sql-Abfragen erstellen kann (und man mit diesen auf andere Kundendatenbanken zugreifen könnte), gibt es zusätzlich einen kompletten Sql-Parser, der diese Eingaben auf verbotene Schlüsselwörter (Set, Exec, Systemprozeduren) prüft und den Zugriff auf andere Datenbanken oder auf meine Verwaltungstabellen unterbindet.



QUOTE (radarin @ Mi 4.06.2008, 14:18)Meine Formulare sind dazu da, um einfach Buchstaben und Zahlen in eine DB zu schreiben, mit einfachem INSERT und UPDATE. Besteht denn da auch schon Gefahr? Reich es da nicht wenn ich mit REPLACE Zeichenfolgen die SQL-Befehlen entsprechen eliminiere?


Selbstverständlich besteht genau da die Gefahr. Das steht in dem Beitrag darüber.

Und wenn jemand ' mit einer Unicode-Sondercodierung angibt, so daß ein Replace das nicht findet?

Oder (als Pseudocode):


CODE <select name='kategorie'>
<option value='1'>Handball</option>
<option value='2'>Fussball</option>
</select>

und:

$cmd = 'Select * From Tabelle Where Kategorie = $kategorie';


nach dem Motto, daß das ja eine Zahl sei. Schon ist die Datenbank gehackt.
 
Wenn man alle GET- und POST- Variablen vor dem Arbeiten mit MySQL so bearbeitet, kann es dann trotzdem Probleme geben?
$variable = mysql_real_escape_string(trim(strip_tags($variable)));
Könnte der oben genannte Code (mit SET, EXEC; in allen Varianten) trotzdem Schaden anrichten?
 
mysql_real_escape_string() ist nur im Falle von Strings sinnvoll, die in der Query mit '' umschlossen werden. Bei Integern müsste stattdessen auf den Typ geprüft werden (z.B. mit (int)). Wiederum ein anderer Fall sind Bezeichner für Spaltenamen u.ä. Siehe hierzu auch:

The Unexpected SQL Injection
 
QUOTE (cr4m0 @ Sa 7.06.2008, 23:35)$variable = mysql_real_escape_string(trim(strip_tags($variable)));
Könnte der oben genannte Code (mit SET, EXEC; in allen Varianten) trotzdem Schaden anrichten?

Selbstverständlich kann das dann Schaden anrichten.

Einfach vor den Schadcode '0 ' ranhängen und das ganze per zusammenkonstruierter Seite an das Feld 'Kategorie' übergeben (eventuell kommt noch ein ; dazwischen).

Das ergibt den syntaktisch korrekten Sql-Code


CODE Select * From Tabelle Where Kategorie = 0 Declare @cmd nvarchar(4000) ...


das wird dann brav ausgeführt.

Wer Sql-Code dynamisch zur Laufzeit zusammenbaut und ihn dann ausführt, der sollte sehr genau wissen, was er tut. Deshalb mache ich das nicht - und mir stattdessen lieber die Arbeit, die entsprechenden gespeicherten Prozeduren zu generieren.

Und ich lasse die Finger davon, Projekte, die solchen zusammengeschusterten Sql-Code enthalten, 'weiterzuentwickeln'. Ich will für so etwas nicht gradestehen müssen.
 
Aber man kann ja ALLE Abfragen so aufbauen:
$abfrage = "SELECT feld FROM tabelle WHERE titel = '".$wert."'";
Durch die Hochkommata richtet der Code keinen Schaden mehr an, oder?
Und wenn man das ohne Hochkommata für Integer-Felder macht, dann muss man die Variable $wert eben vorher mit intval() bearbeiten.
 
QUOTE (cr4m0 @ So 8.06.2008, 19:04)Aber man kann ja ALLE Abfragen so aufbauen:
$abfrage = "SELECT feld FROM tabelle WHERE titel = '".$wert."'";
Durch die Hochkommata richtet der Code keinen Schaden mehr an, oder?
Und wenn man das ohne Hochkommata für Integer-Felder macht, dann muss man die Variable $wert eben vorher mit intval() bearbeiten.

Ich verwende keine dynamisch zusammengesetzten Sql-Abfragen. Also werde ich solchen Techniken auch keine Absolution erteilen. Ich kann (auch ohne großartige PHP/mySql-Kenntnisse) auf Löcher hinweisen - aber nicht behaupten, daß eine Methode sicher sei (abgesehen von gespeicherten Prozeduren, die es nicht zulassen, die Logik zu ändern).

Ich finde es einfach unsinnig, mich mit solchen sinnlosen Fragen zu beschäftigen. Und dann gibt es eine neue Codierungsmöglichkeit innerhalb von PHP - und es gibt damit ein neues Loch.

Die Zeit investiere ich lieber darin, brauchbare gespeicherte Prozeduren zu erstellen. Dann habe ich das Problem nicht.

Wenn Du solche Dinge unbedingt verwenden willst, dann lies den Artikel, den Jörg verlinkt hat.
 
Was genau muss ich unter einer gespeicherten Prozedur verstehen?

CODE
$sql="INSERT INTO tabelle (spalte1, spalte2) VALUES ('Feld1', 'Feld2')";
$insertds = mysql_query($sql);



In den Feldern kann natürlich Beliebiges eingegeben werden. (Geht ja nicht Anders)
 
Jürgen, hilf mir bitte Mal auf die Sprünge.

Warum ist das Ausführen z.B. einer Suchfunktion ala

"select * from quelltabelle where tag like '%".$suchvariable."%'"

in einer SP sicherer als in einer vom Client übermittelten Abfrage?
$suchvariable missbrauchen kann ich in beiden Varianten, daher erschliesst sich mir das noch nicht ganz.

Tante G. liefert mir da auch keine wirklich erschöpfende Antwort.

Gruß,
Tom
 
QUOTE (TSc @ Mo 9.06.2008, 08:17)Warum ist das Ausführen z.B. einer Suchfunktion ala

"select * from quelltabelle where tag like '%".$suchvariable."%'"

in einer SP sicherer als in einer vom Client übermittelten Abfrage?
$suchvariable missbrauchen kann ich in beiden Varianten, daher erschliesst sich mir das noch nicht ganz.

Gespeicherte Prozedur dafür:


CODE Create Procedure dbo.durchsuche_Quelltabelle
@suchvariable nvarchar(4000)
As

Select * From Quelltabelle where tag like '%' + @suchvariable + '%'


Sql-Code wird auf syntaktische Korrektheit geprüft und kompiliert: 'Was macht er, auf welche Tabellen und Spalten greift er zu'. Dann wird Code einmal oder mehrfach (falls das Kompilat gecacht wurde) ausgeführt.

Kompilat bei Verwendung einer SP:


CODE Declare ?suchvariable nvarchar(4000)
Select * From quelltabelle where tag like '%' + ?suchvariable + '%'


Logik, Tabellen/Spaltennamen und nutzerabhängige Daten werden voneinander getrennt. Ersteres liegt mit dem Kompilat fest und kann innerhalb der Ausführung nicht mehr geändert werden.

Kompilat bei direkter Übermittlung:


CODE Select * From quelltabelle where tag like '%Vom Webserver übermittelte Zeichenfolge%'


Verschiedene Nutzereingaben erzeugen verschiedene Kompilate, der Code erwartet keine Variable. Also wird auch die Logik jedesmal neu ermittelt.

Im ersten Fall ist sichergestellt, daß (1) nur eine Select-Anweisung ausgeführt wird, (2) auf welche Tabellen / Spalten diese zugreift, (3) deren Where-Kriterien, (4) daß beim Ausführen zusätzlich eine Zeichenfolge erwartet wird (bei Zahlen / Datumsangaben wird automatisch eine Typüberprüfung durchgeführt). Im zweiten Fall ist alles offen, alles hängt von der vom Webserver übermittelten Zeichenfolge ab. Die kann - mit viel Gewürge - korrekt sein - sie kann aber auch zusätzliche Union, Delete oder per Binärcodierung versteckte Anweisungen enthalten, die Where-Klausel um ein 'Or 0 = 0' erweitern.

Bei der Verwendung von SP wird also zur Erstellungszeit dieser (wozu bsp. Rechte notwendig sind, die die Verbindung vom Web- zum Datenbankprozeß nicht hat / nicht haben sollte) festgelegt, was gemacht werden soll. Bei der Verwendung von ad hoc zusammengebautem Sql-Code ist die Architektur darauf angewiesen, daß beim Zusammenbauen alle möglichen und unmöglichen Fälle berücksichtigt werden - Sisyphos läßt grüßen.

Bei der Verwendung von SP wird dem Webserver auf dem DbServer nur das Recht zugestanden, gewisse SP auszuführen. Bei Ad-Hoc-Lösungen muß der Webserver Select/Insert/Update/Delete - Rechte für alle möglichen Tabellen haben.

Eine Folge: Würde bei server-daten der Webserver komplett gehackt, so daß ein Hacker interaktiv mit Administratorenrechten auf dem Webserver säße, dann könnte er sich PHP/Perl installieren oder neuen NET-Code einspielen, mit dem er versuchen würde, auf die Datenbank zuzugreifen. Und was könnte er machen? Nur genau jene gespeicherten Prozeduren ausführen, die interaktive Nutzer ohnehin ausführen. Er könnte keinen einzigen ad hoc zusammengebauten Sql-Code ausführen. Denn er kann lediglich mit einer Verbindung auf den Datenbankserver zugreifen, die nur diese schwachen Rechte hat.

Man hat also eine mehrstufige Architektur, bei welcher die Komponente, die 'nahe am Client' liegt, auch nur sehr geringe Rechte benötigt. Der Client / Webbrowser kann alles mögliche schicken. Dann reicht es aber auch aus, wenn der Webserver das (mit seinen schwachen Rechten) bloß weiterreicht, weil der Code auf dem DbServer ohnehin bloß gewisse Stellen (@variable) für clientseitige Daten zuläßt.

Bei Ad-Hoc-Anfragen muß der Datenbankserver dem Webserver völlig vertrauen, die Verbindung benötigt starke Rechte. Warum soll ich so ein Risiko in Richtung 'offenes Web' verlagern?
 
Zurück
Oben