Discussion:
securite, sql, formulaire
(trop ancien pour répondre)
ricoh51
2010-06-02 21:32:33 UTC
Permalink
Bonjour,
C'est mon premier message sur ce groupe, je débute en php.
Sur le site du zéro, j'ai trouvé un tuto qui explique ce qu'il faut
faire pour prévenir les injections SQL et les failles XSS :
function bdd($string){ // Données entrantes
if(ctype_digit($string)){
// On regarde si le type de string est un nombre entier (int)
$string = intval($string);
}
else{ // Pour tous les autres types
$string = mysql_real_escape_string($string);
$string = addcslashes($string, '%_');
}
return $string;
}

Si je comprends bien, je dois toujours utiliser la fonction bdd si
j'exécute une requête sql à partir d'une donnée d'un formulaire.
Mais je ne comprends pas bien l'intérêt de regarder si la donnée est un
nombre...
Et je ne comprends pas non plus l'intérêt de addcslashes, je croyais que
c'était le boulot de mysql_escape_string.

function html($string){ // Données sortantes
return htmlentities($string, ENT_COMPAT, 'UTF-8');
}
Et là je dois utiliser la fonction html lorsque je veux écrire dans la
page des données qui proviennent d'un formulaire.

Pouvez-vous me dire si ces deux fonctions sont correctes?
Et y'at-il des cas qui ne sont pas gérés par ces deux fonctions?

Merci d'avance

