Discussion:
Tester l'existence d'un site
(trop ancien pour répondre)
Pascale
2008-07-06 14:51:11 UTC
Permalink
Sur l'un de nos sites, les gens qui s'inscrivent peuvent entrer (entre
autres) l'adresse de leur site web. Afin d'éviter les erreurs les plus
flagrantes, un contrôle est fait :

$siteini=$_POST['siteini'];
$site="http://".$siteini;
$file = @fopen($site,'r');
if ($file)
{$_SESSION['siteini']=$siteini;}
else
{
echo '<p class="erreur">L\'adresse de site '.$site.' renvoie un
message d\'erreur !</p>';
$errurl1='1';
}

Ça ne nous met pas à l'abri de toutes les bourdes, mais globalement ça
marche plutôt bien et oblige certains utilisateurs à ôter leurs moufles
pour se servir du clavier.
Aujourd'hui, j'ai le problème inverse, avec un site qui existe mais renvoie
un code erreur. Pour la page d'accueil du site en question http://www.les-
rolistes-rouennais.com/ ça ne m'étonne pas trop, car non seulement la page
d'accueil met longtemps à s'afficher, mais le chargement semble n'être
jamais fini (« en attente de http://www.les-rolistes-rouennais.com/ »). Ce
qui m'ennuie plus, c'est que j'ai le même message d'erreur
avec d'autres pages, par exemple http://www.les-rolistes-
rouennais.com/forum/accueil-f2.html , mais là aussi, il semble qu'il y ait
des éléments de page qui se chargent de manière sporadique.

Du coup, je suis embarrassée, car je n'ai pas envie du tout de supprimer ce
test, même s'il est imparfait, alors si vous avez de bonnes idées, ne vous
gênez pas... (:
--
Pascale
Olivier Miakinen
2008-07-06 16:03:43 UTC
Permalink
Post by Pascale
Sur l'un de nos sites, les gens qui s'inscrivent peuvent entrer (entre
autres) l'adresse de leur site web. Afin d'éviter les erreurs les plus
[...]
[...]
Aujourd'hui, j'ai le problème inverse, avec un site qui existe mais renvoie
un code erreur. [...]
Si le code de retour de fopen() n'est pas assez informatif, une idée
serait peut-être d'utiliser CURL :
http://fr3.php.net/manual/fr/ref.curl.php

Les codes d'erreur sont assez complets :
http://curl.haxx.se/libcurl/c/libcurl-errors.html

... et certains pourraient t'intéresser, par exemple :

CURLE_URL_MALFORMAT (3)
The URL was not properly formatted.
-> erreur de l'utilisateur

CURLE_COULDNT_RESOLVE_HOST (6)
Couldn't resolve host. The given remote host was not resolved.
-> probable erreur de l'utilisateur (à confirmer avec une requête sur un
site dont tu es sûre, pour vérifier que ce n'est pas le DNS qui est
en rade).

CURLE_COULDNT_CONNECT (7)
Failed to connect() to host or proxy.
-> le site est peut-être correct, même s'il ne répond pas.

etc.
Pascale
2008-07-07 11:20:40 UTC
Permalink
Post by Olivier Miakinen
Si le code de retour de fopen() n'est pas assez informatif, une idée
http://fr3.php.net/manual/fr/ref.curl.php
Ça a l'air de correspondre à ce que je cherche, par contre, je suis
totalement neuneue pour la mise en œuvre...

On commence par faire :

$ch=curl_init($url);
puis on récupère le code erreur éventuel avec

curl_errno($ch);

Mais en fait non, j'ai rien compris ? Si...?
--
Pascale
Mickaël Wolff
2008-07-07 12:36:13 UTC
Permalink
Post by Pascale
$ch=curl_init($url);
puis on récupère le code erreur éventuel avec
curl_errno($ch);
Mais en fait non, j'ai rien compris ? Si...?
curl_init créé une ressource, et l'initialise avec le paramètre s'il
lui est fournit.

curl_setopt te permet de configurer ta ressource.

Il faut savoir que, par défaut, curl va télécharger la page distante
et renvoyer le contenu vers ton navigateur. Donc si tu veux seulement
vérifier que la page existe, tu peux utiliser le code suivant :

function check_url($url)
{
$socket = curl_init($url) ;
curl_setopt($socket, CURLOPT_NOBODY, true) ;
$message = curl_exec($socket)
? curl_getinfo($socket, CURLINFO_HTTP_CODE)
: curl_error($socket) ;

curl_close($socket) ;
return $message ;
}

À noter que le message renvoyé n'est pas forcément une erreur.

Je profites du thread pour soulever un point concernant curl et la
sécurité. En fournissant directement l'URL de l'utilisateur à Curl, n'y
a-t-il pas potentiellement un problème de sécurité ?
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Patrick Mevzek
2008-07-07 13:39:24 UTC
Permalink
Post by Mickaël Wolff
En fournissant directement l'URL de l'utilisateur à Curl, n'y
a-t-il pas potentiellement un problème de sécurité ?
Si, multiples même.

Voir par exemple des papiers sur la sécurité d'OpenID (même problème :
l'utilisateur fournit une URL à un serveur qui doit s'en servir et s'y
connecter), ou un client HTTP « paranoïaque » dans un autre language :
http://search.cpan.org/~bradfitz/LWPx-ParanoidAgent-1.03/lib/LWPx/ParanoidAgent.pm
(avec quelques explications sur les pièges évités).

