OVH Cloud OVH Cloud

[Long] Pratiques de codage php et webapps

120 réponses
Avatar
John Gallet
Bonjour,


NB1 : xpost fr.comp.lang.php et fu2 fr.comp.securite (les deux sont
modérés).

Après moult tergiversations, je laisse le fu2 sur fr.comp.securite car
on dépasse le cadre du langage PHP et que les failles à débattre sont
majoritairement
humaines et non liées au langage. J'encourage plus que vivement les
habituels lecteurs/contributeurs de fclphp à suivre la discussion sur
fcs (et à le
consulter régulièrement une fois cette bonne habitude prise ;-)...)

Je me porte volontaire pour essayer de faire une synthèse de la
discussion qu'on pourra intégrer dans l'une des deux FAQs et référencer
depuis l'autre.

NB 2 : Cet article étant long et fcs étant modéré, je rappelle aux
contributeurs qui seraient tentés de le citer intégralement que leur
réponse n'a aucune chance d'être publiée. Si vous avez un doute sur la
bonne manière de répondre sur un forum usenet, usez et abusez de
http://www.giromini.org/usenet-fr/repondre.html


Suite aux divers questions/trolls sur la sécurité des applications
écrites en PHP dans une optique web, je lance un petit débat sur les
pratiques de codage en PHP apportant ou non un vrai "plus" de sécurité.

J'entends par "faille de sécurité" une erreur de codage ou de conception
qui permet de passer outre une procédure d'authentification, d'avoir
accès à des données non publiques, ou de modifier/détruire des
données/des scripts, exclusivement dans une optique web, avec php comme
langage dans mon esrit à l'origine, mais on pourra élargir à d'autres
langages/plateformes de web dynamique comme perl, jsp, asp, .net etc...

Les questions sont les suivantes :

Question 1 :

Quelles sont les principales failles existantes dans les scripts PHP que
vous avez rencontrées ? Quels risques induisaient-elles ? Comment les
avez vous corrigées ?

Question 2 :

Quelles sont les principales fausses vérifications de sécurité que vous
connaissez ? Comment peut-on les contourner (indiquer la difficulté
pour y arriver) ou pourquoi ne sont-elles pas fiables ou non applicables
sur le principe même ?

Question 3 :

Pensez vous à des failles théoriques potentielles que vous n'avez pas
encore vérifiées en pratique ?

------------
Je commence bien entendu :

Question 1 (failles existantes):
a) variables non itilialisées en register_globals=On (injection de
variables)
Risque : principalement accès non autorisés, mais tout est possible.
Correction : initialiser ses variables (Sans blague...), ou utiliser des
fonctions/des objets car ils snt insensibles à l'injection de variables.
Piège : croire qu'on est toujours en register_globals=Off et coder comme
un cochon.
Correction : idem.

b) include dynamiques (ex include($toto);)

Risque : exécution sur sa machine de n'importe quel code souhaité par
l'attaquant (installation de back-doors, défigurations, etc....
Correction : ne pas utiliser d'includes dynamiques ou vérifier que le
fichier est bien local si hébergement dédié. Renforcer les restrictions
d'include_path. Attention, depuis php5, file_exists peut éventuellement
renvoyer TRUE sur des fichiers distants (à restester, je n'ai pas poussé
plus loin que le "tip php5" du manuel).
Piège : essayer de se renforcer avec include($toto.'.php');
Contournement : $toto="[target]/script_sans_extension"; par exemple.

c) injection SQL.
Risque : accès non autorisés, corruption de données
Correction : filtrage des variables, échappement de ' et " par le
caractère ad hoc pour la base de données (\ pour mysql, ' pour sybase
etc...)

d) confiance dans les variables venant de l'extérieur. Par exemple,
recalculer une facture à payer en utilisant un prix transmis par un
champ HIDDEN ou calculé en javascript. Ne pas revalider la donnée parce
qu'elle l'a été en JavaScript.
Risque : multiples. Accès non autorisés, corruption de données, etc...
Correction : ne faire confiance qu'à des données conservées côté serveur
(refaire une requête sgbd pour obtenir le prix de l'article, les frais
de port, etc...). Faire avant tout les validations de cohérence des
données côté serveur et non en javascript.