eric
Mickael Wolff
2010-06-03 06:39:07 UTC
Permalink
Post by ricoh51
Sur le site du zéro, j'ai trouvé un tuto qui explique ce qu'il faut
Ou plutôt ce qu'il ne faut pas faire. c'est assez usuel sur ce site.
Post by ricoh51
function bdd($string){ // Données entrantes
if(ctype_digit($string)){
// On regarde si le type de string est un nombre entier (int)
$string = intval($string);
}
Aucun intérêt. Ce n'est pas à la couche d'abstraction de la base de
données de s'occuper de déterminer quelles sont les données valides ou
les convertir.
Post by ricoh51
else{ // Pour tous les autres types
$string = mysql_real_escape_string($string);
La seule chose logique.
Post by ricoh51
$string = addcslashes($string, '%_');
Comme le dit la doc de MySQL, mysql_real_escape_string n'échappe pas
% et _ car il n'y a pas de raison de les échappés dans le cas général.
Post by ricoh51
Si je comprends bien, je dois toujours utiliser la fonction bdd si
j'exécute une requête sql à partir d'une donnée d'un formulaire.
Non. La fonction est trop bourrin, pas assez fine. Elle fait fis du
contexte. C'est justement en conseillant ce genre de choses qu'on
encourage les trous de sécurité subtils.
Post by ricoh51
Mais je ne comprends pas bien l'intérêt de regarder si la donnée est un
nombre...
Aucun, surtout qu'on risque un bogue si l'entier est supérieur à 2^16 - 1
Post by ricoh51
function html($string){ // Données sortantes
return htmlentities($string, ENT_COMPAT, 'UTF-8');
}
Et là je dois utiliser la fonction html lorsque je veux écrire dans la
page des données qui proviennent d'un formulaire.
Surtout pas. Encore une fois, l'échapement des caractères doit être
fait en fonction du contexte (textnode, attrnode, etc) et non pas
échapés brutalement sans aucun discernement. Sans compte qu'ici, on ne
gère pas du tout les attaques se basant sur un encodage différent.
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
ricoh51
2010-06-03 08:59:19 UTC
Permalink
Post by Mickael Wolff
Post by ricoh51
else{ // Pour tous les autres types
$string = mysql_real_escape_string($string);
La seule chose logique.
ok, alors prenons un exemple simple : j'ai un espace membre, et je veux
vérifier que le pseudo n'existe pas encore au moment de l'inscription.
J'accepte tous les caractères dans un pseudo, la seule restriction est
que sa longueur doit être comprise entre 6 et 20 caractères. Je fais :

if(isset(pseudo)){ //Vérif du pseudo
$pseudo2 = mysql_real_escape_string($pseudo);
$sql="SELECT COUNT(*) AS verif_exist FROM visiteur WHERE
pseudoVisiteur='$pseudo2'";
$reponse=mysql_query($sql);
$donnees = mysql_fetch_array($reponse);
if ($donnees['verif_exist'] != 0){ // le pseudo existe déja
$erreurPseudo='Ce pseudo existe déjà.';
}
$longueur=mb_strlen($pseudo, 'UTF-8');
if(($longueur<6)||($longueur>20)){
$erreurPseudo='La longueur du pseudo doit être comprise entre 6 et
20 caractères.';
}
}

Et lorsque le compte est créée, et que le gars se connecte, je vérifie
le pseudo puis j'affiche le pseudo dans la page :

$pseudo=$_POST['pseudo'];
$pass = $_POST['password'];
$pseudo2 = mysql_real_escape_string($pseudo);
$pass2 = mysql_real_escape_string($pass);
// [snip] la verif qu'il y a $pseudo2 dans la base
$sql = "select * from visiteur WHERE pseudoVisiteur='".$pseudo2."'";
$reponse=mysql_query($sql);
$donnees = mysql_fetch_array($reponse);
if(sha1($pass2)==$donnees['passVisiteur']){ // ici c'est bon
$_SESSION['pseudo']=$pseudo;
}

// et plus tard
echo '<p>Bonjour ' . htmlentities($_SESSION['pseudo']) . '</p>';
Post by Mickael Wolff
Post by ricoh51
function html($string){ // Données sortantes
return htmlentities($string, ENT_COMPAT, 'UTF-8');
}
Et là je dois utiliser la fonction html lorsque je veux écrire dans la
page des données qui proviennent d'un formulaire.
Surtout pas. Encore une fois, l'échapement des caractères doit être fait
en fonction du contexte (textnode, attrnode, etc)
je ne comprends pas textnode, attrnode...


et non pas échapés
Post by Mickael Wolff
brutalement sans aucun discernement. Sans compte qu'ici, on ne gère pas
du tout les attaques se basant sur un encodage différent.
Ah? Peux tu développer?

Merci beaucoup

eric
Mickael Wolff
2010-06-10 10:51:05 UTC
Permalink
Désolé pour le lag, je suis un peu occupé en ce moment.
Post by ricoh51
ok, alors prenons un exemple simple : j'ai un espace membre, et je veux
vérifier que le pseudo n'existe pas encore au moment de l'inscription.
J'accepte tous les caractères dans un pseudo, la seule restriction est
if(isset(pseudo)){ //Vérif du pseudo
$pseudo2 = mysql_real_escape_string($pseudo);
$sql="SELECT COUNT(*) AS verif_exist FROM visiteur WHERE
pseudoVisiteur='$pseudo2'";
$reponse=mysql_query($sql);
$donnees = mysql_fetch_array($reponse);
if ($donnees['verif_exist'] != 0){ // le pseudo existe déja
$erreurPseudo='Ce pseudo existe déjà.';
}
$longueur=mb_strlen($pseudo, 'UTF-8');
if(($longueur<6)||($longueur>20)){
$erreurPseudo='La longueur du pseudo doit être comprise entre 6 et 20
caractères.';
}
}
Ici tu mélange allègrement la logique métier (un pseudo a telle
taille) et la logique de contrôle (aiguillage de la requête). C'est
malheureusement la méthode canonique sous PHP. Je ne vais pas trop m'en
éloigner pour ne pas te perdre, et te proposes plutôt ceci :

<?php

$errors = array('pseudo' => array()) ;

if(isset($pseudo)) // Cette condition n'est pas suffisante
{
$sql = sprintf('SELECT COUNT(*) AS verif_exist FROM visiteur WHERE
pseudoVisiteur = \'%s\''
, mysql_real_escape_string($pseudo));

$result = mysql_query($sql) ;
$row = mysql_fetch_array($result) ;
if ($row['verif_exist'] > 0)
$errors['pseudo'][] = 'Ce pseudo existe déjà.' ;

mysql_free_result($result) ;

$longueur = mb_strlen($pseudo, 'UTF-8') ; // Es-tu certain d'avoir de
l'UTF-8 en entrée ?
if($longueur < 6 || $longueur > 20)
$errors['pseudo'][] = 'La longueur du pseudo doit être comprise entre
6 et 20 caractères.' ;
}
else
$errors['pseudo'][] = 'Ooops' ;
Post by ricoh51
echo '<p>Bonjour ' . htmlentities($_SESSION['pseudo']) . '</p>';
htmlspecialchars suffit amplement.
Post by ricoh51
je ne comprends pas textnode, attrnode...
<http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html>
TextNode
<http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-1312295772>
AttrNode
<http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-637646024>
Post by ricoh51
Ah? Peux tu développer?
<http://shiflett.org/blog/2005/dec/googles-xss-vulnerability>
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
ricoh51
2010-06-10 20:19:35 UTC
Permalink
Post by Mickael Wolff
Désolé pour le lag, je suis un peu occupé en ce moment.
ben c'est déjà très sympa de me répondre, je ne vais pas me plaindre en
plus :)
Post by Mickael Wolff
Post by ricoh51
ok, alors prenons un exemple simple : j'ai un espace membre, et je veux
vérifier que le pseudo n'existe pas encore au moment de l'inscription.
J'accepte tous les caractères dans un pseudo, la seule restriction est
if(isset(pseudo)){ //Vérif du pseudo
$pseudo2 = mysql_real_escape_string($pseudo);
$sql="SELECT COUNT(*) AS verif_exist FROM visiteur WHERE
pseudoVisiteur='$pseudo2'";
$reponse=mysql_query($sql);
$donnees = mysql_fetch_array($reponse);
if ($donnees['verif_exist'] != 0){ // le pseudo existe déja
$erreurPseudo='Ce pseudo existe déjà.';
}
$longueur=mb_strlen($pseudo, 'UTF-8');
if(($longueur<6)||($longueur>20)){
$erreurPseudo='La longueur du pseudo doit être comprise entre 6 et 20
caractères.';
}
}
Ici tu mélange allègrement la logique métier (un pseudo a telle taille)
et la logique de contrôle (aiguillage de la requête).
oui... pas bien, j'ai déjà eu des périodes d'intégrisme d'abstraction
(pas en php je débute), mais pour des petits projets comme ça, je me
demande si ça vaut bien la peine?

C'est
Post by Mickael Wolff
malheureusement la méthode canonique sous PHP. Je ne vais pas trop m'en
<?php
$errors = array('pseudo' => array()) ;
je ne comprends pas cette construction... je ne domine pas assez les
"tableaux" de php je crois :)
Post by Mickael Wolff
if(isset($pseudo)) // Cette condition n'est pas suffisante
{
$sql = sprintf('SELECT COUNT(*) AS verif_exist FROM visiteur WHERE
pseudoVisiteur = \'%s\''
, mysql_real_escape_string($pseudo));
ok, ici pour un pseudo, la vérification du type (le %s) n'apporte rien
je pense, mais j'imagine que c'est une bonne habitude à prendre.
Post by Mickael Wolff
mysql_free_result($result) ;
pareil, j'imagine que c'est une bonne habitude à prendre de libérer la
mémoire.
Post by Mickael Wolff
$longueur = mb_strlen($pseudo, 'UTF-8') ; // Es-tu certain d'avoir de
l'UTF-8 en entrée ?
Ma page comporte :
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
et ma base de données est entièrement en utf-8. Je voulais être
tranquille pour le jour où mon_beau_site_de_la_mort sera traduit en
chinois, coréen etc :)
Post by Mickael Wolff
if($longueur < 6 || $longueur > 20)
$errors['pseudo'][] = 'La longueur du pseudo doit être comprise entre 6
et 20 caractères.' ;
}
else
$errors['pseudo'][] = 'Ooops' ;
Post by ricoh51
echo '<p>Bonjour ' . htmlentities($_SESSION['pseudo']) . '</p>';
htmlspecialchars suffit amplement.
ok
Post by Mickael Wolff
Post by ricoh51
Ah? Peux tu développer?
<http://shiflett.org/blog/2005/dec/googles-xss-vulnerability>
pfff, il faut devenir un vrai pirate pour faire un site sans trop de
trou de sécurité :(

Je te remercie beaucoup

eric
John GALLET
2010-06-12 15:13:08 UTC
Permalink
Re,
Post by ricoh51
oui... pas bien, j'ai déjà eu des périodes d'intégrisme d'abstraction
(pas en php je débute), mais pour des petits projets comme ça, je me
demande si ça vaut bien la peine?
Honnêtement: oui. Il faut au moins séparer:
- la décision préalable "j'ai bien reçu une requête cohérente et valide"
- la couche d'interaction avec le stockage
- la couche de "présentation"/sortie, qu'elle soit en html, pdf, excel...
Post by ricoh51
je ne comprends pas cette construction... je ne domine pas assez les
"tableaux" de php je crois :)
Si ça peut t'aider: ce sont des hash tables. Une clef référence une
donnée (qui peut elle même être un autre tableau).
Post by ricoh51
Post by Mickael Wolff
$sql = sprintf('SELECT COUNT(*) AS verif_exist FROM visiteur WHERE
pseudoVisiteur = \'%s\''
, mysql_real_escape_string($pseudo));
ok, ici pour un pseudo, la vérification du type (le %s) n'apporte rien
je pense, mais j'imagine que c'est une bonne habitude à prendre.
Là encore, plusieurs méthodes possibles. Même avec un %d pour "forcer"
un entier, moi je préfère vérifier que c'en est un avant de décider que
je peux faire la requête, et si je m'attends à recevoir un entier
obligatoire comme donnée, si je ne reçois pas un entier, je ne fais même
pas de tentative de requête sql. Cas dans lequel le sprintf %d ne me
sert strictement plus à rien vu que j'ai déjà validé que **c'est** est
un entier.

