OVH Cloud OVH Cloud

$_REQUEST securite ?

15 réponses
Avatar
jpll
bonjour à tous,
J'ai cru lire dans un post qq part ici que $_REQUEST pouvait mettre à mal la
sécurité.
Qu'en est-il exactement ? ( j'ai un peu tendance à l'utiliser...
beaucoup ). Je pensais que les superglobales accroissaient le niveau de la
sécurité.
merci.

10 réponses

1 2
Avatar
Laurent Seguin
jpll , le 26 mai 2004 23:03:51, écrivait ceci:

J'ai cru lire dans un post qq part ici que $_REQUEST pouvait mettre à
mal la sécurité.


C'est un troll ? Au cas ou...

Qu'en est-il exactement ? ( j'ai un peu tendance à l'utiliser...
beaucoup ).


Moi aussi, tout le temps même.

Je pensais que les superglobales accroissaient le niveau
de la sécurité.


Oui et non. Disons que si tu ne vérifies pas ce que tu attends, même avec
les superglobale tu peux manger chaud.

Maintenant il y en a qui vont te dire que tu fais un formulaire avec un
method="post" et que ca arrive par GET (ou inversement) il ne faut pas
prendre en compte les données reçus. Perso je trouve que c'est de la fausse
sécurité qui peu donner un faux sentiment sécuritaire et qu'il y a beaucoup
mieux à faire coté sécurité que de savoir comment sont arrivés les données.

Avatar
CrazyCat
jpll wrote:

bonjour à tous,
J'ai cru lire dans un post qq part ici que $_REQUEST pouvait mettre à mal la
sécurité.
Qu'en est-il exactement ? ( j'ai un peu tendance à l'utiliser...
beaucoup ). Je pensais que les superglobales accroissaient le niveau de la
sécurité.
merci.


