Autor |
Beitrag |
Marco D.
      
Beiträge: 2750
Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
|
Verfasst: Mi 27.12.06 21:58
Ich möchte eine PHP-Funktion schreiben, die einen string 'entschärft', sodass er gefahrlos in die DB eingetragen werden kann. So will ich Angriffen wie z.B. XSS vorbeugen.
Kann man das so machen? Was fehlt noch?
C#-Quelltext 1: 2: 3: 4: 5: 6: 7:
| function DefuseString($string) { $string = mysql_real_escape_string($string); $string = html_special_chars($string); ... return $string; } |
_________________ Pascal keeps your hand tied. C gives you enough rope to hang yourself. C++ gives you enough rope to shoot yourself in the foot
|
|
jakobwenzel
      
Beiträge: 1889
Erhaltene Danke: 1
XP home, ubuntu
BDS 2006 Prof
|
Verfasst: Mi 27.12.06 21:59
Wenn du den String nur gefahrlos in ne Datenbank eintragen willst, kannste des html_special_chars auch weglassen. Nur für die HTML-Ausgabe is das muss.
_________________ I thought what I'd do was, I'd pretend I was one of those deaf-mutes.
|
|
Marco D. 
      
Beiträge: 2750
Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
|
Verfasst: Mi 27.12.06 22:04
jakobwenzel hat folgendes geschrieben: | Wenn du den String nur gefahrlos in ne Datenbank eintragen willst, kannste des html_special_chars auch weglassen. Nur für die HTML-Ausgabe is das muss. |
Ok, gibt es dann noch mehr Funktionen, die man braucht? Dann kann ich ja auch gleich mysql_real_escape_string nehmen, wenn es bloß die eine wäre. 
_________________ Pascal keeps your hand tied. C gives you enough rope to hang yourself. C++ gives you enough rope to shoot yourself in the foot
|
|
Arne K.
      

Beiträge: 112
C# (VS 2008 Professional)
|
Verfasst: Mi 27.12.06 22:56
Wenn du den String in die Datenbank speicherst: mysql_escape_string().
Wenn du ihn anzeigen willst:
htmlentities(); bzw. html_entities(); (bin mir gerade nicht so sicher).
Ändere niemals den String, bevor du ihn in die DB einträgst (außer Escapen)! Nach dem Auslesen kannst du mit ihm machen, was du willst! Wenn du ihn aber schon vorformatiert aus der DB bekommst, ist jede nachträgliche Korrektur unmöglich bzw. äußerst aufwändig!
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Do 28.12.06 11:54
Zitat: | The String has been defused. Anti-Hacker wins. |
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| if (!empty($_GET)) extract($_GET); if (!empty($_POST)) extract($_POST);
function kill_tags_deep($value) { $value = is_array($value) ? array_map('kill_tags_deep', $value) : trim(strip_tags(stripslashes($value)));
$bad = array ('@<script[^>]*?>.*?</script>@si', '@<[\/\!]*?[^<>]*?>@si', '@&(quot|#34);@i', '@&(amp|#38);@i', '@&(lt|#60);@i', '@&(gt|#62);@i', '@&(nbsp|#160);@i', '@&(iexcl|#161);@i', '@&(cent|#162);@i', '@&(pound|#163);@i', '@&(copy|#169);@i', '@(\d+);@e');
$good = array ('', '', '"', '&', '<', '>', ' ', chr(161), chr(162), chr(169), 'chr(\1)');
return preg_replace($bad, $good, $value); return $value; }
$_POST = kill_tags_deep($_POST); $_GET = kill_tags_deep($_GET); |
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
alcaeus
      
Beiträge: 226
|
Verfasst: Do 28.12.06 22:23
Reyx hat folgendes geschrieben: | Ändere niemals den String, bevor du ihn in die DB einträgst (außer Escapen)! Nach dem Auslesen kannst du mit ihm machen, was du willst! |
Falsch. Es kommt auf die Verwendung drauf an. Wenn ich mich so einschraenken will, dass ich niemals HTML erlaube, dann kann ich Zeit sparen indem ich das htmlspecialchars() vor dem Eintragen in die DB erledige, anstatt es bei jedem Seitenaufruf zu erledigen. Ich mache bei jedem String folgendes:
Quelltext 1: 2:
| $str = (string) $str; $str = htmlspecialchars(trim($str)); |
Falls der String in die DB wandert, laeuft dann noch mysql_real_escape_string() drueber. Und wenn magic_quotes_gpc an ist, wird vor dem trim() noch ein stripslashes() ausgefuehrt.
XSS hat damit ueberhaupt keine Chance.
@GTA-Place: was genau soll die Funktion erledigen?
Greetz
alcaeus
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Do 28.12.06 22:37
Das ist ne Mischung aus Example 2 ( de2.php.net/stripslashes) und noch PregReplace dazu. Auf gut deutsch: Doppelt hält besser.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
Arne K.
      