Accessoirement, algorithmiquement, ça ne sert à rien de faire un select
pour vérifier qu'un pseudo n'existe pas: c'est le boulot de la base de
données. Tu fais ton insert, et si la clef primaire/unique te renvoie
DUPLICATE_KEY... bah c'est qu'il existe déjà... Voir "la stratégie
d'insert/update dans la FAQ de ce forum, http://faqfclphp.free.fr/
Post by ricoh51
Post by Mickael Wolff
mysql_free_result($result) ;
pareil, j'imagine que c'est une bonne habitude à prendre de libérer la
mémoire.
Oui, car en théorie PHP le fait tout seul, mais il y a déjà eut des bugs
où l'appel automatique ne se faisait pas.
Post by ricoh51
Post by Mickael Wolff
$longueur = mb_strlen($pseudo, 'UTF-8') ; // Es-tu certain d'avoir de
l'UTF-8 en entrée ?
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
et ma base de données est entièrement en utf-8.
Deux choses:

- vérifie ce que le serveur web envoie comme HEADER à l'insu de ton
plein gré, car il prime sur ce que tu mets dans ton http-equiv.

- ce n'est pas parce que tu demandes au client (navigateur) de t'envoyer
de l'utf-8 que moi, gentil cracker de base, je ne vais pas justement
t'envoyer du coréen avec wget.

