Escape problemen met PHP i.c.m. databases

Controleer altijd of get_magic_quotes_gpc() en get_magic_quotes_runtime() aan staan. Als 1 van deze twee aan staat, worden variabelen binnen PHP die enkele (') of dubbele (") quotes of backslashes (\) bevatten automagisch escaped. Dat wil zeggen dat een string die in PHP binnen komt via GET, POST of een cookie (gpc) die een ', " of \ bevat automagisch een \ voor die character krijgt. Bekijk het volgende voorbeeld:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<form method="get">

   <input
      name="test"
      type="text"
      value="Test: ', " and \"
   />
   <input type="submit" />
</form>
<pre>
<?
if ( get_magic_quotes_gpc () ) {
   echo 'Magic quoting with get, post or cookie is enabled', "\n";
}


print_r ( $_GET );
?>


Uitvoer met get_magic_quotes_gpc aan, na submit:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
Magic quoting with get, post or cookie is enabled
Array
(
    [test] => Test: \', \" and \\
)


Het is het overwegen waard om zelf de controle te houden op het escapen van variabelen, om te voorkomen dat je bijvoorbeeld in <input ...> velden een ongewenste backslash krijgt.

Mijn voorkeur heeft het dan ook om in de code te checken of er al ge-escaped is, en zo ja: die escape characters weer te verwijderen:

Uiteraard is het ook een optie om je configuratie helemaal naar je hand te zetten, maar je kunt een reden om dat niet globaal te doen en de magic quotes directives kun je niet altijd per script aan of uit zetten, behalve magic_quotes_runtime (zie set_magic_quotes_runtime (). Daarnaast is het het overwegen waard om je scripts zo portable mogelijk te maken (onafhankelijk van configuraties)

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?
set_magic_quotes_runtime ( 0 );

if ( get_magic_quotes_gpc () ) {
   foreach ( $_POST as $key => $value ) {
      $_POST [ $key ] = stripslashes ( $value );
   }

   foreach ( $_GET as $key => $value )
   // etcetera ...
}
?>


Vervolgens kun je met je eigen escape functies de juiste escapes doen:


Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
define ( 'QUOTE_SINGLE',      39 );
define ( 'QUOTE_DOUBLE',      34 );
define ( 'QUOTE_BACKTICK',    96 );
function
mysql_escape ( $string, $quote_char_code = QUOTE_SINGLE ) {
   $quote_char = chr ( $quote_char_code );

   return
      $quote_char .
         str_replace (
            array ( '\\', $quote_char ),
            array ( '\\\\', '\\' . $quote_char ),
            $string
         )
      $quote_char;
}

// ....
$query = "
   INSERT INTO
      table(fieldname)
   VALUES(
      "
. mysql_escape_string (
         'Dit " is \' een string \\ met wat \ bullshit \\\' '
      ) . "
   );
"
;
?>



Overigens is het ook te overwegen de ANSI-SQL wijze van escapen te hanteren, door een enkele quote te escapen met een extra enkele quote:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
<?php
function ansi_sql_escape ( $string ) {
   return str_replace ( "'", "''", $string );
}

?>


Om goed te testen of je escaping wel goed werkt, probeer het volgende in te voeren in je database door middel van een formuliertje:

Quote:
' \' '' \\' \\\' " \" "" \\" \\\" ` \` `` \\` \\\`

Wanneer je bij inserten van deze string geen foutmelding krijgt en je krijgt exact dezelfde string terug bij het uitlezen van die string uit je database, werkt je escaping perfect:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
if ( isset ( $_GET [ 'string' ] ) ) {
   $query = '
      INSERT INTO
         table(fieldname)
      VALUES(
         ' . mysql_escape ( $_GET [ 'string' ] ) . '
      );
   ';
   mysql_query ( $query )
      or trigger_error ( "Fout: " . mysql_error () . "<br>query: " . $query );
   $id = mysql_insert_id ();
   $query = '
      SELECT
         fieldname
      FROM
         table
      WHERE
         field_id=' . $id;
   $res = mysql_query ( $query )
      or trigger_error ( "Fout: " . mysql_error () . "<br>query: " . $query );
   $selected_field = mysql_result ( $res, 0, 0 );
   echo 'inserted: ', $_GET [ 'string' ], '<br>';
   echo 'retrieved: ', $selected_field, '<br>';
   echo 'ok?: ', $selected_field == $_GET [ 'string' ], '<br>';
}
?>


<form method="get">
<input type="text" name="string" />
<input type="submit" />
</form>

« Lees de omschrijving en reacties

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.