Beiträge: 112
C# (VS 2008 Professional)
|
Verfasst: Fr 29.12.06 00:08
alcaeus hat folgendes geschrieben: | Falsch. Es kommt auf die Verwendung drauf an. Wenn ich mich so einschraenken will, dass ich niemals HTML erlaube, dann kann ich Zeit sparen indem ich das htmlspecialchars() vor dem Eintragen in die DB erledige, anstatt es bei jedem Seitenaufruf zu erledigen. |
Und du kannst mit gewissheit sagen, dass du niemals deinen Parser ändern wirst? Dass du niemals Technologien anwenden wirst, die vielleicht ein Umdenken nötig machen? Und auch, dass du niemals deine eigene Meinung ändern wirst?
Für derlei Performanceprobleme sind Cacher übrigens geradezu prädestiniert 
|
|
freak4fun
      
Beiträge: 604
Erhaltene Danke: 4
Win 7 Pro
VS 2013 Express, Delphi, C#, PHP, Java
|
Verfasst: Fr 29.12.06 13:07
Und wie macht man das mysql_real_escape_string(); bei der Ausgabe wieder rückgängig?
MfG
freak
_________________ "Ich werde auf GAR KEINEN Fall…!" - "Keks?" - "Okay, ich tu's."
i++; // zaehler i um 1 erhoehen
|
|
Marco D. 
      
Beiträge: 2750
Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
|
Verfasst: Fr 29.12.06 13:09
freak4fun hat folgendes geschrieben: | Und wie macht man das mysql_real_escape_string(); bei der Ausgabe wieder rückgängig?  |
Würde mich auch mal interessieren...
_________________ Pascal keeps your hand tied. C gives you enough rope to hang yourself. C++ gives you enough rope to shoot yourself in the foot
|
|
wulfskin
      
Beiträge: 1349
Erhaltene Danke: 1
Win XP
D5 Pers (SSL), D2005 Pro, C, C#
|
Verfasst: Fr 29.12.06 13:57
Übrigens, auf PHP.net gibt es noch einen interessanten Kommentar dazu: Zitat: | Note that this function will NOT escape _ (underscore) and % (percent) signs, which have special meanings in LIKE clauses.
As far as I know there is no function to do this, so you have to escape them yourself by adding a backslash in front of them. |
Das würde ich mal lieber _nicht_ vergessen!
Zum Auslesen: Ich denke da ist keine Umwandlung mehr erforderlich, er wird "unescaped" ausgegeben.
_________________ Manche antworten um ihren Beitragszähler zu erhöhen, andere um zu Helfen.
|
|
Marco D. 
      
Beiträge: 2750
Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
|
Verfasst: Fr 29.12.06 14:08
wulfskin hat folgendes geschrieben: | Übrigens, auf PHP.net gibt es noch einen interessanten Kommentar dazu: Zitat: | Note that this function will NOT escape _ (underscore) and % (percent) signs, which have special meanings in LIKE clauses.
As far as I know there is no function to do this, so you have to escape them yourself by adding a backslash in front of them. | Das würde ich mal lieber _nicht_ vergessen!
Zum Auslesen: Ich denke da ist keine Umwandlung mehr erforderlich, er wird "unescaped" ausgegeben. |
Danke für den Hinweis!
_________________ Pascal keeps your hand tied. C gives you enough rope to hang yourself. C++ gives you enough rope to shoot yourself in the foot
|
|
Marco D. 
      
Beiträge: 2750
Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
|
Verfasst: Fr 29.12.06 14:16
Habe das jetzt so:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| //'entschärft' einen String für das Eintragen in die DB function DefuseString($string) { $string = mysql_real_escape_string($string);
//setzt ein Backslash vor _ (underscore= und % (percent) $string = str_replace('_','/_',$string); $string = str_replace('%','/%',$string);
$string = htmlspecialchars($string); return $string; } |
_________________ Pascal keeps your hand tied. C gives you enough rope to hang yourself. C++ gives you enough rope to shoot yourself in the foot
|
|
alcaeus
      