Relis mon document, c'est important: NE JAMAIS partir du principe qu'on
reçoit ce qu'on a demandé. On peut parfaitement "mettre hors jeu" en
rejetant violemment tout ce qui est de manière évidente de la bidouille,
mais il faut le faire, pas partir du principe que ça n'arrivera pas.

Ce dont tu es sûr, sauf si le serveur http envoie avant ton script un
header disant que le charset est autre chose, c'est que la navigateur
est censé comprendre ton output comme utf-8. Tu n'es pas sûr que tu vas
en recevoir. Tu "espères" en recevoir, et si c'est autre chose, tu peux
envoyer sur les roses.
Post by ricoh51
Post by Mickael Wolff
Post by ricoh51
echo '<p>Bonjour ' . htmlentities($_SESSION['pseudo']) . '</p>';
htmlspecialchars suffit amplement.
Rien du tout suffit amplement vu que tu dis envoyer un charset utf-8 si
on part du principe que de toutes façons tu as auparavant interdit
l'utilisation des XSS dans cette donnée en autorisant exclusivement des
caractères "normaux" dans le pseudo. Il n'y a pas de raison qu'on
admette < ou & dans un pseudo. Même si ici caser une XSS en 20
caractères c'est probablement faisable mais plus contraignant.
Post by ricoh51
pfff, il faut devenir un vrai pirate pour faire un site sans trop de
trou de sécurité :(
Il faut en connaître un minimum vital pour ne pas faire une passoire.

a++;
JGA
Michael DENIS
2010-06-03 06:39:07 UTC
Permalink
Post by ricoh51
C'est mon premier message sur ce groupe, je débute en php.
Sur le site du zéro, j'ai trouvé un tuto qui explique ce qu'il faut
Je ne connais pas ces différentes fonctions, mais je serai tenté de vous
donner un conseil simple : pour éviter beaucoup de problèmes, *il suffit
déjà de vérifier que l'on reçoit ce que l'on a demandé*.

Mais encore ? Si j'ai un champ "liste déroulante" par exemple et que la
valeur reçue n'est pas dans la liste ou si je mets un champ avec une
longueur maximum et que j'en reçois plus, il y a vraisemblablement un
problème...
--
Michaël DENIS
ricoh51
2010-06-07 21:37:05 UTC
Permalink
Post by Michael DENIS
Post by ricoh51
C'est mon premier message sur ce groupe, je débute en php.
Sur le site du zéro, j'ai trouvé un tuto qui explique ce qu'il faut
Je ne connais pas ces différentes fonctions, mais je serai tenté de vous
donner un conseil simple : pour éviter beaucoup de problèmes, *il suffit
déjà de vérifier que l'on reçoit ce que l'on a demandé*.
Mais encore ? Si j'ai un champ "liste déroulante" par exemple et que la
valeur reçue n'est pas dans la liste ou si je mets un champ avec une
longueur maximum et que j'en reçois plus, il y a vraisemblablement un
problème...
oui c'est ce que je crois comprendre : Être parano et avoir beaucoup de
bon sens :)

