Attention à ne pas confondre deux choses:
• Valider la donnée d'entrée (GET, POST etc) pour que son "typage" soit correct; ie: je veux un nombre qui sera un id donc je sanitize ou filtre l'entrée pour être sûr d'avoir un entier)
• Encoder la donnée pour l'insérer à un endroit donné (JSON, HTML, XML); ie: je veux afficher le pseudo du joueur dans un strong, donc je fais un echo "<strong>" . htmlentities($user->name, 'utf-8') . "</strong>"
Dans l'exemple de Sôbi, FILTER_SANITIZE_NUMBER_INT: pas de soucis, on veut effectivement un entier car l'id est un entier par nature. Mais FILTER_SANITIZE_SPECIAL_CHARS, non car on veut en fait un texte (osef de ce qu'il y a dedans), donc cette entrée n'aura pas de FILTER_* particulier.
Dans un second temps, ces données sont surement utilisées ailleurs dans le code (dans un HTML, dans un JSON, dans une requête SQL, etc). A chacun de ces endroit-là correspondra un "encodage" de la donnée:
• "<strong>" . htmlentities($myData, 'utf-8') . "</strong>"
• json_encode($myData)
• prepare_query... execute_query($preparedQuery, array('myParam' => $myData))
• $domNode->appendChild(new DOMText($myData))
Il y a donc bien deux opérations à distinguer pour ne pas s'emmêler: le filtrage des entrées, qui sert à s'assurer de l'existence et de la nature de ce que le serveur reçoit, et "l'encodage des sorties", qui sert à s'assurer qu'une donnée est insérée/utilisée correctement dans une chaine de caractères (HTML) ou autre.
C'est pour cette raison qu'il existe finalement très peu de FILTER_*: il n'y a pas de FILTER_JSON par exemple, car en pratique, la donnée d'entrée doit être une texte (FILTER_UNSAFE_RAW me semble-t-il) et l'échappement json se fait dans la sortie du serveur (echo json_encode(...)).
Si je reprends:
Alors tu rates la partie "encodage", car ton $soustrait, ton $ID, ton $ressources sont balancés directement par concaténation dans ta requête. L'encodage se ferait par un
ou
Mais il n'existe pas tellement de "sql_escape()" donc je te le déconseille.
Alors, oui, si tu te dis "mais $ID est un entier: je l'ai filtré en le récupérant du $_POST[] donc c'est pas grave?", alors tu as raison, car "sql_escape({INT}) == {INT}" (ie: un entier ne change pas quand il est échappé). Mais cela vient juste de ça! Supposons que, pour une raison quelconque, le SQL n'accepte les entiers qu'en hexadécimal, alors "sql_escape({INT}) != {INT}" (ie: 100 deviendra 0x64). Donc, même s $ID est un entier "et qu'on peut donc le mettre là dans la requête sans problème", je te le déconseille: traite-le comme une donnée quelconque à échapper, osef que le résultat de cet échappement" soit le même.
Cela te simplifiera éééénormément le raisonnement car tu ne chercheras pas à savoir ce qu'une variable contient pour savoir s'il faut ou non l'échapper: tu échappes tout, et dans tes variables, tu stockes toujours des données réelles (non-échappées, mais éventuellement filtrées).
Tout ce qui est sorti du serveur peut avoir été modifié: JSON, HTML, COOKIES, etc.
Et n'oublie pas que rien n'oblige l'utilisateur à être passé par ton interface: tu peux très bien créer ta propre interface faisant n'importe quelle requête.
• Valider la donnée d'entrée (GET, POST etc) pour que son "typage" soit correct; ie: je veux un nombre qui sera un id donc je sanitize ou filtre l'entrée pour être sûr d'avoir un entier)
• Encoder la donnée pour l'insérer à un endroit donné (JSON, HTML, XML); ie: je veux afficher le pseudo du joueur dans un strong, donc je fais un echo "<strong>" . htmlentities($user->name, 'utf-8') . "</strong>"
Dans l'exemple de Sôbi, FILTER_SANITIZE_NUMBER_INT: pas de soucis, on veut effectivement un entier car l'id est un entier par nature. Mais FILTER_SANITIZE_SPECIAL_CHARS, non car on veut en fait un texte (osef de ce qu'il y a dedans), donc cette entrée n'aura pas de FILTER_* particulier.
Dans un second temps, ces données sont surement utilisées ailleurs dans le code (dans un HTML, dans un JSON, dans une requête SQL, etc). A chacun de ces endroit-là correspondra un "encodage" de la donnée:
• "<strong>" . htmlentities($myData, 'utf-8') . "</strong>"
• json_encode($myData)
• prepare_query... execute_query($preparedQuery, array('myParam' => $myData))
• $domNode->appendChild(new DOMText($myData))
Il y a donc bien deux opérations à distinguer pour ne pas s'emmêler: le filtrage des entrées, qui sert à s'assurer de l'existence et de la nature de ce que le serveur reçoit, et "l'encodage des sorties", qui sert à s'assurer qu'une donnée est insérée/utilisée correctement dans une chaine de caractères (HTML) ou autre.
C'est pour cette raison qu'il existe finalement très peu de FILTER_*: il n'y a pas de FILTER_JSON par exemple, car en pratique, la donnée d'entrée doit être une texte (FILTER_UNSAFE_RAW me semble-t-il) et l'échappement json se fait dans la sortie du serveur (echo json_encode(...)).
Si je reprends:
Code :
prepare('UPDATE table SET tot = "'.$soustrait.'" WHERE ID = "'.$ID.'" AND obj = "'.$ressource.'"')
Alors tu rates la partie "encodage", car ton $soustrait, ton $ID, ton $ressources sont balancés directement par concaténation dans ta requête. L'encodage se ferait par un
Code :
$prepared = prepate('UPDATE table SET tot = ? WHERE ID = ? AND obj = ?)
execute($prepared, array($soustrait, $ID, $ressource)
Code :
query('UPDATE table SET tot = "'.sql_escape($soustrait).'" WHERE ID = "'.sql_escape($ID).'" AND obj = "'.sql_escape($ressource).'"')
Alors, oui, si tu te dis "mais $ID est un entier: je l'ai filtré en le récupérant du $_POST[] donc c'est pas grave?", alors tu as raison, car "sql_escape({INT}) == {INT}" (ie: un entier ne change pas quand il est échappé). Mais cela vient juste de ça! Supposons que, pour une raison quelconque, le SQL n'accepte les entiers qu'en hexadécimal, alors "sql_escape({INT}) != {INT}" (ie: 100 deviendra 0x64). Donc, même s $ID est un entier "et qu'on peut donc le mettre là dans la requête sans problème", je te le déconseille: traite-le comme une donnée quelconque à échapper, osef que le résultat de cet échappement" soit le même.
Cela te simplifiera éééénormément le raisonnement car tu ne chercheras pas à savoir ce qu'une variable contient pour savoir s'il faut ou non l'échapper: tu échappes tout, et dans tes variables, tu stockes toujours des données réelles (non-échappées, mais éventuellement filtrées).
Tout ce qui est sorti du serveur peut avoir été modifié: JSON, HTML, COOKIES, etc.
Et n'oublie pas que rien n'oblige l'utilisateur à être passé par ton interface: tu peux très bien créer ta propre interface faisant n'importe quelle requête.