Sonderzeichen umwandeln HTML injection verhindern
Hi,
ich will meine Seite sicher vor Angriffen machen, da soll man ja für gewöhnlich htmlspecialchars() verwenden.
Jedoch weis ich nicht genau was ich alles beachten muss bei der Versendung eines Formulars und dann bei dem einfügen in eine Datenbank.
Beispiel:
1. Sollte ich das Abspeichern in eine andere Variablen hier $nachricht verhinden und direkt dann z.B. in die Datenbank eintragen oder ist der Gebrauch der $nachricht Variable nicht ganz so tragisch?
2. Würde der Code ausreichen um die Seite sicher zu machen?
3. Muss ich noch etwas beim Einfügen in die Datenbank beachten und auch bei der Ausgabe?
4. Sollte ich auch auch andere Funktionen wie stripslasches(), trim(), usw. benutzen? Wenn ja welche?
Würd mich freuen wenn jemand behilflich sein könnte und mir sagen würde was ich alles bei so etwas beachten sollte.
Gruß
Sapzero
ich will meine Seite sicher vor Angriffen machen, da soll man ja für gewöhnlich htmlspecialchars() verwenden.
Jedoch weis ich nicht genau was ich alles beachten muss bei der Versendung eines Formulars und dann bei dem einfügen in eine Datenbank.
Beispiel:
$nachricht=htmlspecialchars($_POST('nachricht'));
2. Würde der Code ausreichen um die Seite sicher zu machen?
3. Muss ich noch etwas beim Einfügen in die Datenbank beachten und auch bei der Ausgabe?
4. Sollte ich auch auch andere Funktionen wie stripslasches(), trim(), usw. benutzen? Wenn ja welche?
Würd mich freuen wenn jemand behilflich sein könnte und mir sagen würde was ich alles bei so etwas beachten sollte.
Gruß
Sapzero
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 125913
Url: https://administrator.de/contentid/125913
Ausgedruckt am: 22.11.2024 um 14:11 Uhr
9 Kommentare
Neuester Kommentar
Hallo Sapzero
du solltest dir auf jeden Fall einmal die folgenden beiden Seiten zum Thema SQL-Injection durchlesen:
Im diesem Sinne wird dann auch diese Seite noch einmal interessant:
Zu beachten gilt immer:
Was du auch noch machen kannst ist das Prüfen der Eingaben mit regulären Ausdrücken und den Variablenfunktionen, z.B.:is_numeric().
So kann man anhand dieser Auswertung dem Benutzer zur erneuten Eingabe auffordern, oder es einfach ignorieren so das die bösen Eingaben gar nicht erst in einem SQL-Query genutzt werden.
<code type=php">
$errorfields=array();
/*###########################
eintrag pruefen ######
*/
$newE=array('name' =>isset($_POST['name']) && trim($_POST['name'])!='' ? trim($_POST['name']) : NULL,
'email'=>isset($_POST['email']) && trim($_POST['email'])!='' ? trim($_POST['email']) : NULL,
'home' =>isset($_POST['home']) && trim($_POST['home'])!='' ? trim(str_replace('http://','',$_POST['home'])) : NULL,
'text' =>isset($_POST['text']) && trim($_POST['text'])!='' ? trim($_POST['text']) : NULL,
'cap' =>isset($_POST['cap']) && trim($_POST['cap'])!='' ? trim($_POST['cap']) : NULL,
'zahl' =>isset($_POST['zahl']) && is_numeric($_POST['zahl'])!='' ? (int)$_POST['zahl'] : NULL
);
email und homepage sind optionale eingaben
if(!is_null($newE['email']) && !preg_match('/^[a-z0-9]+?[a-z0-9\-_.]+[a-z0-9]+@[a-z0-9]+?[a-z0-9\-_.]+[a-z0-9]+?\.[a-z]{2,5}$/i',$newE['email'])) $errorfields='E-Mail';
if(!is_null($newE['home']) && !preg_match('/^(http:\/\/|www.|http:\/\/www.)?[a-z0-9\-_.]+\.[a-z]{2,5}([a-z0-9\-_.:\/?&;=%]*)$/i',$newE['home'])) $errorfields='Homepage';
$cap=NULL;
/*#############################
eintrag speichern ######
*/
if(empty($errorfields)) wenn alle felder gueltig sind
{
es gibt wahrscheinlich keine fehleingaben, speicher neuen eintrag
eingaben in SQL-Query integrieren und an db-server schicken
natürlich mysql_real_escpe_string() nicht vergessen
Ich übergebe das $newE-Array an eine Klasse die die Daten dann weiterverarbeitet.
}
else
{
ungueltige eingaben
ungueltige eingaben verwerfen und erneut das formular anzeigen
echo 'Die Eingaben der Felder "'.implode('","',$errorfields).'" wurden nicht akzeptiert !';
}
Edit: Oha, das liest sich aber blöde...
~Arano
du solltest dir auf jeden Fall einmal die folgenden beiden Seiten zum Thema SQL-Injection durchlesen:
Im diesem Sinne wird dann auch diese Seite noch einmal interessant:
Zu beachten gilt immer:
Alle Benutzereingaben sind böse !
Und dabei sollte man auch nicht zwischen Besuchern und Administratoren unterscheiden.Was du auch noch machen kannst ist das Prüfen der Eingaben mit regulären Ausdrücken und den Variablenfunktionen, z.B.:is_numeric().
So kann man anhand dieser Auswertung dem Benutzer zur erneuten Eingabe auffordern, oder es einfach ignorieren so das die bösen Eingaben gar nicht erst in einem SQL-Query genutzt werden.
<code type=php">
$errorfields=array();
/*###########################
eintrag pruefen ######
*/
$newE=array('name' =>isset($_POST['name']) && trim($_POST['name'])!='' ? trim($_POST['name']) : NULL,
'email'=>isset($_POST['email']) && trim($_POST['email'])!='' ? trim($_POST['email']) : NULL,
'home' =>isset($_POST['home']) && trim($_POST['home'])!='' ? trim(str_replace('http://','',$_POST['home'])) : NULL,
'text' =>isset($_POST['text']) && trim($_POST['text'])!='' ? trim($_POST['text']) : NULL,
'cap' =>isset($_POST['cap']) && trim($_POST['cap'])!='' ? trim($_POST['cap']) : NULL,
'zahl' =>isset($_POST['zahl']) && is_numeric($_POST['zahl'])!='' ? (int)$_POST['zahl'] : NULL
);
email und homepage sind optionale eingaben
if(!is_null($newE['home']) && !preg_match('/^(http:\/\/|www.|http:\/\/www.)?[a-z0-9\-_.]+\.[a-z]{2,5}([a-z0-9\-_.:\/?&;=%]*)$/i',$newE['home'])) $errorfields='Homepage';
/*#############################
eintrag speichern ######
*/
if(empty($errorfields)) wenn alle felder gueltig sind
{
es gibt wahrscheinlich keine fehleingaben, speicher neuen eintrag
eingaben in SQL-Query integrieren und an db-server schicken
natürlich mysql_real_escpe_string() nicht vergessen
Ich übergebe das $newE-Array an eine Klasse die die Daten dann weiterverarbeitet.
}
else
{
ungueltige eingaben
ungueltige eingaben verwerfen und erneut das formular anzeigen
echo 'Die Eingaben der Felder "'.implode('","',$errorfields).'" wurden nicht akzeptiert !';
}
Edit: Oha, das liest sich aber blöde...
~Arano
Mahlzeit
Zu kompliziert hm... ich kann es ja einmal versuch zu erklären, belasse es dabei erst mal auf die Eingabe eines Namens:
Vorweg eine alternative Syntax für ein If/else
Das macht es jetzt vielleicht noch verständlicher.
Wenn das Formularfeld "name" übertragen wurde und dessen "getrimmter" Inhalt nicht leer ist, schreibe den getrimmten Inhalt in die Variable - andernfalls schreibe NULL in die Variable.
Wenn der Inhalt der Variable $name gleich NULL entspricht oder nicht auf den regulärem Ausdruck passt, füge den Formularfeldtitel dem $error-Array hinzu.
Zu dem regulärem Ausdruck (RegEx = regular expression): Bei dem Namen habe ich in diesem Fall bestimmt, das dieser nur aus kleinen und großen Buchstaben bestehen darf (a-z und A-Z) und eine Länge von mindestens 3 bzw. längstes 20 Zeichen haben darf.
Wird nun ein - oder ' oder ein sonstiges Zeichen in das Feld eingetragen um z.B. eine SQL-Injection zu starten, so führt das zu einem Fehler und das Skript abgebrochen - die Injection verhindert.
Wenn das $error-Array leer ist, haben die Eingaben meine oberen Test bestanden und sind vermutlich (hoffentlich) keine SQL-Injectionen, schließlich kann man ja nicht an jede Möglichkeit denken und 100% Sicherheit gibt es ja nicht.
Sollte das $error-Array doch nicht leer sein breche ich die Weiterverarbeitung ab, so habe ich mindestens "ungewollte" Fehleingaben verhindert und stoppe leichte versuche der Injectionen.
Um die Sicherheit noch weiter zu erhöhen, wird dann beim eintragen in die Datenbank wieder die Funktion mysql_real_escape_string() verwendet.
Schwieriger wird dann schon bei solchen Eingabefeldern wie Textareas. Denn hier kann ich wie bei dem Namen nicht einfach bestimmen das nur a-zA-Z erlaubt sind, hier mache ja auch andere Zeichen Sinn: ?!"-'.,;:äü$%Éé und so weiter und sofort. Hier sollte dann auf jeden Fall die Escape-Funktion benutzt werden.
Aber auch die Verwendung von PHP-Manual: htmlspecialchars(ENT_QUOTES) ist sicher ratsam, wenn PHP-Manual htmlentities(ENT_QUOTES) (de2.php.net) nicht vielleicht sogar zu bevorzugen wäre, weil diese alle Sonderzeichen umwandelt.
~Arano
ob es ausreicht die funktion "mysql_real_escape_string" bei einer Datenbankabfrage und bei html die funktion "htmlspecialchars" vor die Variable zu setzen
Naja öhm... so direkt kann ich das leider auch nicht beantworten, auf jeden Fall wird es dadurch sicherer !Zu kompliziert hm... ich kann es ja einmal versuch zu erklären, belasse es dabei erst mal auf die Eingabe eines Namens:
Vorweg eine alternative Syntax für ein If/else
<?php
if( BEDINGUNG ){
$var='wert';
}
else{
$var=NULL;
}
// ist das selbe wie:
$var = BEDINGUNG ? 'wert1' : NULL;
?>
$name = isset($_POST['name']) && trim($_POST['name'])!='' ? trim($_POST['name']) : NULL;
if(is_null($name) || !preg_match('/^([a-zA-Z]{3,20})$/',$name)) $error = 'Name;'
Zu dem regulärem Ausdruck (RegEx = regular expression): Bei dem Namen habe ich in diesem Fall bestimmt, das dieser nur aus kleinen und großen Buchstaben bestehen darf (a-z und A-Z) und eine Länge von mindestens 3 bzw. längstes 20 Zeichen haben darf.
Wird nun ein - oder ' oder ein sonstiges Zeichen in das Feld eingetragen um z.B. eine SQL-Injection zu starten, so führt das zu einem Fehler und das Skript abgebrochen - die Injection verhindert.
if(empty($error))
{
// keine Fehleingaben / SQL-Injection, speichere...
}
else
{
// Fehleingaben / SQL-Imjection, abbruch !
}
Sollte das $error-Array doch nicht leer sein breche ich die Weiterverarbeitung ab, so habe ich mindestens "ungewollte" Fehleingaben verhindert und stoppe leichte versuche der Injectionen.
Um die Sicherheit noch weiter zu erhöhen, wird dann beim eintragen in die Datenbank wieder die Funktion mysql_real_escape_string() verwendet.
Schwieriger wird dann schon bei solchen Eingabefeldern wie Textareas. Denn hier kann ich wie bei dem Namen nicht einfach bestimmen das nur a-zA-Z erlaubt sind, hier mache ja auch andere Zeichen Sinn: ?!"-'.,;:äü$%Éé und so weiter und sofort. Hier sollte dann auf jeden Fall die Escape-Funktion benutzt werden.
Aber auch die Verwendung von PHP-Manual: htmlspecialchars(ENT_QUOTES) ist sicher ratsam, wenn PHP-Manual htmlentities(ENT_QUOTES) (de2.php.net) nicht vielleicht sogar zu bevorzugen wäre, weil diese alle Sonderzeichen umwandelt.
~Arano
SQL Injection und sonstige EIngabefilterungen sind grundsätzlich mal zwei verschiedene Paar Schuhe...
Bei der SQL Injection geht es darum zu verhindern, daß durch eine Benutzereingabe ungewollte Befehle an den SQL-Server abgesetzt werden, indem z.B. durch ein ' in der Benutzereingabe ein String vorzeitig beendet und der Rest der Eingabe als neuer SQL-Befehl interpretiert wird.
Hier leistet mysql_real_escape_string() gute Dienste, da reservierte Zeichen in (my)SQL durch die entsprechenden Escape-Sequenzen ersetzt werden. Darüber hinaus sollte man, wie bereits hier erwähnt, alle Eingaben auf Korrektheit überprüfen und ggfs. unerwünschte Zeichen oder Zeichenketten ausfiltern, etwa auch CR und LF-Zeichen, wenn die Eingabe an sich nur einzeilige Angaben zuläßt. Es gibt genügend Tricks, um auch in einem an sich einzeiligen Formularfeld Zeilenvorschübe zu verstecken, was u.a. bei Mail-Formularen zu Problemen führen kann, wenn eine eingegebene Adresse ungefiltert an die mail() - Funktion übergeben wird.
htmlspecialchars() sollte vor allem bei der Ausgabe eingesetzt werden, um zu verhindern, daß vom Benutzer eingegebene HTML-Tags (vor allem <script> aber auch z.B. <iframe> im Kontext der eigenen Webseite erscheinen). Zusätzlich zu htmlspecialchars() sollte hier aber auch strip_tags() verwendet werden, um alle oder bestimmte HTML-Tags aus der Usereingabe zu filtern.
Bei der SQL Injection geht es darum zu verhindern, daß durch eine Benutzereingabe ungewollte Befehle an den SQL-Server abgesetzt werden, indem z.B. durch ein ' in der Benutzereingabe ein String vorzeitig beendet und der Rest der Eingabe als neuer SQL-Befehl interpretiert wird.
Hier leistet mysql_real_escape_string() gute Dienste, da reservierte Zeichen in (my)SQL durch die entsprechenden Escape-Sequenzen ersetzt werden. Darüber hinaus sollte man, wie bereits hier erwähnt, alle Eingaben auf Korrektheit überprüfen und ggfs. unerwünschte Zeichen oder Zeichenketten ausfiltern, etwa auch CR und LF-Zeichen, wenn die Eingabe an sich nur einzeilige Angaben zuläßt. Es gibt genügend Tricks, um auch in einem an sich einzeiligen Formularfeld Zeilenvorschübe zu verstecken, was u.a. bei Mail-Formularen zu Problemen führen kann, wenn eine eingegebene Adresse ungefiltert an die mail() - Funktion übergeben wird.
htmlspecialchars() sollte vor allem bei der Ausgabe eingesetzt werden, um zu verhindern, daß vom Benutzer eingegebene HTML-Tags (vor allem <script> aber auch z.B. <iframe> im Kontext der eigenen Webseite erscheinen). Zusätzlich zu htmlspecialchars() sollte hier aber auch strip_tags() verwendet werden, um alle oder bestimmte HTML-Tags aus der Usereingabe zu filtern.
was ich noch fragen wollte ist es auch möglich statt htmlspecialchars einfach die Eingaben mit preg_replace zu ersetzen.
Möglich ist es - klar !Aber für solche einfachen ersetzungen sollte dann lieber auf "str_replace" zurückgegriffen werden.
Und bevor du nun nach jedem Zeichen einzeln in dem Text suchst (strpos), dann ersetze sie doch lieber mit "str_replace" durch nichts: str_replace(array, '', $text);
~Arano