Beiträge: 226
|
Verfasst: Fr 29.12.06 17:08
Quelltext 1: 2: 3:
| //setzt ein Backslash vor _ (underscore= und % (percent) $string = str_replace('_','/_',$string); $string = str_replace('%','/%',$string); |
Backslash, nicht Slash:
Quelltext 1: 2: 3:
| //setzt ein Backslash vor _ (underscore= und % (percent) $string = str_replace('_','\_',$string); $string = str_replace('%','\%',$string); |
Ausserdem: lass es weg. Diese Zeichen haben bei einem INSERT oder UPDATE oder auch SELECT ohne LIKE keine besondere Bedeutung und muessen nicht escaped werden. Nur bei einer SELECT-Abfrage mit LIKE-Klausel musst du sie escapen, da % und _ in dem Fall als Wildcards gelten. _ matcht ein einzelnes Zeichen, % einen beliebigen String (also wie ? und * unter Windows). Ich wuerde die Funktion so machen:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31:
| /* * Bereitet einen String zum Eintragen in die DB vor * @param string $string Der String zum Escapen * @param bool $multibyte True wenn multibyte-Zeichen (Ӓ) auch akzeptiert werden sollen * @param bool $like Wenn True, werden auch _ und % escaped * @return string Der fertige String */ function escape_db_string($string, $like = False) { // Siehe Kommentar [1] if (get_magic_quotes_gpc()) { $string = stripslashes($string); } // Siehe Kommentar [2] $string = htmlspecialchars(trim(str_replace(array("\r\n", "\r"), array("\n", "\n"), $string))); // Siehe Kommentar [3] // Multibyte-Zeichen? if ($multibyte && strpos($result, '&#') !== False) { $string = preg_replace('#&(\#[0-9]+;)#', '&\1', $string); } // Siehe Kommentar [4] if ($like) { //setzt einen Backslash vor _ (underscore= und % (percent) $string = str_replace(array('_', '%'), array('\_', '\%'), $string); }
return $string; } |
Hier die Kommentare:
1. Wenn magic quotes aktiviert sind, wurde vor dem Uebergeben der Daten an das Script bereits ein addslashes() ausgefuehrt. In dem Fall musst du es rueckgaengig machen, um den String nicht doppelt zu escapen.
2. Was macht das Monster? Erstmal setzt es konsequent \n fuer Zeilenumbrueche durch; verschiedene Betriebssysteme haben da unterschiedliche Auffassungen. Anschliessend ein trim() um Speicherplatz zu sparen, und ganz am Ende noch ein htmlspecialchars().
3. Was sind Multibyte-Zeichen? Dinge wie z.B. Ӓ. Diese koennen als Zeichen dargestelt werden, werden durch das htmlspecialchars() aber zersemmelt. Wenn der Parameter also auf true ist, und solche Zeichen vorkommen, wandeln wir sie wieder zurueck.
4. Die Sache mit dem LIKE habe ich von einem Parameter abhaengig gemacht. Wie erwaehnt muss das Escapen von _ und % nicht immer geschehen; mit dem Parameter kannst du das jetzt steuern. Wenn du denkst, dass du das nicht brauchen wirst, kannst du den Teil inkl. Parameter gleich rauswerfen
Greetz
alcaeus
|
|
Marco D. 
      
Beiträge: 2750
Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
|
Verfasst: Fr 29.12.06 17:14
Danke.
_________________ Pascal keeps your hand tied. C gives you enough rope to hang yourself. C++ gives you enough rope to shoot yourself in the foot
|
|
delfiphan
      
Beiträge: 2684
Erhaltene Danke: 32
|
Verfasst: Fr 29.12.06 20:16
Ich stimme Reyx voll zu: Daten soll man so roh wie möglich speichern. Was machst du, wenn du auf eine andere HTML-Version umsteigen willst oder deine Daten in einem Delphi-Programm darstellen willst, oder du die Daten bearbeiten willst?
Wenn du nur Text zulässt und kein HTML, dann kannst du den String mit mysql_real_escape_string escapen und die dann so in deine mysql-Query einfügen. Was du eventuell vorher noch tun kannst ist eine Ersetzung von "\r\n" zu "\n" und anschliessend "\r" zu "\n".
@Multibyte-Character: Definiere deine HTML-Seite als UTF-8 und verwende diesen Charset. Du gehst damit vielen Charset-Albträumen aus dem Weg. Wenn deine Seite UTF-8 ist, dann achte darauf, dass die Felder der SQL-Tabelle ebenfalls UTF-8 sind und du die Daten und SQL-Connection auch als UTF-8 definierst ("set character set utf8", "set character_set_connection=utf8"). Beim Darstellen als HTML kannst du dann den String aus der Datenbank mit htmlentities($str, ENT_COMPAT, 'UTF-8') "entschärfen". Was du noch tun kannst ist dann noch die Ersetzung "\n" zu "<br>" bzw. "<br/>".
@Like: Wenn du wegen dem "Like" alle Prozentzeichen im Text ersetzst hast du das Problem am falschen Ort gepackt. Du musst wenn schon deinen Suchstring korrekt escapen, doch aber nicht die Daten!
@stripslashes: Die Magicquotes wurden gegen einen häufigen Anfängerfehler geschaffen. Ich finde die Sache äusserst unsauber. Nicht jeder gepostete String landet automatisch auf einer Datenbank! Schalte die aus und verwende stattdessen mysql_real_escape_string!
Htmlentities sollte definitiv keine Performanceschwierigkeiten bringen. Wenn du Performanceprobleme hast gibt es dafür direktere Lösungen.
|
|
|