Et bien sûr là on ne parle même pas d'éventuelles failles dans le client
HTTP en lui-même juste de failles découlant du fait d'accepter de
l'extérieur une information réutilisée telle quelle.
--
Patrick Mevzek . . . . . . . . . . . . . . Dot and Co
<http://www.dotandco.net/> <http://www.dotandco.com/>
Mickaël Wolff
2008-07-07 17:05:07 UTC
Permalink
Post by Patrick Mevzek
Post by Mickaël Wolff
En fournissant directement l'URL de l'utilisateur à Curl, n'y
a-t-il pas potentiellement un problème de sécurité ?
Si, multiples même.
J'ai un peu fouillé, et c'est en fait un énorme trou si on ne fait pas
attention. Merci pour les infos.

Pascale, le bout de code que j'ai fournit à titre d'illustration n'est
pas sécurisé. Il ne faut pas l'utiliser en production. Je regarde pour
faire une classe mieux fagotée, je la posterais ici.
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Pascale
2008-07-07 19:17:01 UTC
Permalink
Post by Mickaël Wolff
Pascale, le bout de code que j'ai fournit à titre d'illustration n'est
pas sécurisé. Il ne faut pas l'utiliser en production. Je regarde pour
faire une classe mieux fagotée, je la posterais ici.
Bon, merci à tous de vous être penchés sur mon cas (-:
Je crois que tout le monde a compris ce que je veux faire, mais quelques
précisions ne peuvent pas nuire. La personne qui s'inscrit au site a le
droit de rentrer, parmi ses coordonnées, l'adresse de son site (le http://
est positionné automatiquement, on contrôle que l'utilisateur ne le met pas
2 fois). Le but est de prévenir la saisie d'adresses de sites farfelues ou
erronées. Je ne veux en aucun cas que le site s'ouvre automatiquement sur
l'ordinateur de la personne qui s'inscrit, je veux simplement prévenir la
saisie d'adresses erronées (je suis embêtée non seulement avec ceux qui
tapent avec leurs moufles, avec ceux qui veulent mettre un texte du style
« en chantier », et aussi avec ceux, plus nombreux qu'on ne croit, qui
confondent adresse de site et adresse courriel, ce qui fait qu'on se
retrouve avec des URL du genre http://***@fai.fr).
Le contrôle de l'URL s'effectue non seulement à l'inscription, mais à
chaque fois que la personne modifie quelque chose dans ses coordonnées.
Si je peux avoir un message d'erreur plus précis que « URL erronée », ce
sera pas plus mal (:
--
Pascale
Patrick Mevzek
2008-07-07 20:30:47 UTC
Permalink
Post by Pascale
Le but est de prévenir la saisie d'adresses de sites farfelues ou
erronées.
Mon conseil est alors :
- de ne faire qu'un test syntaxique (pas de connexion à la ressource
pointée par l'URL)
- d'autoriser https:// (éventuellement)
- et de permettre aux gens bien de donner directement l'URL avec http://
au début :-)

Vous n'avez donc besoin ni de fopen, ni de curl.
Mais d'une bonne bibliothèque d'analyse des URLs (non il ne ne suffit pas
d'avoir http:// au début, il y a plusieurs règles à vérifier... on peut
s'en sortir là avec une expression régulière mais mieux vaut laisser cà à
une bibliothèque optimisée pour ca)
Post by Pascale
Le contrôle de l'URL s'effectue non
seulement à l'inscription, mais à chaque fois que la personne modifie
quelque chose dans ses coordonnées.
Pourquoi ne pas revérifier *que* si le champ « Adresse du site » est
modifié (et donc ne pas revérifier si on change que le reste) ?
Post by Pascale
Si je peux avoir un message d'erreur
L'URL est bonne syntaxiquement ou non. Après la ressource est accessible
ou non, et si elle ne l'est pas cela ne signifie pas *nécessairement* que
l'URL est mauvaise : cela peut être un problème temporaire d'accès
n'importe où entre les deux serveurs, un code HTTP 500 ou 503, etc.
De toute façon, j'imagine (mais je peux me tromper je n'ai pas tout le
contexte), que vos utilisateurs ne sont pas tous les administrateurs des
sites web renseignés, donc même si vous donnez une erreur très précise,
ils ne pourront de toute façon rien corriger d'eux-mêmes (au mieux
transférer au support technique de la société gérant leur site web, avec
des résultats non garantis). Donc ce qui est utile pour eux, et pour vous,
c'est juste « l'URL est-elle valide syntaxiquement » et pas « la ressource
pointée par l'URL est-elle accessible maintenant de suite depuis un
serveur très spécifique ».