eric
John GALLET
2010-06-05 13:12:46 UTC
Permalink
Bonjour,
Post by ricoh51
C'est mon premier message sur ce groupe, je débute en php.
"Bienvenue chez les fous" (tm).
Post by ricoh51
Sur le site du zéro, j'ai trouvé un tuto qui explique ce qu'il faut
Il y a plusieurs types d'injections sql, et encore plus de types
d'injections xss, ne serait-ce que savoir si elles sont "instantanées"
ou "stockées".
Post by ricoh51
Si je comprends bien, je dois toujours utiliser la fonction bdd si
j'exécute une requête sql à partir d'une donnée d'un formulaire.
Il faut toujours filtrer ses données en entrée, c'est à dire vérifier si
ce qu'on reçoit est bien conforme à ce qu'on attend, y compris comme
déjà suggéré selon des listes de valeurs possibles, mais quand on reçoit
un identifiant muet type autoincrement, ce n'est pas faisable.
Post by ricoh51
Et je ne comprends pas non plus l'intérêt de addcslashes, je croyais que
c'était le boulot de mysql_escape_string.
Bof. Ca fait partie des querelles de clocher.
Post by ricoh51
Et là je dois utiliser la fonction html lorsque je veux écrire dans la
page des données qui proviennent d'un formulaire.
C'est pas aussi simple que ça, là non plus. Si elle vient à l'origine du
monde extérieur et qu'elle a été stockée en base de données, elle ne
vient pas "directement" du formulaire, mais elle peut néanmoins être
dangereuse si on n'a pas fait le boulot avant.
Là encore, querelles de clocher. Personnellement je ne stocke pas des
bombes amorcées dans ma cave: je désamorce d'abord, puis je stocke.
D'autres font le filtrage en sortie de la base de données.
Post by ricoh51
Pouvez-vous me dire si ces deux fonctions sont correctes?
Clairement: non. Même pas le début de commencement des prémisces.
Post by ricoh51
Et y'at-il des cas qui ne sont pas gérés par ces deux fonctions?
Un début de réponse sur un document PDF que j'ai rédigé il y quelques
années déjà, synthèse d'un thread assez long sur fr.comp.securite

http://www.saphirtech.com/securite.html

HTH
JG
ricoh51
2010-06-07 21:37:05 UTC
Permalink
Post by John GALLET
Un début de réponse sur un document PDF que j'ai rédigé il y quelques
années déjà, synthèse d'un thread assez long sur fr.comp.securite
http://www.saphirtech.com/securite.html
merci pour ce lien, je "comprends" maintenant que la sécurité c'est
compliqué :) C'est plutôt flippant je trouve...