oui, c'est moi qui l'ai dit :)
En fait, je n'aime pas $_REQUEST pour la simple et bonne raison que je
trouve qu'il est dangereux de pouvoir passer une variable aussi bien en
get qu'en post.
Imagine que tu fasses un accès via un formulaire qui utilise un champ de
type hidden (par exemple pour connaitre le numéro d'étape où se trouve
l'utilisateur). Un petit malin pourrait passer l'étape en url, donc
arriver à une certaine page sans avoir suivi le cheminement normal et
"casser" ta page (afficher des erreurs) et avoir accès a des parties
normalement inaccessibles.

--
Tout sur les eggdrops
http://www.c-p-f.org
ML @

Avatar
John Gallet
En fait, je n'aime pas $_REQUEST pour la simple et bonne raison que je
trouve qu'il est dangereux de pouvoir passer une variable aussi bien en
get qu'en post.


Pourquoi ? Justifie toi techniquement.


Imagine que tu fasses un accès via un formulaire qui utilise un champ de
type hidden (par exemple pour connaitre le numéro d'étape où se trouve
l'utilisateur). Un petit malin pourrait passer l'étape en url, donc
arriver à une certaine page sans avoir suivi le cheminement normal et
"casser" ta page


Et en QUOI est-ce que récupérer ton paramètre HIDDEN dans $_POST (en
admettant d'ailleurs que tu as mis METHOD="POST" dans ton formulaire) au
lieu de le récupérer dans $_REQUEST amène une QUELCONQUE sécurité ??

Bon, ça va, j'ai compris, je me le tiens, mon "débat du mois" suivant.
Le temps de contacter un modéro de fcs (Laurent, j'arrive) et c'est
parti.

John

Avatar
Eric Daspet
CrazyCat wrote:
Imagine que tu fasses un accès via un formulaire qui utilise un champ de
type hidden (par exemple pour connaitre le numéro d'étape où se trouve
l'utilisateur). Un petit malin pourrait passer l'étape en url, donc
arriver à une certaine page sans avoir suivi le cheminement normal et
"casser" ta page (afficher des erreurs) et avoir accès a des parties
normalement inaccessibles.


C'est justement ça une "fausse impression de sécurité".
Celui qui est capable de rajouter ce champ dans l'url directement
pourrait tout aussi facilement modifier ton formulaire HTML et l'envoyer
en POST, ou utiliser une extension de son navigateur pour modifier le
contenu du hidden, ou envoyer le tout via un script.

Le POST n'est pas du tout une sécurité, et si il pourrait avoir ainsi
accès à des parties normalement inaccessibles le problèmes ne vient pas
du GET/POST, il vient d'une mauvaise vérification ou d'une mauvaise
gestion de tes données. Celui qui peut faire un GET peut généralement
faire un POST ou un cookie.

--
Eric Daspet
Venez aider notre mangeur de cigogne sur http://mangeur-de-cigogne.info/

Avatar
CrazyCat
John Gallet wrote:

En fait, je n'aime pas $_REQUEST pour la simple et bonne raison que je
trouve qu'il est dangereux de pouvoir passer une variable aussi bien en
get qu'en post.
Pourquoi ? Justifie toi techniquement.

Et en QUOI est-ce que récupérer ton paramètre HIDDEN dans $_POST (en
admettant d'ailleurs que tu as mis METHOD="POST" dans ton formulaire) au
lieu de le récupérer dans $_REQUEST amène une QUELCONQUE sécurité ??


Qu'on m'arrète si je me trompe (attendez 30s, je prends un autre exemple):
$_REQUEST permet de récupérer un tableau de toutes les valeurs passées
par $_GET, $_POST, $_COOKIE et $_FILES.
Cela veut donc dire que si dans les cookies j'envois id (qui est l'id
d'un utilisateur) et que mon site est mal fait (je ne vérifie que la
présence et la valeur de $id), un utilisateur pas trop stupide peut
analyser la trame (il y a de très bons outils pour ça) et voir que l'id
est toujours le même pour lui.
Partant du principe que le webmaster est en id=1, pourquoi ne ferait-il
pas http://www.monsite.com/admin/index.php?id=1 ?
en utilisant $_REQUEST, je verrais bien $id = 1, alors qu'avec
$_COOKIE['id'] je ne le verrais pas.

L'exemple du get/post n'était pas forcémment le meilleur mais il m'est
venu a l'esprit parce que je l'utilise fréquemment.

Pour résumer mon idée, utiliser $_REQUEST revient plus ou moins à
utiliser register_global, ce qui a bien été défini comme un risque
potentiel.

--
Tout sur les eggdrops
http://www.c-p-f.org
ML @


Avatar
Bobe
jpll nous a dit le 26/05/2004 23:03:

bonjour à tous,
J'ai cru lire dans un post qq part ici que $_REQUEST pouvait mettre à mal la
sécurité.
Qu'en est-il exactement ? ( j'ai un peu tendance à l'utiliser...
beaucoup ). Je pensais que les superglobales accroissaient le niveau de la
sécurité.
merci.


Ah non, ça va pas recommencer.. :o)

--
Bobe (Aurélien Maille)
http://webnaute.net

"la vie d'un geek est un combat perpétuel contre l'imperfection"

Avatar
John Gallet
Re,

La question mérite qu'on s'y arrête un peu, c'est vraiment pas du troll,
là, sur les principes c'est important.

Qu'on m'arrète si je me trompe (attendez 30s, je prends un autre exemple):
$_REQUEST permet de récupérer un tableau de toutes les valeurs passées
par $_GET, $_POST, $_COOKIE et $_FILES.


Oui. Pour $_FILES je ne sais plus s'il a été ajouté ou retiré récemment,
mais en gros c'est ça.

Cela veut donc dire que si dans les cookies j'envois id (qui est l'id
d'un utilisateur) et que mon site est mal fait (je ne vérifie que la
présence et la valeur de $id), un utilisateur pas trop stupide peut
analyser la trame (il y a de très bons outils pour ça) et voir que l'id
est toujours le même pour lui.


Oui.

Partant du principe que le webmaster est en id=1, pourquoi ne ferait-il
pas http://www.monsite.com/admin/index.php?id=1 ?


C'est possible.

en utilisant $_REQUEST, je verrais bien $id = 1, alors qu'avec
$_COOKIE['id'] je ne le verrais pas.


En effet.

Mais tu ne le verras pas non plus si ton utilisateur "pas trop stupide"
édite son cookie et met id=1 dedans. Elle est **ICI** la faille. Si tu
considère que l'id est bien 1 (donc administrateur), que tu ailles la
pêcher dans _COOKIES ou dans _REQUEST, tu es b...é pareil. Dès lors que
l'attaquant sait qu'il suffit de te transmettre une variable id valant
1, je te garantis qu'il arrivera à te l'envoyer sous la forme que tu
veux (cookie, post, get) sans difficulté.

La seule chose qu'il faut retenir c'est que la vérification du mode de
transmission n'apporte pas de sécurité parce que le contenu des
variables est très facilement modifiable par un attaquant, même
débutant, qu'elles soient en cookie, transmises en post ou en get, le
principe est le suivant, à graver dans le marbre et à répéter tous les
soirs avant de se coucher :

"Rien ni personne ne peut empêcher un attaquant d'envoyer n'importe quoi
à nos scripts n'importe quand, autant de fois à la seconde qu'il le
souhaitera".

C'est l'enfance de l'art que de t'envoyer la donnée que tu souhaites
recevoir à partir du moment où je sais quelle est sa VALEUR, quel que
soit le mode de transmission sous lequel tu souhaites que je te les
fournisses, j'y arriverai en deux minutes.

Le principe de base est de ne JAMAIS FAIRE CONFIANCE à ce qui vient de
l'internaute, quel que soit le mode de transmission. Toujours partir du
principe que les données peuvent avoir été modifiées dans un but de
nuire côté client. Evidemment, ne pas faire confiance à du JS qu'il
suffit de désactiver.

Si tous les navigateurs de la terre recevaient les cookies sous forme
chiffrée en pgp, ou incluaient un checksum des données pour vérifier
leur non modification par un attaquant, on pourrait peut-être trouver un
intérêt à cette vérification car alors on pourrait faire *confiance* aux
données. A condition bien sûr que la vérification soit faite côté
serveur, pas dans le navigateur où on peut faire sauter des protections
(navigateurs en open source).

Si tu veux vérifier que tu as effectivement affaire à l'administrateur
du site, il faut ou que tu fasses systématiquement transiter un
login/pass (lourd, dangereux) ou que tu lui attribues pour une durée
déterminée (10 minutes, 1 heure, deux jours...) un jeton d'accès que tu
stockes obligatoirement côté serveur et si tu le souhaites côté client.
Autant il est ultra facile d'essayer d'ajouter id=1 dans le cookie
autant il est plus difficile (doux euphémisme) de trouver que l'actuel
jeton valable deux heures et stocké dans le cookie vaut
14TGWXfDTAe66GRD54Mljhdcys89A1, chaîne aléatoire de 30 (ou 50 chars
dépend de la durée de vie du jeton).

Ca c'est de la vraie sécurité. Savoir que ledit jeton a effectivement
été lu dans un cookie, tu t'en tapes donc totalement par rapport à ce
niveau là de sécurité, car tripoter un cookie, tout le monde sait faire,
mais trouver la valeur du jeton, ce sont les mathématiques qui te
donnent la "certitude" que c'est suffisement peu probable dans le délai
imparti pour le faire.

Pour résumer mon idée, utiliser $_REQUEST revient plus ou moins à
utiliser register_global, ce qui a bien été défini comme un risque
potentiel.


Pas du tout. Le risque exposé par register_globals=On est le suivant sur
un exemple.

Dans check.php :
<?php
$login=$_REQUEST['login']; $pass=$_REQUEST['pass'];
....
$res=mysql_query("SELECT COUNT(login) FROM mes_users WHERE
login='$login' AND pass='$pass'", $dad);
...
$row=mysql_fetch_row($res);
if($row[0]==1) $authenticated=1; // elle est ICI la faille
// fin de check.php
?>
Dans main.php :
<?php
// et elle est aussi ICI où elle aurait pu êter corrigée
require('check.php');
if(!$authenticate) exit("erreur login/pass);
// et là on considère que ok, login pass sont bons. Dommage... You've
been cracked...
?>

Et bien là, n'importe quel blaireau qui ajoute &authenticate«cd dans
un lien href ou input hidden name="authenticate" value="toto" pourra
accéder à tes ressources sans même connaître un login.

La faille vient du fait que $authenticate n'a JAMAIS ETE INITIALISEE ET
qu'en register_globals=On ALORS elle l'est depuis l'extérieur. Si tu
passes en register_globals=Off alors tu peux t'amuser à tripoter l'url
autant que tu voudras, il n'y aura plus de variable $authenticate
définie directement dans le script donc la faille ci-dessus disparait.
C'est clairement une erreur de codage, il suffisait d'écrire else
$authenticate=0 lors du test du nombre de rangs existants, ou
d'initialiser dans tous les cas $authenticate à zéro avant le test,
bref, les solutions ne manquent pas. Ceci n'a donc rien à voir avec
_GET, _POST et _REQUEST.

Mais de même, si tu remplaces par if($_COOKIES['authenticate']==1) il
suffit de modifier le cookie... Donc il n'y a pas plus de sécurité en
écrivant ça qu'en écrivant if($_REQUEST['authenticate']==1) je dirais
même que justement, on aura plus tendance à détecter cette **faille** de
sécurité de conception (on ne fait pas plus confiance au contenu d'un
cookie qu'à une variable arrivant d'un formulaire) en lisant qu'on est
en train de faire confiance à une variable de _REQUEST qui indique bien
la provenance du monde extérieur (donc potentiellement traffiquée).

Dans la liste des fausses sécurités, on peut aussi citer le test du
HTTP_REFERRER car il est très simple de le simuler. Je n'ai pas dit que
c'était inutile, mais qu'il ne faut pas en faire un mécanisme de
sécurité. Pareil pour REMOTE_ADDR et toute solutoin basée sur l'IP du
client. Mais justement, je vais lancer un thread là dessus.

HTH
JG

Avatar
CrazyCat
John Gallet wrote:

[snip d'une superbe démonstration]

Ok, en fait la grosse différence qu'il faut noter est sur
l'instanciation des variables.
Mon erreur venait du fait que je suis parti d'un exemple qui n'avait
rien à voir avec la sécurité ou presque, et j'ai voulu le continuer en
l'appliquant à la sécurité, alors que mon utilisation était fortement
bancale (même moi je ne mettrais pas la valeur de $authenticate dans un
champ hidden ou un cookie).

Effectivement, ton exemple me prouve que j'avais tort à 99%, de même que
tes explications sur la possibilité de "cracker" une page (rien n'est
vraiment inviolable de toutes manières).

Il n'empèche que je persiste à vouloir utiliser et différencier les
différents types de données transmises pour des raisons pratiques, à
savoir que sur certains sites je dois avoir un déroulement "temporel",
toutes les étapes sont obligatoires donc je ne veux surtout pas qu'un
petit malin puisse essayer *trop facilement* d'aller à la page 2 sans
passer par la page 1.

Je sais qu'il y a beaucoup d'autres méthodes pour cela, mais j'utilise
cette méthode parce que:
- je peux indiquer "Vous êtes à l'étape $etape" sans réfléchir,
- mes pages sont des formulaires, il est plus simple de rajouter un
simple champ,
- je génère des includes "logiques" (fichier_$etape.inc.php).

Voila, donc j'ai pu expliquer mon 1% de justesse, mais je conserverait
bien au chaud cette magistrale démonstration de John :)


--
Tout sur les eggdrops
http://www.c-p-f.org
ML @
Avatar
Laurent Seguin
CrazyCat , le 27 mai 2004 17:46:28, écrivait ceci:

Il n'empèche que je persiste à vouloir utiliser et différencier les
différents types de données transmises pour des raisons pratiques, à
savoir que sur certains sites je dois avoir un déroulement "temporel",
toutes les étapes sont obligatoires donc je ne veux surtout pas qu'un
petit malin puisse essayer *trop facilement* d'aller à la page 2 sans
passer par la page 1.


Ah ? tu crois ? Tu sais c'est hyper simple de voir ce qui passe par
method="post", live HTTP header (extension de firefox) simplifie grandement
la tâche.

Je sais qu'il y a beaucoup d'autres méthodes pour cela,


Oui genre... Un flag coté serveur (j'crois avoir entenu que c'était aussi
pour ca).

mais j'utilise
cette méthode parce que:
- je peux indiquer "Vous êtes à l'étape $etape" sans réfléchir,


Pareil avec mon flag.

- mes pages sont des formulaires, il est plus simple de rajouter un
simple champ,


Bof... Je traite la première étape, si c'est bon $flag++;

- je génère des includes "logiques" (fichier_$etape.inc.php).


include('fichier_$flag.inc.php");

Voila, donc j'ai pu expliquer mon 1% de justesse,


Même pas...

Avatar
Thibaut Allender

Mais de même, si tu remplaces par if($_COOKIES['authenticate']==1) il
suffit de modifier le cookie... Donc il n'y a pas plus de sécurité en
écrivant ça qu'en écrivant if($_REQUEST['authenticate']==1) je dirais
même que justement, on aura plus tendance à détecter cette **faille** de
sécurité de conception (on ne fait pas plus confiance au contenu d'un
cookie qu'à une variable arrivant d'un formulaire) en lisant qu'on est
en train de faire confiance à une variable de _REQUEST qui indique bien
la provenance du monde extérieur (donc potentiellement traffiquée).


d'autant plus qu'il faut savoir que la variable s'appelle "authenticate"
sans access aux sources, bon courage ;)

alors que dans le cookie, on voit clairement son nom

--
thibaut allender | freelance | web|system developer|designer
+32 496 26 75 76 | http://capsule.org *new version*

1 2