e) uploads de fichiers.
Outre les failles du langage php lui même qui apparaissent parfois à ce
sujet, les tutoriels que j'ai vus n'insistent pas assez sur le besoin de
faire attention aux extensions autorisées par rapport aux extensions
parsées sur le serveur. Si le serveur considère comme du code php le
fichier toto.php.txt, il faut interdire tout nom de fichier contenant
.php. dans son nom. Ceci doit venir en complément d'une liste
restrictive d'extensions explicitement autorisées (.jpg, .gif, .doc
etc...). Je suis plus particulièrement intéressé sur ce point par les
vérification purement serveur permettant de vérifier le type de fichier
traité.

f) utilisation de header("Location:...)
Algo (erronné)
1. vérification de cohérence
2.1 si problème alors header("Location:bad.php"); // jusqu'ici tout va
bien
2.2 si ok alors header("Location:ok.php"); // et plouf dommage, il
suffit d'appeler directement ok.php avec n'importe quels arguments et
tout passe.
Correction :
2.1 si problème require('erreur.php'); exit();
2.2 (sinon) require('traitement.php'); // rappel : toute variable locale
est alors définie dans traitement.php

g) appels systèmes non filtrés
Dans le même genre que les includes dynamiques, passer directement la
saisie de l'utilisateur à exec() ou system(). Personnellement, j'ai
tendance à interdire tout exécution de code directe, filtrée ou par (je
remplace les actions possibles par des cases à cocher et j'exécute ce
qu'il faut). Peut-être est-ce par trop parano et que 'lon peut autoriser
certaines choses.
Risques : donner la main sur votre machine à un attaquant.
Correction : ne jamais passer quoi que ce soit qui vient de l'extérieur
en argument, mais c'est parfois trop restrictif.

Question 2 (fausses vérifications):

a) vérifier que la donnée a bien été transmise par la méthode POST sous
prétexte qu'elle vient d'un formulaire.
Contournement : il suffit d'envoyer une donnée vérolée par post, que ce
soit en modifiant du html ou en utilisant la librairie CURL par exemple
pour de l'attaque massive. C'est le contenu de la donnée qu'il faut
vérifier, pas son mode de transmission.

b) Vérifier que les données viennent bien "de mon site" en utilisant
HTTP_REFERRER.

Une idée (qui n'est pas de moi) et que je n'ai pas réussi à mettre en
oeuvre : injection SQL par des entiers ou plus généralement injection
SQL insensible aux habituelles vérifications sur les quotes.

Soit la requête : "UPDATE .... WHERE id=$i " avec id de type entier
(typiquement : autoincrement)
But de la manip : injecter dans $i une chaîne transformant la requête en
(par exemple):
"UPDATE ... WHERE id=0 OR 1=1"
(requête qui va corrompre les données en impactant tous les rangs de la
table)
Moyen sous mysql : utiliser la fonction mysql CHAR et complèter la
chaîne en hexa. Mais je n'ai pas réussi à le faire, je me prends ou du
syntax error ou une chaîne non interprêtée.

Espérant faire avancer le shimili... le shcibi... le biniou.

JG

10 réponses

Avatar
Dominique Blas
Nicolas George wrote:

Dominique Blas wrote in message
<41ae58be$0$30405$:
Je sais que ce type de saisie ouverte doit être acceptée parfois (Wiki,
forums). Sans aller jusqu'à recoder un interpréteur je pense qu'une
translation est peut-être une solution.
Je m'explique. Le système de filtrage explicité auparavant intervient dès
la soumission du formulaire en éléminant les caractères inacceptables. On
peut très bien imaginer qu'au lieu de les éliminer dans le cas d'une zone
ouverte il les translate ( ex : ';' devient 0xff, '$' devient 0xfe, etc)


Je suis désolé, mais j'ai envie de dire que c'est n'importe quoi.

Si je commande à un informaticien un serveur pour un forum d'entraide
mathématique (donc où il faut taper des formules), que l'informaticien me
livre le serveur, mais qu'il me dit « attention, pour des raisons de
sécurité, il n'y aura pas marqué < et > dans les textes, mais 0xFF et
0xFE », moi je vais avoir envie de lui répondre « attention, pour des
raisons de sécurité, il n'y aura pas marqué 10000 EUR sur votre chèque,
mais 0x00 EUR ».
Ce n'est pas ce que j'ai écrit. Je ne demande pas à l'internaute de saisir

0xFE mais bien < > ou ?.
0xFE c'est le format interne de codage dans le SGBD.
Bien entendu au réaffichage ce 0xFE est retranscrit en <, > ou ?.
C'est là que le bât blesse car cela n'évite pas le XSS.


S'il est dans les spécifications d'autoriser tel ou tel caractère, il faut
l'autoriser, et la seule manière de le faire est de les remplacer par leur
forme inerte.

(Et comme cette forme inerte dépend de ce à quoi on envoit ces caractères,
il ne faut le faire qu'au moment où on sait ce qu'on va en faire.)

voire les coder sur 2 octets (UTF-8)).