Existe-t-il un document du même genre qui donne l'état de l'art (en
2010) pour réaliser un site web avec un espace membre? (pseudo, mot de
passe, mail de confirmation...)

eric
Jean-Francois Ortolo
2010-06-08 10:22:27 UTC
Permalink
Post by ricoh51
Post by John GALLET
Un début de réponse sur un document PDF que j'ai rédigé il y quelques
années déjà, synthèse d'un thread assez long sur fr.comp.securite
http://www.saphirtech.com/securite.html
merci pour ce lien, je "comprends" maintenant que la sécurité c'est
compliqué :) C'est plutôt flippant je trouve...
Existe-t-il un document du même genre qui donne l'état de l'art (en
2010) pour réaliser un site web avec un espace membre? (pseudo, mot de
passe, mail de confirmation...)
eric
Bonjour Monsieur

Pour ce qui est des données reçues par un formulaire, on peut
utiliser les fonctions php ad hoc.

Par exemple, pour le cas de la variable object reçue en mode post par
le script :

$object = filter_input( INPUT_POST, 'object', FILTER_SANITIZE_STRING,
FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_LOW );

if( $object === NULL OR $object === false OR empty( $object )
// traitement d'erreur
else
{
// Traitement OK.
}

Pas besoin de s'embarrasser de filtrages perso par des expressions
rationnelles plus ou moins foireuses, php fait le boulot.

Il y a un certain nombre de ces filtres associés aux fonctions
filter_imput() et autres... C'est dans le PHP Manual.

Bien à vous.

Amicalement.

Jean-François Ortolo
Pascal
2010-06-08 20:59:39 UTC
Permalink
Post by ricoh51
merci pour ce lien, je "comprends" maintenant que la sécurité c'est
compliqué :) C'est plutôt flippant je trouve...
Bonjour,

Faudrait pas devenir parano, non plus! ;-)
Il me semble que le secret d'une sécurisation bien faite consiste
d'abord à l'adapter aux enjeux.

On peut faire le parallèle avec les portes blindées et leurs serrures
multipoint.
Si je n'ai à protéger que des livres de poches et des croûtes au mur, je
ne prendrais ni le même prestataire, ni le même contrat d'assurance, que
si je possède une collection de livres rares et des toiles de maîtres.
Post by ricoh51
Existe-t-il un document du même genre qui donne l'état de l'art (en
2010) pour réaliser un site web avec un espace membre? (pseudo, mot de
passe, mail de confirmation...)
Donc oui, bien sûr, il existe d'autres recommandations, mais pas
forcément adaptées à tout projet ou réalisation.

Dans le "haut de gamme", on peut trouver cela :
http://www.owasp.org/index.php/Category:OWASP_PHP_Project

Chaque framework (cadriciel) proposera son modèle de sécurité, comme par
exemple celui de Zend :
http://framework.zend.com/manual/en/learning.multiuser.html

D'autres permettent d'intégrer des plugins, comme Symfony :
http://www.symfony-project.org/plugins/filter

Tout ça répond à la préoccupation d'avoir quelque chose de sérieux sans
devoir tout réinventer.
Sinon, comme Jean-François le faisait justement remarquer, il existe une
bibliothèque au moins dédiée au filtrage, dans PHP :
http://fr2.php.net/manual/en/book.filter.php

Cordialement,
Pascal
John GALLET
2010-06-12 15:13:08 UTC
Permalink
Re,
Post by ricoh51
merci pour ce lien, je "comprends" maintenant que la sécurité c'est
compliqué :) C'est plutôt flippant je trouve...
Non, c'est juste le syndrôme JCVD: "il faut être aware"... Ne jamais
faire quelque chose sans en comprendre les implications, avantages et
inconvénients.
Post by ricoh51
Existe-t-il un document du même genre qui donne l'état de l'art (en
2010) pour réaliser un site web avec un espace membre? (pseudo, mot de
passe, mail de confirmation...)
Il est "dans l'état de l'art" au sens que nulle nouvelle forme d'attaque
spécifique n'est apparue depuis, juste des raffinements. Ce qui manque,
c'est une bonne couche sur la gestion correcte des charsets.

En revanche, sur l'implémentation pour y arriver, ce document n'étant
même pas "spécifique" à php, il y a plein de moyens.