D'autre part, vous n'avez aucune garantie que le site appartient bien/est
géré par la personne en question. Tout le monde pourra mettre
http://www.google.com/
Mieux vaut donc que le champ soit optionnel.

Sinon, il faut mettre en place une vérification style : Placez un
fichier ayant un nom « dynamique, choisi aléatoirement » sur votre serveur
et on teste.
--
Patrick Mevzek . . . . . . . . . . . . . . Dot and Co
<http://www.dotandco.net/> <http://www.dotandco.com/>
Olivier Miakinen
2008-07-07 17:05:07 UTC
Permalink
Post by Patrick Mevzek
Post by Mickaël Wolff
En fournissant directement l'URL de l'utilisateur à Curl, n'y
a-t-il pas potentiellement un problème de sécurité ?
Si, multiples même.
Même si cette URL n'est utilisée que pour une requête HEAD, et que la
seule information utile qu'on en retient est un éventuel code d'erreur ?

Je ne vois pas quel problème de sécurité cela pourrait poser pour
l'appelant : il y a *beaucoup* moins de risques que pour un simple
internaute cliquant sur un lien avec un navigateur qui ferait un GET
au lieu d'un HEAD et qui, en outre, interpréterait le JavaScript.

Et même pour l'appelé : s'il n'implémente pas d'effet de bord aux
requêtes HEAD, il ne risque pas grand chose -- et inversement s'il
reformate son disque dur en réponse à un HEAD, c'est bien fait pour
sa pomme !
Post by Patrick Mevzek
l'utilisateur fournit une URL à un serveur qui doit s'en servir et s'y
connecter),
Tu aurais un lien (si possible traduit en français) ?
Post by Patrick Mevzek
http://search.cpan.org/~bradfitz/LWPx-ParanoidAgent-1.03/lib/LWPx/ParanoidAgent.pm
(avec quelques explications sur les pièges évités).
Je n'ai pas bien compris ce que ça fait (il faut dire que je ne suis pas
allé voir ce qu'était LWP::UserAgent dont il dérive).
Post by Patrick Mevzek
Et bien sûr là on ne parle même pas d'éventuelles failles dans le client
HTTP en lui-même juste de failles découlant du fait d'accepter de
l'extérieur une information réutilisée telle quelle.
Oui, bien sûr. Mais dans ce cas, quel genre de contrôle ferais-tu sur
l'URL qui pourrait minimiser les risques lors de la connexion par CURL ?
Mickaël Wolff
2008-07-07 18:55:58 UTC
Permalink
Post by Olivier Miakinen
Tu aurais un lien (si possible traduit en français) ?
C'est vrai que moi aussi ça m'aurait aider. Cependant, en essayant
l'url file:///etc/passwd dans curl_init, même en configurant l'option
CURLOPT_NOBODY à true le contenu du fichier est affiché :-D
Post by Olivier Miakinen
Je n'ai pas bien compris ce que ça fait (il faut dire que je ne suis pas
allé voir ce qu'était LWP::UserAgent dont il dérive).
Ce que je pense qu'il faut en retirer, c'est la limitation du timeout
(pour éviter les redirections éternelles), l'exclusion d'hôtes sensibles
afin d'éviter de détourner la fonctionnalité pour sonder le voisinage
réseau, etc. Tiens, si ça ce trouve, en utilisant la fonctionnalité
telnet, on peut éventuellement utiliser ça pour faire du spam :-D (oui,
c'est une obsession).
Post by Olivier Miakinen
Oui, bien sûr. Mais dans ce cas, quel genre de contrôle ferais-tu sur
l'URL qui pourrait minimiser les risques lors de la connexion par CURL ?
Vérifier que c'est une URL désignant une ressource HTTP est un bon
début en fait. C'est d'ailleurs ce que je suis en train de corriger dans
mes devs. Je n'avais pas réalisé la puissance de cURL.
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Olivier Miakinen
2008-07-07 19:17:01 UTC
Permalink
Post by Mickaël Wolff
C'est vrai que moi aussi ça m'aurait aider. Cependant, en essayant
l'url file:///etc/passwd dans curl_init, même en configurant l'option
CURLOPT_NOBODY à true le contenu du fichier est affiché :-D
Peut-être bien, mais je te rappelle le début du code de Pascale :
-----------------------------------
$siteini=$_POST['siteini'];
$site="http://".$siteini;
$file = @fopen($site,'r');
-----------------------------------

Je veux bien manger ma barbe si l'url html://file:///etc/passwd ouvre
quoi que ce soit en local...
Post by Mickaël Wolff
[...] l'exclusion d'hôtes sensibles
afin d'éviter de détourner la fonctionnalité pour sonder le voisinage
réseau
Ah oui, là je suis d'accord. Par exemple en lui passant une adresse IP.
Post by Mickaël Wolff
, etc. Tiens, si ça ce trouve, en utilisant la fonctionnalité
telnet, on peut éventuellement utiliser ça pour faire du spam :-D (oui,
c'est une obsession).
Même réponse que pour file : c'est impossible puisque c'est Pascale qui
rajoute http:// au début.
Post by Mickaël Wolff
Vérifier que c'est une URL désignant une ressource HTTP est un bon
début en fait.
Cf. supra. Pas besoin de le vérifier : on l'impose.
Pascale
2008-07-07 20:30:47 UTC
Permalink
Post by Olivier Miakinen
Même réponse que pour file : c'est impossible puisque c'est Pascale qui
rajoute http:// au début.
Je pourrais ne pas le faire, c'était juste pour faciliter la vie des
utilisateurs (et la nôtre, par la même occasion).
--
Pascale
Patrick Mevzek
2008-07-07 20:30:48 UTC
Permalink
Post by Olivier Miakinen
Je veux bien manger ma barbe si l'url html://file:///etc/passwd ouvre
quoi que ce soit en local...
[..]
Post by Olivier Miakinen
Même réponse que pour file : c'est impossible puisque c'est Pascale qui
rajoute http:// au début.
[..]

En théorie, oui. En pratique dès qu'on utilise un outil basé sur du C, et
donc des chaînes terminées par U+0000, des bugs surgissent. C'est
fréquent, régulier, et cela ne disparaîtra jamais totalement.
La dernière faille curl mentionné dans mon autre message, à savoir :
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-4850
en est un exemple d'ailleurs, même si effectivement elle ne serait
probablement pas exploitable dans le cas précis évoqué ici.

Donc, coller http:// au début peut faire partie d'une politique de
sécurité, mais ce ne doit être qu'un maillon, pas le seul.
On peut après, vérifier syntaxiquement la chose. C'est un deuxième maillon.
Et un U+0000 sera normalement bloqué lors de ce deuxième maillon.
Post by Olivier Miakinen
Post by Mickaël Wolff
Vérifier que c'est une URL désignant une ressource HTTP est un bon
début en fait.
Cf. supra. Pas besoin de le vérifier : on l'impose.
Et si on veut du HTTPS :-) ?
--
Patrick Mevzek . . . . . . . . . . . . . . Dot and Co
<http://www.dotandco.net/> <http://www.dotandco.com/>
Patrick Mevzek
2008-07-07 20:30:47 UTC
Permalink
Post by Olivier Miakinen
Même si cette URL n'est utilisée que pour une requête HEAD, et que la
seule information utile qu'on en retient est un éventuel code d'erreur ?
Oui.
Mais le problème de sécurité n'est pas *que* sur le serveur faisant la
requête, ce dernier peut devenir l'origine d'une attaque de type deni de
service (distribué ou non).

Voici quelques exemples de choses (tirées d'un papier sur la sécurité
d'OpenID que j'avais lu mais je n'ai plus la référence en tête) auxquelles
il faut penser, c'est à dire des URLs ennuyeuses :

- http://www.nsa.gov:1/, http://www.nsa.gov:2/, http://www.nsa.gov:3/
on fait une attaque de déni de service sur tous les ports, ou un
équivalent « nmap » (même si ce n'est pas du HTTP sur tous les ports, le
client risque de retourner un code différent entre « pas de réponse » et
« une réponse qui ne ressemble pas à du HTTP »).
Et, indépendamment d'une réponse ou non du serveur appelé, cela peut être
gênant juste d'initier un trafic vers certaines destinations...
- https://192.168.1.15/internal/auth?ip=1.1.1.1
URL interne à un réseau normalement
- http://localhost:8080/
même genre, et contournement d'un éventuel pare-feu local (sur le
serveur web)
- http://www.youtube.com/largemovie.flv
déni de service en temps et RAM consommée (sauf si on fait un HEAD, ok)
- file:///dev/null
il faut probablement veiller à ne faire que du HTTP/HTTPS
- http://www.example.com/register.pl?user=toto&pass=titi
remplissage « automatique » de formulaires à distance (sauf CAPTCHA et
autres), ou spam de blogs et autres, etc...
Post by Olivier Miakinen
Je ne vois pas quel problème de sécurité cela pourrait poser pour
l'appelant : il y a *beaucoup* moins de risques que pour un simple
internaute cliquant sur un lien avec un navigateur qui ferait un GET au
lieu d'un HEAD et qui, en outre, interpréterait le JavaScript.
Il est difficile de quantifier les dangers respectifs de différentes
pratiques.
L'appelant devient la source d'un certain trafic (une requête HTTP), comme
délégataire du client qui a soumis l'URL. Il est alors *responsable* de ce
trafic, comme l'est un proxy HTTP. Il vaut mieux qu'il soit absolument sûr
de la légitimité de ce trafic, car sinon il est lui-même vulnérable (cf
exemple http://localhost:8080/ plus haut) ou devient un intermédiaire
pour exploiter des vulnérabilités ailleurs (ce qui n'est pas beaucoup plus
enviable... avec les lois en préparation c'est un coup à perdre son accès
ADSL :-))
Post by Olivier Miakinen
Et même pour l'appelé : s'il n'implémente pas d'effet de bord aux
requêtes HEAD, il ne risque pas grand chose -- et inversement s'il
reformate son disque dur en réponse à un HEAD, c'est bien fait pour sa
pomme !
Pas seulement. Il peut faire confiance implicite au serveur appelant,
parce qu'il est dans le même réseau, etc... et donc permettre l'accès à
une ressource privée. Oui, le modèle de sécurité du serveur appelé est en
partie en défaut. Mais, en pratique, ce genre de défaut est fréquent.

Ou à l'opposé, il peut mettre en place de la QoS et donc refuser l'accès
au serveur appelant, parce qu'il a déjà vu son IP trop souvent dans le
passé, alors que la ressource demandée serait accessible depuis un client
« normal ».

De même, un client HTTP s'identifie (User-Agent & co, mais aussi en-têtes
Accept souvent absent par exemple, ce qui est détecté par des outils
comme mod_security, etc.) différemment d'un navigateur, ce qui peut
entraîner une différence de réponse de la part d'un serveur (ok, le
problème est du ressort du serveur HTTP appelé, mais en pratique on voit
souvent ce genre de situations).
Post by Olivier Miakinen
Post by Patrick Mevzek
http://search.cpan.org/~bradfitz/LWPx-ParanoidAgent-1.03/lib/LWPx/ParanoidAgent.pm
(avec quelques explications sur les pièges évités).
Je n'ai pas bien compris ce que ça fait (il faut dire que je ne suis pas
allé voir ce qu'était LWP::UserAgent dont il dérive).
LWP::UserAgent est un client HTTP en Perl (comme curl donc).
LWPx::ParanoidAgent est une sous-classe du précédent, donc toujours un
client HTTP comme curl mais qui en plus vérifie certaines choses comme :
- suppression de la fonctionnalité proxy (requêtes directes toujours)
- utilisation seulement des "schemes" http et https
- impossible de se connecter sur des IPs privées (192.168.x etc ...)
- prise en compte de listes noires de noms/IPs
- prise en compte d'un time out global pour être sûr de s'arrêter au bout
d'un certain temps et de ne pas rester bloqué à la merci d'un serveur
distant qui répond, intentionnellement ou non, très lentement.
(cas précis évoqué au début de ce fil)
En tenant compte des redirections HTTP (autre point à prendre en compte
globalement, les navigateurs détectent les boucles de redirection et
s'arrêtent après un certain nombre de sauts, je ne sais pas si c'est le
cas, par défaut, dans tous les clients HTTP), des chaînes de CNAME dans les
DNS (qui pourraient provoquer des boucles), etc.
Post by Olivier Miakinen
Post by Patrick Mevzek
Et bien sûr là on ne parle même pas d'éventuelles failles dans le
client HTTP en lui-même juste de failles découlant du fait d'accepter
de l'extérieur une information réutilisée telle quelle.
Oui, bien sûr. Mais dans ce cas, quel genre de contrôle ferais-tu sur
l'URL qui pourrait minimiser les risques lors de la connexion par CURL ?
Par rapport au besoin du posteur initial, il me semble qu'un simple test
syntaxique sur l'URL entrée suffit (ce qui n'est même pas fait dans
l'exemple donné au début, même coller http:// systématiquement au début,
ca me paraît dangereux, moi si on me demande une adresse web, c'est une
URL, donc je mets déjà le http:// au début :-)), il n'y a pas besoin de
curl. Je ne vois pas bien l'intérêt de vérifier si le serveur en question
répond, existe, etc. (sauf si on cherche réellement à récupèrer quelque
chose dessus, genre une image pour un avatar ou autre) parce qu'il
pourrait y avoir *plein* de problèmes, y compris du côté de l'appelant
(problèmes réseau, etc.) qui font que le serveur ne répond pas, et
répondra plus tard, ou le contraire, etc. [ Ca me rappelle ZoneCheck cette
affaire :-)] Ca, plus les risques auxquels on s'expose fait que je ne
trouve pas utile d'aller faire la requête HTTP en question.

