OVH Cloud OVH Cloud

Soucis avec magic_quotes_gpc

27 réponses
Avatar
Zouplaz
Bonjour, je cherche une solution pour faire un addslashes systématiquement
si le système hôte n'a pas l'option magic_quotes_gpc activée (et donc que
les données provenants d'un POST/GET/COOKIE sont livrées telles quelles)

Tous les accès aux variables GET ou POST de mon application passent par
cette méthode :

function getRequestParam($paramName)
{
global $HTTP_SERVER_VARS;

if($HTTP_SERVER_VARS['REQUEST_METHOD']=="GET")
$result = $_GET[$paramName];
else
$result = $_POST[$paramName];

if (!get_magic_quotes_gpc())
$result = addslashes($result);
return $result;
}

Et malgré tout, sur le système de production (FreeBSD PHP 4.3.10 en CGI),
j'obtiens des erreurs lorsqu'une quote est insérée dans un champ de
formulaire.

Par ailleurs, je précise que j'utilise toujours la syntaxe suivante dans
mes requêtes SQL :

nom_de_champ_db = '$valeur_du_champ'

Je veux dire par là que je mets la valeur du champs elle même entre ''


Une idée ?

Par avance merci.

10 réponses

1 2 3
Avatar
ftc
Et si on veut différencier les actions en fonction de la provenance
GET ou POST, on peut ?



Ca n'a strictement aucun intérêt et ça prouve qu'on a rien compris au
film, mais techniquement, on peut.

a++;
JG


Je vois au moins un cas ou différencier les deux est intéressant : quand
on veut implémenter un système de cache.

On met en cache les données demandées via GET identifiables via une URI
et on ne met pas en cache celle demandées via POST.

Tiens, ça rappelle les spécifications HTTP.


Avatar
John GALLET
Bonjour,

magic_quotes_gpc est une abomination,
On est d'accord.


tu devrais plutôt faire en sorte de le désactiver.
Arf !


Ça a été créé pour empêcher que les débutants se prennent des failles,
Oui.


un site pro ne devrait surtout pas l'utiliser...


Et comment tu fais, gros malin, pour écrire une application qui va
tourner sur une machine dont tu ne maîtrise pas, par définition, la
configuration ? Tu crois que les clients vont te laisser tripoter ou
exiger la configuration de leur serveur ? Doux rêve.

Ce n'est pas POST/GET/Cookie qu'il faut échapper, ce sont les chaînes
que tu insères dans une requête.
Oui sur le papier. La seule solution de toutes façons, c'est le typage

fonctionnel(1).

Ces chaînes ne sont pas forcément POST/GET/Cookie, et il se peut que tu
veuilles utiliser les variables POST/GET/Cookie pour autre chose que
créer des requêtes.


Et dès lors que l'utilisation d'un SGBD est effective (je ne parle pas
des applications, et il en existe, qui n'ont pas besoin de SGBDR)
combien de ces chaînes en question ont une chance d'avoir l'apostrophe
dans la liste des caractères autorisés de toutes façons ? Dit autrement,
qu'est-ce qu'on en a à foutre de pourrir une chaîne qui est déjà
pourrie de toutes façons ? Une fois de plus, de toutes façons, seul le
typage fonctionnel est bon.

De plus l'échappement réalisé n'est valable qu'avec certains SGBDs, ce
qui empêche la portabilité.
Tous ceux que je connais (et j'en connais une tétrachiée) sauf Sybase.


(1) ce que j'appelle "typage fonctionnel" c'est une liste de triplets
NOM_TYPE - liste de caractères autorisés - traitements autres que le
filtrage sur les caractères autorisés. Par exemple :

SIMPLE_STRING - AZaz09- traitement rien d'autre.

TELEPHONE - 09parenthèses+- traitement rien d'autre

NOM_FAMILLE - AZaztrait d'union apostrophe- traitement : gérer les
postrophes.

etc...

a++;
JG

Avatar
bruno
Si cette directive est supprimée, comment pourra-t-on donc repérer si
les variables ont été polluées de ou non ?


elles ne seront plus polluées, car le resultat booléen de
get_magic_quotes_gpc()
te sert a savoir si les magic quotes sont actives... si elles sont
desactivées, plus de pollution...

Avatar
John GALLET
Re,

si elles sont desactivées, plus de pollution...


.. seulement des applications super buggées et des injections SQL encore
plus à la pelle que maintenant.

Si cette disparition n'est pas accompagnée d'un vrai moyen intelligent
et pratique pour faire génériquement de l'input sanitizing, ce sera une
connerie encore plus grosse que celle qui a consisté à l'ajouter.

JG

Avatar
loufoque
John GALLET a dit le 08/09/2005 à 13:08:

Et comment tu fais, gros malin, pour écrire une application qui va
tourner sur une machine dont tu ne maîtrise pas, par définition, la
configuration ?


Ben tu fais en sorte que ce soit toujours inactif, au lieu de faire en
sorte que ce soit toujours actif comme proposait Zouplaz.
Au début de chacun de tes scripts, tu détectes si c'est activé, et si
c'est le cas, tu appliques stripslashes récursivement sur $_GET, $_POST,
$_COOKIE et $_REQUEST.


Dit autrement,
qu'est-ce qu'on en a à foutre de pourrir une chaîne qui est déjà
pourrie de toutes façons ?


Je ne considère pas un paramètre extérieur comme une donnée pourrie.


Tous ceux que je connais (et j'en connais une tétrachiée) sauf Sybase.


Sybase, Microsoft SQL Server, SQLite, et sûrement d'autres, qui peut se
vanter de connaître tous les SGBDs existants, passés et futurs ?
Si on veut faire une application portable d'un SGBD à l'autre, on a pas
le choix.

De toutes façons le problème c'est pas qu'il en existe ou pas, mais que
c'est totalement illogique comme fonctionnement.

Je veux écrire des données en POST dans un fichier (ou quoique ce soit
d'autre), merde il me fout des slashes partout sans aucune raison.
Je ne veux pas que mes données soient préparées pour être utilisés avec
une application spécifique, je veux les données telles quelles ont été
soumises afin qu'elles soient utilisable avec n'importe quoi.


(1) ce que j'appelle "typage fonctionnel" c'est une liste de triplets
NOM_TYPE - liste de caractères autorisés - traitements autres que le
filtrage sur les caractères autorisés.


Je ne vois pas quel est l'intérêt de filtrer les données, si ce n'est
limiter les possibilités de l'application.

Si tu créés une chaîne dans une requête SQL, bien sûr qu'il faut faire
la correspondance entre chaîne PHP et chaîne SQL.
D'ailleurs il vaut mieux utiliser une fonction qui fait la
correspondance PHP -> SQL toute seule, comme ceci :
$sql->format('SELECT bidule FROM machin WHERE chose = %s', $chose)

De même, si tu affiches une donnée dans un document SGML ou XML, bien
sûr qu'il faut encoder les caractères reservés.

Et voilà, rien qu'avec le bon sens on évite la plupart des failles dont
sont victimes les débutants (injections SQL et XSS).

Avatar
loufoque
John GALLET a dit le 08/09/2005 à 09:26:

Source svp ?


php.internals
PHP 6.0 Wishlist

Le "bientôt" est donc relatif.

Avatar
John GALLET
Re,

Ben tu fais en sorte que ce soit toujours inactif, au lieu de faire en
sorte que ce soit toujours actif comme proposait Zouplaz.
Au début de chacun de tes scripts, tu détectes si c'est activé, et si
c'est le cas, tu appliques stripslashes récursivement sur $_GET, $_POST,
$_COOKIE et $_REQUEST.


Ce n'est **absolument pas rendre inactif**, c'est faire l'opération
inverse de celle qui est choisie par un autre contributeur dans le cas
où la configuration l'impose.

Son choix (qui est guidé par son besoin de s'interfacer avec un sgbdr)
c'est de par défaut considérer que toutes ses variables ont besoin
d'être échappées, le tiens, c'est de considérer que par défaut, tu veux
les variables brutes. Et puis ensuite tu recommences à jouer quand tu as
une requête SQL à faire. C'est une méthode, à mon avis la meilleure pour
oublier une variable et se faire entuber par une injection sql, mais sur
le papier, elle marche aussi bien.

Dit autrement, qu'est-ce qu'on en a à foutre de pourrir une chaîne
qui est déjà pourrie de toutes façons ?
Je ne considère pas un paramètre extérieur comme une donnée pourrie.



Lis ce que j'ai écrit. Si je sais pertinement que ledit paramètre
extérieur doit fonctionnellement contenir un numéro de téléphone, je
dois conclure qu'il est pourri s'il contient une apostrophe. Si je sais
qu'il contient un nom de famille, je sais pertinement qu'il peut
contenir ce caractère apostrophe donc je *dois* le gérer si cette donnée
est envoyée vers un sgbd.

Je veux écrire des données en POST dans un fichier (ou quoique ce soit
d'autre), merde il me fout des slashes partout sans aucune raison.
Une fois de plus, tu ne lis pas ce qu'on t'écrit. Si ton application n'a

pas de raisons d'échapper els apostrophes, il est *évident* que ça fout
seulement le bordel.

Je ne vois pas quel est l'intérêt de filtrer les données, si ce n'est
limiter les possibilités de l'application.
Eviter de stocker n'importe quoi, tout simplement. Eviter des erreurs

débiles, comme par exemple une erreur de syntaxe SQL quand on a un
espace dans une donnée entière. Toi qui parle de "logique", ça m'étonne
fortement comme comportement.

Si tu créés une chaîne dans une requête SQL, bien sûr qu'il faut faire
la correspondance entre chaîne PHP et chaîne SQL.
Ca n'a rien à voir. Si tu dois stocker un type de donnée de genre date

de naissance, il n'y a AUCUNE raison que tu te retrouves avec le
caractère @ ou * ou ! à l'intérieur, c'est AUSSI SIMPLE QUE CA.

D'ailleurs il vaut mieux
Non, pas "il vaut mieux", c'est *une* méthode (la tienne, entre autres).


Et voilà, rien qu'avec le bon sens on évite la plupart des failles dont
sont victimes les débutants (injections SQL et XSS).
Et avec encore moins de bon sens que tu décris, (parce que moi j'appelle

ça du codage nécessitant des connaissances techniques minimum des
attaques existantes), simplement en ayant une liste de caractères
autorisés explicitement par type de données, on a encore moins de problèmes.

Maintenant chacun sa méthode, loin de moi l'idée d'essayer de te
convaincre de faire quoi que ce soit différement de ce que tu fais
actuellement.
a++;
JG

PS : merci pour l'info et sa soruce, j'avoue que j'ai décroché de ces
listes il y a plusieurs années maintenant, j'ai déjà suffisement de mal
avec bugtrack.


Avatar
John GALLET
Re,

Je vois au moins un cas ou différencier les deux est intéressant :
Perso, je n'en ai pas encore rencontré. Ce qui ne veut pas dire qu'il

n'y a pas un cas tordu où ça peut servir, mais vu en revanche le nombre
de cas que j'ai vus où c'était de la connerie...

Dans le cas que tu décris, je ne dirais pas que c'est "intéressant" je
qualifierai plutôt ça de discriminant de type "à la grosse louche
baveuse". Tu pars du principe (grossier à mon sens) que seule une
requête faite par un humain qui entre des données avec ses petits doigts
potelés donnera des résultats différents. Quand bien même ce serait le
cas, il n'y a pas ensuite lieu d'aller chercher les données dans $_POST
ou $_GET selon le cas, on peut toujours aller dans $_REQUEST.

quand on veut implémenter un système de cache.
A mon sens, un système de cache, qui met donc en cache le résultat d'une

requête http, doit décider de mettre en cache ou non ledit résultat
selon un et un seul critère : la fréquence de mise à jour de ladite
ressource. Avec une invalidation automatique dudit cache quand on sait
qu'on peut détecter ladite modification.

On met en cache les données demandées via GET identifiables via une URI
et on ne met pas en cache celle demandées via POST.
Beaucoup trop grossier comme différenciation. Et si la donnée arrive

depuis un cookie tu fais quoi, cache ou pas cache ? (t'en utilise jamais
et tu as raison donc la question ne se pose pas, ok).

J'ai beau recevoir la demande par GET de telle courbe générée par la
GD-LIB (je risque pas de la recevoir par POST, ou alors faut être tordu)
et bien je vais ou non la mettre en cache selon sa fréquence de mise à
jour. Si ce sont les performances mensuelles du groupe oui, je la
calcule une fois par jour. Si c'est le cours de la valeur en bourse, je
la recalcule à chaque fois.
Pareil pour les requêtes POST, si je gère un moteur de recherche interne
à mon application, je peux très bien avoir intérêt à cacher les
résultats. Les contre-exemples ne manquent pas.

D'ailleurs, quand on utilise un cache de résultats de SGBDR, on fait
bien ça par rapport à la requête SQL, et donc on décide de mettre en
cache local (je ne parle par du cache mémoire du serveur SGBDR lui même)
uniquement par rapport à la fréquence des requêtes de DML hors select
sur la ou les tables impactées.

La méthodede transmission des données, on s'en fout.

a++;
JG

Avatar
ftc
Dans le cas que tu décris, je ne dirais pas que c'est "intéressant" je
qualifierai plutôt ça de discriminant de type "à la grosse louche
baveuse". Tu pars du principe (grossier à mon sens) que seule une
requête faite par un humain qui entre des données avec ses petits doigts
potelés donnera des résultats différents.


C'est sympa pour les contributeurs qui se sont cassé le c.. à mettre en
place des normes comme HTTP.

Dans la norme HTTP il est stipulé que les données GET sont mises en
cache par défaut sauf stipulation contraire et que les données POST ne
sont pas mises en cache sauf stipulation contraire.

Cette règle s'applique au navigateur et systèmes de cache. Rien
n'interdit de modifier le comportement au cas par cas.

Donc c'est pas compliqué, quand on reçoit du GET, on met en cache sauf
si ... quand on reçoit en POST on ne met pas en cache sauf si ...

Pareil pour les requêtes POST, si je gère un moteur de recherche
interne à mon application, je peux très bien avoir intérêt à cacher
les résultats. Les contre-exemples ne manquent pas.


Si tu mettais la requête en GET, tu bénéficierais du cache du navigateur
et de celui des proxy, la première chose à faire est donc de passer les
requêtes en GET avant de vouloir implémenter un cache en PHP.


Si tu ne fais pas la différenciation, ton appli doit prendre une
décision quand à la politique générale et on se retrouve avec une liste
phénoménale d'exceptions difficiles à maintenir et qui allourdissent le
code de façon totalement inutile. Si pour toi c'est une meilleure
solution, c'est ton droit de le croire.

Avatar
Olivier Miakinen

C'est sympa pour les contributeurs qui se sont cassé le c.. à mettre en
place des normes comme HTTP.


;-) Norme client-serveur, rappelons-le (cf plus bas).

Dans la norme HTTP il est stipulé que les données GET sont mises en
cache par défaut sauf stipulation contraire et que les données POST ne
sont pas mises en cache sauf stipulation contraire.


Voui voui voui, mais tu le dis toi-même :

Cette règle s'applique au navigateur et systèmes de cache. Rien
n'interdit de modifier le comportement au cas par cas.


Ben voilà. Ça s'applique au navigateur et au système de cache parce que,
contrairement au serveur, ils ne peuvent pas deviner si les données ont
été rafraîchies depuis la dernière requête. Sachant que les pages
statiques sont le plus souvent appelées par GET et les pages vraiment
dynamiques sont souvent appelées par POST, il n'y avait pas à se casser
le c... bien longtemps pour en déduire la règle par défaut (« sauf
stipulation contraire », tu le dis toi-même).

Pareil pour les requêtes POST, si je gère un moteur de recherche
interne à mon application, je peux très bien avoir intérêt à cacher
les résultats. Les contre-exemples ne manquent pas.


Si tu mettais la requête en GET, tu bénéficierais du cache du navigateur
et de celui des proxy, la première chose à faire est donc de passer les
requêtes en GET avant de vouloir implémenter un cache en PHP.


La première chose à faire, *côté serveur*, c'est de détecter quand les
données changent, et d'indiquer (la « stipulation contraire ») cet état
dans les réponses HTTP, et ce, que l'on passe par GET ou par POST.

Si tu ne fais pas la différenciation, ton appli doit prendre une
décision quand à la politique générale et on se retrouve avec une liste
phénoménale d'exceptions difficiles à maintenir et qui allourdissent le
code de façon totalement inutile. Si pour toi c'est une meilleure
solution, c'est ton droit de le croire.


La meilleure solution, c'est de commencer par lire ceci :
<http://www.mnot.net/cache_docs/> (adresse donnée par Pierre Goiffon
sur fciwa le 10 août dernier).


1 2 3