On ne peut pas coder arbitrairement n'importe quel caractère sur deux
octets en UTF-8. La correspondance caractère <-> codage UTF-8 est
totalement univoque (avec caractère = codepoint Unicode).
Oui mais rien ne m'empêche de choisir une plage pour y effectuer mes

translations.

Enfin bref, de toute manière cetet histoire de translation ne règle pas tous
les pb loin s'en faut. Voir mon post précédent.

En ce qui concerne le site de mathématique soit on accepte la possibilité de
XSS ou d'IFRAME soit on réaffiche le tout sous forme d'une image et
lorqu'on l'internaute demande à corriger sa formule et bien on échappe les
caractères litiigeux (< >) en expliquant à l'internaute qu'il doit effacer
le caractère d'échappement vant sa soumission.

Que peut-on faire d'autre ?

db
--
email : usenet blas net


Avatar
Dominique Blas
Nicolas George wrote:

John Gallet wrote in message :
Est-ce que je résume ton point de vue en disant ceci :

Il faut rendre inerte du code offensif pouvant potentiellement être
dangereux lors de sa relecture ultérieure par une application. Comme les
trsnformations nécessaire à le rendre inerte dépendent de l'application
(par exemple : transformer en entités html pour un navigateur ou
[INSERER ICI UN AUTRE EXEMPLE DANS UNE AUTRE APPLI] il est préférable de
faire ces traductions quand on récupère les informations par type de
canal de sortie.


Oui, c'est exactement ça.
Et-on certain que la transformation en entités HTML ne présente aucun risque

pour un navigateur comme IE ?


Auquel j'ajouterai :

Si on a un seul canal de sortie (par exemple, l'interface html de
l'administrateur) on peut aussi faire la transformation avant le
stockage.


Oui, c'est vrai, mais pour que ce soit une bonne idée, il faut :

- être sûr qu'on ne voudra jamais ajouter un nouveau canal de sortie
(serveur NNTP, document PDF, ou que sais-je) ;
pour éluder ce cas il suffit d'utiliser un format intermédiaire (XML) et

c'est à partir de ce format que l'on protégera ses sorties selon le canal
utilisé.


- être sûr qu'on ne voudra pas ajouter des traitements (mise en valeur de
certains mots, par exemple) après le stockage.
Là encorel e format intermédiare peut-être un secours.

db

--
email : usenet blas net


Avatar
Nicolas George
Dominique Blas wrote in message
<41af3975$0$18770$:
Ce n'est pas ce que j'ai écrit. Je ne demande pas à l'internaute de saisir
0xFE mais bien < > ou ?.


C'est bien ce que j'ai compris.

0xFE c'est le format interne de codage dans le SGBD.


Alors là, ça ne sert complètement à rien, puisque < et > sont totalement
inertes dans des chaînes stockées dans un gestionnaire de bases de données.
C'est ' et qu'il faut protéger, et le gestionnaire de base de données
décodera ça lors du stockage.

Bien entendu au réaffichage ce 0xFE est retranscrit en <, > ou ?.
C'est là que le bât blesse car cela n'évite pas le XSS.


Évidemment, si on remet tel quel < et >, ça ne va pas poser. Il faut aussi
penser qu'on s'adresse à un navigateur en HTML (alors que la source des
données n'était pas du HTML !), et qu'en HTML, < s'écrit &lt; et > s'écrit
&gt;. Si on pense à faire ça, il n'y a aucun problème.

Oui mais rien ne m'empêche de choisir une plage pour y effectuer mes
translations.


Ah, d'accor. Bof.

Enfin bref, de toute manière cetet histoire de translation ne règle pas tous
les pb loin s'en faut.


Ce n'est pas que ça ne règle pas les problèmes, c'est complètement
déconnecté des problèmes. C'est comme de proposer de changer la fenêtre
parce que la porte en ferme pas bien : rien à voir.

En ce qui concerne le site de mathématique soit on accepte la possibilité de
XSS ou d'IFRAME soit on réaffiche le tout sous forme d'une image et
lorqu'on l'internaute demande à corriger sa formule et bien on échappe les
caractères litiigeux (< >) en expliquant à l'internaute qu'il doit effacer
le caractère d'échappement vant sa soumission.

Que peut-on faire d'autre ?


Les coder comme entités HTML, ni plus, ni moins.

Avatar
Nicolas George
Dominique Blas wrote in message
<41af37fe$0$18770$:
Si seulement le fait d'afficher des htmlentities protégeait le navigateur
mais il y a de bonnes chances que celui-ci interprète ces entités comme le
fait IE lorsqu'il croise des codes Unicode : il les interprète de manière
récursive jsuqu'à ce qu'il n'y en ait plus. D'om les immenses facilités de
phishing (ou d'obscurcissement de l'URL réellement pointé) dont on
dispose. Que peut-on faire contre ça ?


Euh, je ne sais pas ce à quoi fait référence de « codes Unicode »
qu'internet explorer « interprète » « jusqu'à ce qu'il n'y en ait plus »,
mais je tiens à souligner que si le codage de < et > par &lt; et &gt; ne
protégeait pas le développement des entités, ça se verrait tout de suite :
aucun tutoriel sur le HTML, ne fonctionnerait, pour commencer.

Donc pour répondre à un autre message : oui, on est certain que &lt; et &gt;
sont parfaitement inertes sur n'importe quel navigateur qui a été testé plus
de cinq minutes (et internet explorer a beau être plein de trous, je pense
qu'on peut être sûr qu'il a été testé au moins dix minutes).

(Ça devient faux si on va utiliser du javascript pour aller lire ces
&lt;...&gt; (que javascript verra comme <...>) et ensuite les réinjecter
dans le document sans échappement avec un document.write. Mais si on fait
ça, c'est vraiment qu'on le fait exprès, je ne vois pas comment on peut
faire une horreur de ce genre par accident.)

Ce qu'on peut faire en GET on le fait de la même manière en POST, donc
autant interdire le GET non ?


Je ne suis pas d'accord avec ça : GET et POST ont des sémantiques assez
différentes : GET sert à obtenir une information du serveur, POST sert à
modifier l'état du serveur. En particulier, il est normalement anodin de
demander le rechargement d'une page obtenue par GET (parce que le transfert
a été interrompu et qu'on veut le reprendre, par exemple), tandis que
recharger une page obtenue par un POST peut causer une nouvelle exécution de
l'action demandée par POST.

Dans l'exemple d'un forum, la consultation des messages devrait se faire par
GET, et l'envoi d'un nouveau message par POST. À titre personnel, je trouve
qu'une requête POST ne devrait presque jamais aboutir sur une page, mais
seulement sur une redirection vers une autre page (en GET). Ainsi, il n'y a
pas de risque de poster un message en double avec un rechargement
intempestif.

Avatar
Dominique Blas
Nicolas George wrote:

Dominique Blas wrote in message
<41af3975$0$18770$:
Ce n'est pas ce que j'ai écrit. Je ne demande pas à l'internaute de
saisir 0xFE mais bien < > ou ?.


C'est bien ce que j'ai compris.

0xFE c'est le format interne de codage dans le SGBD.


Alors là, ça ne sert complètement à rien, puisque < et > sont totalement
inertes dans des chaînes stockées dans un gestionnaire de bases de
données.
Pas dans un SGBD XML qui prend progressivement le pas sur les SGBD <<

classiques >>.
C'est ' et qu'il faut protéger, et le gestionnaire de base de
données décodera ça lors du stockage.

Bien entendu au réaffichage ce 0xFE est retranscrit en <, > ou ?.
C'est là que le bât blesse car cela n'évite pas le XSS.


Évidemment, si on remet tel quel < et >, ça ne va pas poser. Il faut aussi
penser qu'on s'adresse à un navigateur en HTML (alors que la source des
données n'était pas du HTML !), et qu'en HTML, < s'écrit &lt; et > s'écrit
&gt;. Si on pense à faire ça, il n'y a aucun problème.
Oui mais rien ne m'empêche de choisir une plage pour y effectuer mes
translations.


Ah, d'accor. Bof.

Enfin bref, de toute manière cetet histoire de translation ne règle pas
tous les pb loin s'en faut.


Ce n'est pas que ça ne règle pas les problèmes, c'est complètement
déconnecté des problèmes. C'est comme de proposer de changer la fenêtre
parce que la porte en ferme pas bien : rien à voir.

En ce qui concerne le site de mathématique soit on accepte la possibilité
de XSS ou d'IFRAME soit on réaffiche le tout sous forme d'une image et
lorqu'on l'internaute demande à corriger sa formule et bien on échappe
les caractères litiigeux (< >) en expliquant à l'internaute qu'il doit
effacer le caractère d'échappement vant sa soumission.

Que peut-on faire d'autre ?


Les coder comme entités HTML, ni plus, ni moins.


Tiens il faudra que je fasse l'essai.
Mais bon je suis paresseux.

Ainsi le circuit est le suivant, prenons l'exemple de nos < et >.
Monsieur Internaute saisit son texte sous cette forme (1) :
blah, blah, <b>blah</b> ..<script> ;... </script>
Ceci est traduit en interne de manière (2) :
blah, blah, &lt;b&gt;blah&lt;/b&gt; ..&lt;script&gt; ;... &lt;/script&gt;

OK ?

Lors d'un réaffichage, le serveur d'applications expédie donc la chaîne
précédente ( la (2) ) pour affichage. C'est très bien et elle apparaît donc
comme elle a été saisie ( format (1) ). Magnifique. Excepté que la mise en
gras que souhaitait l'internaute a sauté, elle.
Et si le serveur doit expédier l'info à destination d'une zone TEXTAREA en
vue d'être modifiée (édition d'un message avant soumission par exemple) le
serveur doit bien l'expédier au format 1 et non 2 n'est ce pas ?
Ca complique tout de même.

Certains forums << pro >> ont fait le choix d'éliminer tout ce qui traîne
entre < et >. Pourquoi pas.
Mais le fin du fin ne serait-il pas un traitement au cas par cas c'est à
dire ne n'autoriser que les balises << sans danger >> et correspondant à
une mise en forme ?
Mais pour cela il faudrait pousser le vice jusqu'à contrôler également les
attributs de ces balises.
Ca devient chaud.

db

--
email : usenet blas net


Avatar
Dominique Blas
Nicolas George wrote:

En fait ce qui me gêne dans le "désamorçage a posteriori" c'est que je
suis quasi certain qu'à un moment ou à un autre, "on"(1) va oublier de
le faire. Alors que si je fais le déminage tout de suite, je suis
peinard.
Notons que la notion initiale de sécurité dans le développement a


passablement évolué depuis le premier article.
En effet, au départ, il s'agissait de protéger le système serveur.
Une des propositions était de filtrer les entrées.

Là nous parlons de protéger l'interface homme-machine de l'internaute
(navigateur HTML, lecteur PDF, navigateur WML, etc) à l'aide, par exemple,
d'un filtrage des sorties.
CEla fait-il toujours partie du périmètre initial ?

db

--
email : usenet blas net


Avatar
Cedric Blancher
Le Fri, 03 Dec 2004 09:01:56 +0000, Dominique Blas a écrit :
Lors d'un réaffichage, le serveur d'applications expédie donc la chaîne
précédente ( la (2) ) pour affichage. C'est très bien et elle apparaît donc
comme elle a été saisie ( format (1) ). Magnifique. Excepté que la mise en
gras que souhaitait l'internaute a sauté, elle.
Et si le serveur doit expédier l'info à destination d'une zone TEXTAREA en
vue d'être modifiée (édition d'un message avant soumission par exemple) le
serveur doit bien l'expédier au format 1 et non 2 n'est ce pas ?
Ca complique tout de même.


C'est pour cela que pas mal de forum ont leur propre balisage, utilisant
entre autres des [] et non des <>. Ça ne rend pas la saisie plus
difficile ou fastidieuse et, amha, évite pas mal de problèmes.

--
GB> une amie déléguée médicale a reçu un avenant de contrat de travail
Rappel à tous : Il serait préférable de BIEN LIRE la question avant de
répondre, la salariée est protégée puisqu'elle est DÉLÉGUÉE SYNDICALE
-+-JG in GNU : Le père Emptoire s'enmmèle les pinceaux -+-

Avatar
John Gallet
Re,


Notons que la notion initiale de sécurité dans le développement a
passablement évolué depuis le premier article.


Je ne pense pas, en revanche comme on a réglé les cas "simpels" on
s'attaque (si je puis dire) au cas le plus complexe à men sens des xss
avec stockage et activation ultérieure.

En effet, au départ, il s'agissait de protéger le système serveur.


Pas au sens que j'ai donné d'une faille de sécurité, qui était
totalement indépendante de qui on vérolait. De plus, si pas un xss on te
pique un id_session quand tu es loggué admin de l'application, ça
pourrait faire désordre.

Là nous parlons de protéger l'interface homme-machine de l'internaute
(navigateur HTML, lecteur PDF, navigateur WML, etc) à l'aide, par exemple,
d'un filtrage des sorties.
CEla fait-il toujours partie du périmètre initial ?


Je ne vois pas pourquoi ça n'en ferai pas partie. Il s'agit de se
protéger de code offensif "dormant".

En tous cas, ça m'intéresse fichtrement, et je ne vois pas de raisons
particulière d'ouvrir un autre thread. En revanche, je ferai
probablement un nouvaeu thread pour la proposition de synthèse. Selon sa
taille, je verrai avec l'équipe de modération si je poste en intégral ou
si je mets un lien http.

a++
JG

Avatar
John Gallet
Re,

contre une injection SQL, tu peux très bien la recevoir dans une de tes
variables POST. Je sens que je n'ai pas encore compris tous les
principes que tu mets en oeuvre dans ta notion d'automate à ce sujet.
Quand tu dois écrire ta clause WHERE, c'est bien parce que tes données
user sont filtrées que tu es protégé, pas parce qu'elles ont été
transmises en POST.
Oui, dans le cas d'un POST mais s'il s'agit d'un GET et que le code manipule

de manière transparente pour le développeur les GET et les POST (comme
c'est le cas dans PHP) et que le développeur n'a spécifiquement filtré que
les POST ? C'est con je sais mais ça arrive.


Je vois ce que tu veux dire et j'avoue que je n'avais pas pensé à cette
faille potentielle supplémentaire qu'itroduisent les braves gens qui
différencient GET et POST (j'ai filtré l'un mais pas de bol j'ai pas
filtré l'autre).
En effet, on pourrait en PHP s'emmêler les crayons vu qu'il y a _GET et
_POST.
Personnellement, j'utilise uniquement $_REQUEST qui rend transparente la
méthode de transmission, et je n'y accède que dans la fonction qui
filtre les entrées, donc je n'avais pas pensé à ce gag.


En fait la redirection n'est pas une protection en soi : elle ne fiat pas
tout loin de là mais contribue, directement, à l'instar du filtrage des
entrées à la sécurité du développement.
Je pense que je commence à comprendre l'apport, vu sous cet angle là.


jamais à traiter le sujet : dans aucun des sites développés par moi il n'y
avait de zone de texte complètement libre.
T'as du bol... Moi j'en ai déjà eu un certain nombre; J'aurais pu faire

l'impasse sous prétexte que les pages perettant de les remplir étaient
sur de l'intranet, mais vu qu'il y a autant, sinon plus, d'attaques
internes à l'entreprise que d'attaques externes...

Par ailleurs, si tu as 100 possibilités d'erreurs à la connexion dans
l'ensemble de ton code tu auras 100 fois
if($dad=úLSE)
{
require('std_excuse.html');
exit();
}
?
bah non, je vais faire une fonction ou un require qui va faire le boulot

tout seul. Je suis beaucoup trop fainéant.

Et si tu veux changer la page d'infos tu te fend d'une ligen de scripts afin
de faire un S&R dans tous les fichiers ?


Certes point. Ou je peux modifier directement le *contenu* du fichier
html, ou je vais utiliser une constante genre
define('STD_ERR_FILE',std_excuses.html'); et faire un
require(STD_ERR_FILE); si vraiment je veux pouvoir changer ce genre de
choses.


a++
JG


Avatar
John Gallet
Re,

: il y a une méthode pour avoir une
garantie fiable de ne jamais envoyer à la sortie de HTML (par exemple)
non-sûr : faire en sorte que les seules fonctions reliées directement à la
sortie n'acceptent pas de chaînes de caractères simples, mais uniquement des
valeurs/objets d'un type abstrait HTML, valeurs qui ne peuvent être
construites que par des appels de constructeurs au nom évocateur.


Autrement dit, de même qu'on utilisera pas directement les variables
fournies en entrée mais qu'on passera par une fonction centrale de
filtrage des entrées, on ne renverra jamais directement au navigateur du
texte par echo/print etc... mais on passera toujours par une fonction de
filtrage en sortie, si je comprends bien.
Ca me parait, là comme ça, à froid et à jeun (au sens, j'ai pas encore
bu mais j'ai faim aussi donc pas les idées au plus clair), être la
meilleure solution. Il faut que je réfléchisse à l'apport suggéré
ailleurs dans le thread d'un format de sortie intermédiaire (typiquement
xml), pour le moment, j'ai l'impression que le format de sortie
intermédiaire déplace le problème sans le résoudre. Mais je vais y
cogiter un peu encore.


Ainsi, si « print $string » n'envoit pas $string au client mais simplement
dans les logs, et que pour envoyer quelque chose au client, il faut appeler
« output $html », avec $html qui ne peut être construit, au choix, qu'avec
html_escape_from_string ou html_unsafe_import_from_string, les problèmes
d'injection de codent se voient comme le nez au milieu de la figure : il y a
marqué « unsafe » dessus.


"Toutafé"(tm). Et donc tu as une fonction/méthode html_output(),
pdf_output() pour autant qu'on soit capable d'envoyer du code offensif
dans un pdf (??? Rassurez moi, ça existe pas encore, hein ? Hein ?) ou
text_ouput() (celle là elle est facile, suffit de stripper tous les tags
et c'est de toutes façns seulement de la présentation).

Dans le cas du HTML, il y a d'ailleurs un choix assez avantageux du type
abstrait à utiliser pour ça : un arbre XML manipulé par une bibliothèque
DOM. Ainsi, on a non seulement la garantie d'avoir une protection totalement
sûre du texte, mais en prime, on a la garantie d'envoyer du XHTML bien
formé, ce qui est toujours une bonne chose.


Là j'ai clairement rien compris à l'intérêt du biniou, mais c'est de
l'implémentation, donc ça me gêne pas (de pas comprendre).
Accessoirement je suis totalment réfractaire à certains standards, donc
pas grave.

Ceci dit, je dis ça dans l'absolu, mais je ne sais pas à quel point ça peut
s'appliquer au cas décrit dans ce thread, à savoir en PHP : ce langage
permet-il de définir des types abstraits facilement ? et est-il possible de
bloquer l'inclusion de code dans la page par un bête print ? J'avoue que je
n'en sais rien.


PHP (même en version 4, si, si, même en 3 d'ailleurs mais l'héritage
buggait parfois) sait faire de l'objet. Donc à la limite, si tu définis
une classe de type html_out, sa méthode toString() peut inclure le
filtrage en sortie. Mais sans aller jusque là, il suffit de remplacer
tous les echo/print et autres envois directs de données au navigateur
par l'appel à une fonction qui le fait après sécurisation
(rigoureusement de la même manière qu'on va utiliser une fonction de
filtrage en entrée pour ne pas accéder directement à
_REQUEST/_POST/_GET).

Ca me parait lourdingue en prime abord, mais je ne vois pas d'autres
solutions.

De toutes façons, mettons nous dans un cas simple : seulement des
interfaces HTML, en entrée comme en sortie, avec une base au milieu. Il
faut nécessairement :
- filtrer les entrées contre les injections SQL
- purger les champs texte "riches" de tout code offensif dormant (avant
ou après stockage en SGBD).

Donc qu'on fasse le filtrage avant le stockage ou avant l'envoi à
l'interface de sortie, il faut bien le faire. Seul le moment où on
appelle la fonction change.

a++
JG