Maintenant s'il y en a réellement besoin, il est fort probable qu'il n'y
en a pas besoin de manière synchrone. Je prendrais donc l'URL que me donne
l'utilisateur et (après un éventuel simple test syntaxique), la stocke
quelque part. Après un processus asynchrone indépendant traite toutes les
URLs en attente.
Ainsi :
- il est complétement décorrélé du serveur web, et ne peut pas planter ce
dernier ni permettre un contrôle quelconque, si tant soit peu évidemment
qu'on le sépare correctement (exemple: utilisateur différent, répertoires
séparés, droits précis, etc.)
- si curl ou n'importe quel client est vulnérable, on arrête
temporairement les vérifications, ou on change de client, etc. Tout ceci
sans conséquences pour le service web, et a priori assez simplement parce
qu'on aura qu'une dizaine de lignes de code spécifiques pour cette tâche à
corriger, plutôt qu'une éventuelle non négligeable partie du code (PHP ou
non) du serveur web, dès qu'on n'a pas pensé à mettre ca proprement dans
une fonction/un fichier à part.

Ok, c'est plus « complexe » à mettre en oeuvre, mais ca utilise les bonnes
pratiques de la sécurité (séparation des processus, donner toujours le
minimum de droits pour faire une tâche, etc.)

Cette approche asynchrone ne fonctionne pas pour des besoins comme ceux
d'OpenID, d'où toutes les précautions explorées plus haut, sans que cela
soit exhaustif évidemment.

