Autor Beitrag
Marco D.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2750

Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
BeitragVerfasst: 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?
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
//"entschärft" einen String zur Eingabe in die DB
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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1889
Erhaltene Danke: 1

XP home, ubuntu
BDS 2006 Prof
BeitragVerfasst: 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. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2750

Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
BeitragVerfasst: Mi 27.12.06 22:04 
user profile iconjakobwenzel 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.
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
EE-Autor
Beiträge: 112


C# (VS 2008 Professional)
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: Do 28.12.06 11:54 
Zitat:
The String has been defused. Anti-Hacker wins.

ausblenden 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
half ontopic starofftopic starofftopic starofftopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 226



BeitragVerfasst: Do 28.12.06 22:23 
user profile iconReyx 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:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
EE-Regisseur
Beiträge: 5248
Erhaltene Danke: 2

WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
BeitragVerfasst: 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.
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
EE-Autor
Beiträge: 112


C# (VS 2008 Professional)
BeitragVerfasst: Fr 29.12.06 00:08 
user profile iconalcaeus 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 604
Erhaltene Danke: 4

Win 7 Pro
VS 2013 Express, Delphi, C#, PHP, Java
BeitragVerfasst: Fr 29.12.06 13:07 
Und wie macht man das mysql_real_escape_string(); bei der Ausgabe wieder rückgängig? :gruebel:

MfG
freak

_________________
"Ich werde auf GAR KEINEN Fall…!" - "Keks?" - "Okay, ich tu's."
i++; // zaehler i um 1 erhoehen
Marco D. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2750

Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
BeitragVerfasst: Fr 29.12.06 13:09 
user profile iconfreak4fun hat folgendes geschrieben:
Und wie macht man das mysql_real_escape_string(); bei der Ausgabe wieder rückgängig? :gruebel:

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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1349
Erhaltene Danke: 1

Win XP
D5 Pers (SSL), D2005 Pro, C, C#
BeitragVerfasst: 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. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2750

Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
BeitragVerfasst: Fr 29.12.06 14:08 
user profile iconwulfskin 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. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2750

Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
BeitragVerfasst: Fr 29.12.06 14:16 
Habe das jetzt so:
ausblenden 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
half ontopic starofftopic starofftopic starofftopic starofftopic starofftopic starofftopic starofftopic star
Beiträge: 226



BeitragVerfasst: Fr 29.12.06 17:08 
ausblenden Quelltext
1:
2:
3:
//setzt ein Backslash vor _ (underscore= und % (percent)
$string = str_replace('_','/_',$string);
$string = str_replace('%','/%',$string);

Backslash, nicht Slash:

ausblenden 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:

ausblenden volle Höhe Quelltext
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. Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2750

Windows Vista
Delphi 7, Delphi 2005 PE, PHP 4 + 5 (Notepad++), Java (Eclipse), XML, XML Schema, ABAP, ABAP OO
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2684
Erhaltene Danke: 32



BeitragVerfasst: 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.