a++;
JGA
Mickael Wolff
2010-06-10 10:51:05 UTC
Permalink
Post by John GALLET
Post by ricoh51
Et je ne comprends pas non plus l'intérêt de addcslashes, je croyais
que c'était le boulot de mysql_escape_string.
Bof. Ca fait partie des querelles de clocher.
Ce n'est absolument pas une querelle de clocher. addcslashes est une
fausse bonne solution. Lorsqu'on envoie des données à travers une
interface, il faut toujours s'assurer d'utiliser la fonction qui filtre
le mieux la donnée. Et addcslashes, la plupart du temps, n'ayant pas une
connaissace approfondie du problème, ne permet pas de filtrer
correctement les données. Utiliser la fonction qui est faite pour (par
exemple mysql_real_escape_string dans le cas de l'usage du module
mysql), est la seule solution valable.
Post by John GALLET
C'est pas aussi simple que ça, là non plus. Si elle vient à l'origine du
monde extérieur et qu'elle a été stockée en base de données, elle ne
vient pas "directement" du formulaire, mais elle peut néanmoins être
dangereuse si on n'a pas fait le boulot avant.
Là encore, querelles de clocher. Personnellement je ne stocke pas des
bombes amorcées dans ma cave: je désamorce d'abord, puis je stocke.
D'autres font le filtrage en sortie de la base de données.
Et c'est comme ça qu'on se retrouve avec des entités HTML au beau
milieu de documents PDF ou d'images sans même s'en rendre compte. Je
considère la base de données comme une source extérieure de données (une
base de données est faite pour être partagée, c'est une vue persistante
des données métiers).
Post by John GALLET
Post by ricoh51
Et y'at-il des cas qui ne sont pas gérés par ces deux fonctions?
Un début de réponse sur un document PDF que j'ai rédigé il y quelques
années déjà, synthèse d'un thread assez long sur fr.comp.securite
http://www.saphirtech.com/securite.html
Beaucoup de choses avec lesquelles je ne suis pas d'accord, mais on
ne va pas troller :p
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
John GALLET
2010-06-12 15:13:08 UTC
Permalink
Post by Mickael Wolff
Lorsqu'on envoie des données à travers une
interface, il faut toujours s'assurer d'utiliser la fonction qui filtre
le mieux la donnée.
Et donc si tu as une webapp qui doit parler à plusieurs SGBDR, il est
donc nul et non avenu de parler de mysql_realmachin ou quoi que ce soit
d'autre. Ce que je veux dire par querelle de clocher c'est que 10
développeurs différents donneront 10 manières différentes de gérer
l'échappement des quotes en SQL selon qu'ils ont l'habitude de
travailler avec mysql, oracle, sybase (qui n'échape pas avec \ mais avec
une autre '), et je ne parle pas des bidouilles avec access ou autres.
Post by Mickael Wolff
(par exemple mysql_real_escape_string dans le cas de l'usage du module
mysql), est la seule solution valable.
Et si tu as Sybase c'est mort.
Post by Mickael Wolff
Et c'est comme ça qu'on se retrouve avec des entités HTML au beau
milieu de documents PDF ou d'images sans même s'en rendre compte.
Et si on ne le fait pas c'est comme ça comme se retrouve comme un con
avec un PDF qui est en train d'embarquer du JS offensif et est devenu
vecteur d'attaque. Pas plus tard qu'il y a trois jours, l'ISC rappelait
que 28% des attaques de malware sont désormais sur vecteur PDF...

http://isc.sans.edu/diary.html?date=2010-06-09
Troisième article.
Post by Mickael Wolff
Je considère la base de données comme une source extérieure de données (une
base de données est faite pour être partagée, c'est une vue persistante
des données métiers).
C'est une possibilité, je dis juste que cette approche nécessite un
niveau élevé de conscience du danger qu'elle
implique et qu'il est **évident** qu'un jour une autre personne qui
travaille avec cette base, aujourd'hui ou après ton départ, se fera
tarter parce que c'est pas "naturellement sécurisé" comme approche et
surtout non intuitif. Une fois de plus: tout l'enjeu est de comprendre
ce que l'on fait, avantages et inconvénients.
Post by Mickael Wolff
Beaucoup de choses avec lesquelles je ne suis pas d'accord, mais on ne
va pas troller :p
On peut aussi discuter sans troller... Je n'ai pas la parole divine,
loin s'en faut.

a++;
JGA
Mickael Wolff
2010-06-27 11:34:44 UTC
Permalink
Post by John GALLET
Lorsqu'on envoie des données à travers une interface, il faut toujours
s'assurer d'utiliser la fonction qui filtre le mieux la donnée.
Et donc si tu as une webapp qui doit parler à plusieurs SGBDR, il est
donc nul et non avenu de parler de mysql_realmachin ou quoi que ce soit
d'autre. Ce que je veux dire par querelle de clocher c'est que 10
développeurs différents donneront 10 manières différentes de gérer
l'échappement des quotes en SQL selon qu'ils ont l'habitude de
travailler avec mysql, oracle, sybase (qui n'échape pas avec \ mais avec
une autre '), et je ne parle pas des bidouilles avec access ou autres.
C'est ce que j'ai dit : la fonction qui filtre le mieux, qui est la
plus adaptée pour résoudre le problème. Je rajouterai que la bonne
solution sera unique, et ne dépendra pas de l'habitude du programmeur :
le choix doit dépendre des technologies employées.
Post by John GALLET
(par exemple mysql_real_escape_string dans le cas de l'usage du module
mysql), est la seule solution valable.
Et si tu as Sybase c'est mort.
J'ai dit PAR EXEMPLE. Évidamment que pour Sybase ce sera la fonction
ad hoc qu'il faudra employer. Et c'est justement là où ta méthode
préventive part en sucette.
Post by John GALLET
Et c'est comme ça qu'on se retrouve avec des entités HTML au beau
milieu de documents PDF ou d'images sans même s'en rendre compte.
Et si on ne le fait pas c'est comme ça comme se retrouve comme un con
avec un PDF qui est en train d'embarquer du JS offensif et est devenu
vecteur d'attaque. Pas plus tard qu'il y a trois jours, l'ISC rappelait
que 28% des attaques de malware sont désormais sur vecteur PDF...
Justement non. En utlisant un outil correct de génération de PDF, qui
propose une fonction d'échappement tel qu'il existe avecl'HTML, ça ne
peut pas arriver.
Post by John GALLET
http://isc.sans.edu/diary.html?date=2010-06-09
Troisième article.
L'article ne parle pas de PDF générés dynamiquement, mais des PDF
envoyés dans les pourriel. C'est quelque peu hors sujet.
Post by John GALLET
C'est une possibilité, je dis juste que cette approche nécessite un
niveau élevé de conscience du danger qu'elle
implique et qu'il est **évident** qu'un jour une autre personne qui
travaille avec cette base, aujourd'hui ou après ton départ, se fera
tarter parce que c'est pas "naturellement sécurisé" comme approche et
surtout non intuitif. Une fois de plus: tout l'enjeu est de comprendre
ce que l'on fait, avantages et inconvénients.
J'emmerde les incompétents. Et j'emmerde ceux qui les embauche. Je
documente suffisament mon travail pour qu'il soit compris, maintenable
et sécurisé.

Ceci dit, filtrer les données à leur arrivée n'est pas naturel pour
moi. Je peste souvent contre les sites qui restreignent bêtement
l'ensemble des données acceptées par des a priori sans réalité. Ces
restrictions interviennent souvent parce que c'est une personne qui a
codé le contrôleur, a filtré les fonnées ici, plutôt que de faire appel
à un objet métier. L'imbécilité la plus courante est la restriction au
niveau des courriels. Peu de développeurs savent que les adresses
suivantes sont syntaxiquement valides :

mickael+***@example.com
"mickael toto"@example.com

Séquestrer le test sur les adresses e-mail dans une classe et
documenter une classe métier est presque un gage de pérénité du test.
Post by John GALLET
Beaucoup de choses avec lesquelles je ne suis pas d'accord, mais on ne
va pas troller :p
On peut aussi discuter sans troller... Je n'ai pas la parole divine,
loin s'en faut.
Une chose qui nous différencie :p
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
ricoh51
2010-06-18 15:19:53 UTC
Permalink
Un grand merci à tous ceux qui m'ont répondu dans ce fil

eric
Continuer la lecture sur narkive:
Loading...