Tout ce qui précède est évidemment en grande partie complétement
indépendant à la fois du client HTTP en question (curl) et du langage (PHP).

Après il faut ajouter les failles de sécurité propres à ces deux éléments.

Pour curl lui-même par exemple :
http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=curl
(en particulier la plus récente
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2007-4850
est problématique pour ce qui nous intéresse ici)

Pour PHP et sa sécurité, trop de liens à mentionner :-)
À noter que personnellement, pour moi, allow_url_fopen est mieux à Off,
donc pas de fopen('http://...') comme évoqué au début.
(mélanger les ressources « locales » comme les fichiers sur le disque dur
du serveur et les ressources « distantes » accessibles par HTTP/FTP/etc.
en supprimant toute distinction entre les deux me paraît être une
mauvaise chose, en tout cas du point de vue de la sécurité ; cela illustre
une façon générale de penser aux problèmes de sécurité que je donne en
cours, à savoir que quand une information change de contexte, ou qu'on
perd le contexte, cela créé un risque. Cf toutes les attaques type XSS,
etc.)
--
Patrick Mevzek . . . . . . . . . . . . . . Dot and Co
<http://www.dotandco.net/> <http://www.dotandco.com/>
Olivier Miakinen
2008-07-07 21:19:56 UTC
Permalink
Bonjour Patrick, et merci de tes réponses. En particulier celle-ci, très
détaillée, à laquelle je ne répondrai qu'en partie (mais j'ai bien tout lu).
[...]
Voici quelques exemples de choses [...] auxquelles
[ liste d'exemples ]
Je me rends. ;-)
il faut probablement veiller à ne faire que du HTTP/HTTPS
Voire que du HTTP. Le besoin de Pascale est de valider une page perso,
pas de se connecter à un service bancaire.

Cela dit, comme tu l'expliquais, une simple analyse syntaxique devrait
suffire. Et sinon, peut-être une requête DNS, non ? Tu n'as pas parlé de
cette éventualité, alors que justement pour le contrôle des adresses de
courriel c'est toi qui conseillais d'en faire une tandis que moi je
l'estimais inutile...
L'appelant devient la source d'un certain trafic (une requête HTTP), comme
délégataire du client qui a soumis l'URL. Il est alors *responsable* de ce
trafic, comme l'est un proxy HTTP. [...]
Oui, c'est juste. Même pour un simple HEAD il pourrait se le voir reprocher.
Maintenant s'il y en a réellement besoin, il est fort probable qu'il n'y
en a pas besoin de manière synchrone. Je prendrais donc l'URL que me donne
l'utilisateur et (après un éventuel simple test syntaxique), la stocke
quelque part. Après un processus asynchrone indépendant traite toutes les
URLs en attente.
- [ deux bonnes raisons pour le faire ]
Oui, c'est une excellente suggestion, à se rappeler car cela pourrait
servir dans d'autres situations.
À noter que personnellement, pour moi, allow_url_fopen est mieux à Off,
donc pas de fopen('http://...') comme évoqué au début.
[OUI]
(mélanger les ressources « locales » comme les fichiers sur le disque dur
du serveur et les ressources « distantes » accessibles par HTTP/FTP/etc.
en supprimant toute distinction entre les deux me paraît être une
mauvaise chose, en tout cas du point de vue de la sécurité ; [...]
Absolument.

Et encore merci pour cette réponse.
--
Olivier Miakinen
Patrick Mevzek
2008-07-08 16:01:35 UTC
Permalink
Post by Olivier Miakinen
Cela dit, comme tu l'expliquais, une simple analyse syntaxique devrait
suffire. Et sinon, peut-être une requête DNS, non ? Tu n'as pas parlé de
cette éventualité, alors que justement pour le contrôle des adresses de
courriel c'est toi qui conseillais d'en faire une tandis que moi je
l'estimais inutile...
Oui, parce que je fais cette différence (certes faible et discutable)
entre les deux cas :

- quand on demande une adresse email, en général on va réellement en avoir
besoin c'est à dire envoyer un email dans le futur, que ce soit un «
Bienvenu » au début, une newsletter, un rappel de mot de passe, etc.
Bref c'est une ressource « chaude ».
- dans le cas exposé, si j'ai bien compris, l'URL du site n'est qu'un
élément de la fiche d'identification, cela ne joue pas de rôle particulier
dans le service fourni, au mieux on met un lien en face du nom de
l'utilisateur et voila. Donc si l'URL ne pointe pas vers une ressource
accessible (le test DNS permettant d'éliminer certains cas triviaux de
ressources non accessibles), cela ne dégrade pas significativement le
service proposé, et cela n'embête en fait que l'internaute qui va cliquer
sur le lien, et pas le serveur qui gère la base d'utilisateurs renseignés
avec une URL. D'où mon avis d'en faire le « minimum » au moment où l'on
recueille l'URL de l'utilisateur, et d'éviter de dépendre de ressources
externes (que ce soit le DNS ou le serveur HTTP pointé, ces deux éléments
étant en-dehors du contrôle du gestionnaire du serveur web qui recuille
l'URL, alors qu'un test syntaxique impose juste une bonne bibliothèque
locale pour faire ca, et aucune dépendance externe).

Donc, compte tenu de cette différence, le test DNS ne me paraît pas
primordial ici. Mais il peut en tout cas être fait bien plus facilement et
avec moins de risques (mais pas aucun, a CNAME b + b CNAME a c'est
embêtant) qu'une requête HTTP.
--
Patrick Mevzek . . . . . . . . . . . . . . Dot and Co
<http://www.dotandco.net/> <http://www.dotandco.com/>
Olivier Miakinen
2008-07-08 17:29:21 UTC
Permalink
Post by Patrick Mevzek
- quand on demande une adresse email, en général on va réellement en avoir
besoin c'est à dire envoyer un email dans le futur, que ce soit un «
Bienvenu » au début, une newsletter, un rappel de mot de passe, etc.
Bref c'est une ressource « chaude ».
- dans le cas exposé, si j'ai bien compris, l'URL du site n'est qu'un
élément de la fiche d'identification, cela ne joue pas de rôle particulier
dans le service fourni, au mieux on met un lien en face du nom de
l'utilisateur et voila. [...]
C'est très clair. Encore merci.
Post by Patrick Mevzek
Donc, compte tenu de cette différence, le test DNS ne me paraît pas
primordial ici. Mais il peut en tout cas être fait bien plus facilement et
avec moins de risques (mais pas aucun, a CNAME b + b CNAME a c'est
embêtant) qu'une requête HTTP.
Oui.

Cordialement,
--
Olivier Miakinen
Pascale
2008-07-08 19:31:22 UTC
Permalink
Post by Patrick Mevzek
- quand on demande une adresse email, en général on va réellement en
avoir besoin c'est à dire envoyer un email dans le futur, que ce soit
un « Bienvenu » au début, une newsletter, un rappel de mot de passe,
etc. Bref c'est une ressource « chaude ».
Il faut surtout que les visiteurs du site puissent joindre les inscrits
(via un formulaire, l'adresse courriel n'est jamais visible).
Post by Patrick Mevzek
- dans le cas exposé, si j'ai bien compris, l'URL du site n'est qu'un
élément de la fiche d'identification, cela ne joue pas de rôle
particulier dans le service fourni, au mieux on met un lien en face du
nom de l'utilisateur et voila. Donc si l'URL ne pointe pas vers une
ressource accessible (le test DNS permettant d'éliminer certains cas
triviaux de ressources non accessibles), cela ne dégrade pas
significativement le service proposé, et cela n'embête en fait que
l'internaute qui va cliquer sur le lien
Oui, et ça, on veut pas... Nous tenons au maximum à ce que les données
soient à jour et fiables, ce qui est une lutte de tous les jours (-;
--
Pascale
Pascale
2008-07-08 19:31:22 UTC
Permalink
Post by Olivier Miakinen
Voire que du HTTP. Le besoin de Pascale est de valider une page perso,
pas de se connecter à un service bancaire.
Tout à fait : nos inscrits sont des associations, et en 4 ans, personne ne
nous a jamais demandé de pouvoir saisir une adresse en https://
Le http:// est mis automatiquement parce que c'est autant de risques
d'erreurs en moins (: (on contrôle qu'il n'est pas entré 2 fois).
Post by Olivier Miakinen
Cela dit, comme tu l'expliquais, une simple analyse syntaxique devrait
suffire.
On en avait une, mais sûrement insuffisante (et puis les regexp et moi,
hummmm... (: ). Difficile de déjouer les sournoiseries du style adresse de
site chez Free à laquelle l'utilisateur ajoute soigneusement un www. au
début...
Depuis que je fais le contrôle avec fopen on a quand même beaucoup moins de
déchet, ce qui nous évite autant de courriers pour dire « vous vous êtes
trompés, SVP veuillez corriger,... ».
À chaque inscription, un message nous est envoyé et nous vérifions quand
même manuellement l'existence de l'URL, car le contrôle actuel ne renvoie
pas d'erreur par exemple si le nom de domaine est abandonné et que le site
est redirigé vers un portail quelconque de services commerciaux ou encore,
si l'utilisateur confond adresse courriel et URL.
Récemment, on a eu un cas assez curieux : une assoc' très sérieuse de
juristes nous rentre une adresse de site qui lue en diagonale paraît
cohérente et lorsque nous l'essayons, nous atterrissons sur un forum Dragon
Ball Z ! En fait, la personne de l'assoc' qui avait saisi les informations
s'était trompée et avait mis wwww au lieu de www et, pour une raison qui
m'échappe, cette adresse était redirigée sur ce fameux forum...
Post by Olivier Miakinen
Oui, c'est juste. Même pour un simple HEAD il pourrait se le voir reprocher.
Comment, c'est MAL, ce que je fais ?...

Je veux bien me contenter d'une analyse syntaxique, mais ça me paraît plus
que très compliqué d'obtenir quelque chose d'efficace.
--
Pascale
Patrick Mevzek
2008-07-08 20:52:18 UTC
Permalink
Post by Pascale
Post by Olivier Miakinen
Voire que du HTTP. Le besoin de Pascale est de valider une page perso,
pas de se connecter à un service bancaire.
Tout à fait : nos inscrits sont des associations, et en 4 ans, personne ne
nous a jamais demandé de pouvoir saisir une adresse en https://
Le http:// est mis automatiquement parce que c'est autant de risques
d'erreurs en moins (: (on contrôle qu'il n'est pas entré 2 fois).
Oui cela ne servira probablement à rien mais c'était une remarque en
passant pour penser à ce qu'on exclut, si on prend le cas des «
validations d'email », il y a tellement de routines qui interdisent les
adresses avec un TLD de plus de 3 caractères (et avec ce qui a été annoncé
récemment, ca va faire des ravages).
Post by Pascale
À chaque inscription, un
message nous est envoyé et nous vérifions quand même manuellement
l'existence de l'URL, car le contrôle actuel ne renvoie pas d'erreur par
exemple si le nom de domaine est abandonné et que le site est redirigé
vers un portail quelconque de services commerciaux
Et donc, même la requête HTTP ne sert « à rien », s'il faut après une
validation humaine sur le contenu, chose que vous ne pourrez de toute
façon pas automatiser à 100%.
Post by Pascale
Je veux bien me contenter d'une analyse syntaxique, mais ça me paraît
plus que très compliqué d'obtenir quelque chose d'efficace.
Utiliser une bibliothèque toute faite.
Je vois :
http://pear.php.net/package/Net_URL2
qui dit :
Easy parsing of Urls

(je n'ai vérifié ni si c'est facile, ni si c'est correct syntaxiquement
parlant)
--
Patrick Mevzek . . . . . . . . . . . . . . Dot and Co
<http://www.dotandco.net/> <http://www.dotandco.com/>
Pascale
2008-07-09 09:50:01 UTC
Permalink
Post by Patrick Mevzek
Oui cela ne servira probablement à rien mais c'était une remarque en
passant pour penser à ce qu'on exclut, si on prend le cas des «
validations d'email », il y a tellement de routines qui interdisent
les adresses avec un TLD de plus de 3 caractères (et avec ce qui a été
annoncé récemment, ca va faire des ravages).
Et donc, même la requête HTTP ne sert « à rien », s'il faut après une
validation humaine sur le contenu, chose que vous ne pourrez de toute
façon pas automatiser à 100%.
Disons qu'on cherche à éviter en amont un maximum d'erreurs afin de ne pas
avoir à écrire aux gens (ce qui suppose de surveiller ensuite s'ils ont
corrigé ou pas).
Post by Patrick Mevzek
Utiliser une bibliothèque toute faite.
http://pear.php.net/package/Net_URL2
Easy parsing of Urls
(je n'ai vérifié ni si c'est facile, ni si c'est correct
syntaxiquement parlant)
Merci, je l'ai téléchargé... M'enfin, d'ici que je me connecte suffisamment
de neurones pour piger comment l'utiliser et voir si ça fonctionne bien...
--
Pascale
Pascale
2008-07-07 11:32:35 UTC
Permalink
Post by Olivier Miakinen
Si le code de retour de fopen() n'est pas assez informatif, une idée
serait peut-être d'utiliser CURL [couic]
Je pense que ça correspond tout à fait à ce qu'il me faut : si je trouve
pas mon bonheur là dedans, c'est vraiment que je m'y prends mal, merci
Olivier (:
--
Pascale
CrazyCat
2008-07-07 12:36:13 UTC
Permalink
Post by Pascale
Sur l'un de nos sites, les gens qui s'inscrivent peuvent entrer (entre
autres) l'adresse de leur site web. Afin d'éviter les erreurs les plus
$siteini=$_POST['siteini'];
$site="http://".$siteini;
Pour ma part, j'utiliserais plutôt une fonction dédiée à cela: fsockopen:

<?
$siteini = $_POST['siteini'];
if (strpos($siteini , 'tp://')===false) $siteini = 'http://'.$siteini ;
if ($fid = @fsockopen($siteunu, 80, $errno, $errstr, 10) {
echo $siteini.' OK';
} else {
echo 'Error with '.$siteini.': '.$errno.' -> '.$errstr;
}
?>
--
Réseau IRC Francophone: http://www.zeolia.net
Aide et astuces webmasters : http://www.c-p-f.org
Communauté Francophone sur les Eggdrops: http://www.eggdrop.fr
Continuer la lecture sur narkive:
Loading...