sécurisé mon site

keviin1988
Invité n'ayant pas de compte PHPfrance

24 oct. 2009, 13:21

Salut,
cela fait un moment que je cherche à sécurisé mon site contre les injection sql et autre type d'attaque mais j'avance vraiment pas :( .Les tuto que je trouve sont contradictoire ...J'ai un accès à php.ini ,es que je doit mettre les magic quotes en OFF ?

Si j'écris se code pour une chaine de caractère comme paramètre
$ pseudo = mysql_real_escape_string ($ _GET [ 'pseudo']);
$ requete = mysql_query ( "SELECT age FROM membres WHERE pseudo = '$ pseudo'");

et se code pour un entier comme paramètre
$ id = intval ($ _POST [ 'id']);
$ requete = mysql_query ( "SELECT age FROM membres WHERE id = $ id");
es que mon site sera sure ?

je suis perdu , merci énormément d'avance

Mammouth du PHP | 985 Messages

24 oct. 2009, 14:15

J'ai un accès à php.ini ,es que je doit mettre les magic quotes en OFF ?
En théorie oui, d'autant plus qu'à partir de PHP 6, ils seront définitivement supprimés.
Donc oui, tu peux les mettre à OFF.
$ pseudo = mysql_real_escape_string ($ _GET [ 'pseudo']);
$ requete = mysql_query ( "SELECT age FROM membres WHERE pseudo = '$ pseudo'");
En théorie, c'est assez sécurisé si, et seulement si, tu utilises la fonction mysql_real_escape_string() et que tu entoures ta variable ensuite de simples guillemets.
Par contre, pour éviter les erreurs de Type Notice et certains bugs, il est préférable de toujours vérifier si la variable est définie avant...
Il est préférable aussi de prendre comme habitude aussi de toujours sortir les variables.
Donc:
$pseudo = (isset($_POST['pseudo'])) ? trim($_POST['pseudo']) : null;

if(!empty($pseudo)) {
$requete = mysql_query('SELECT age FROM `membres` WHERE pseudo = ' . "'" . mysql_real_escape_string($pseudo) . "'");
}
$ id = intval ($ _POST [ 'id']);
$ requete = mysql_query ( "SELECT age FROM membres WHERE id = $ id");
Avec une variable contenant un entier, effectivement aucun besoin d'utiliser mysql_real_escape_string() ou d'entourer la variable de simples guillemets si, et seulement si, on est certain que cette même variable contient bien un entier.
Donc en théorie, en utilisant la fonction intval(), oui cela est assez sécurisé.
Seul bémol: Vue que tu ne fais aucune autre vérification avant la fonction intval(), si l'utilisateur envoi un caractère particulier comme un @ -> cela risque de faire, je croie, planter le script.
Pour moi, l'utilisation de la fonction intval() dans ces circonstances est une erreur.
Donc je ferais personnellement, comme ceci:
$id = (isset($_POST['id'])) ? trim($_POST['id']) : null;

if(!empty($id) && ctype_digit($id)) {
$requete = mysql_query('SELECT age FROM `membres` WHERE id = ' . $id);
}
Ou si pour une raison particulière, tu as besoin de l'utilisation de la fonction intval() dans ce cas précis:
$id = (isset($_POST['id'])) ? trim($_POST['id']) : null;

if(!empty($id) && ctype_digit($id)) {
$requete = mysql_query('SELECT age FROM `membres` WHERE id = ' . intval($id));
}
Ou encore, si tu veux prendre en compte les lettres aussi:
$id = (isset($_POST['id'])) ? trim($_POST['id']) : null;

if(!empty($id) && ctype_alnum($id)) {
$requete = mysql_query('SELECT age FROM `membres` WHERE id = ' . intval($id));
}
Ou pour finir, si tu veux prendre en compte les "." aussi:
$id = (isset($_POST['id'])) ? trim($_POST['id']) : null;

if(!empty($id) && preg_match('#^[[:alnum:]\.]{1,}$#', $id)) {
$requete = mysql_query('SELECT age FROM `membres` WHERE id = ' . intval($id));
}
Il existe d'autres techniques et habitudes..., ici c'est juste un exemple :wink:

[EDIT]
Personnellement, j'ai toujours pris comme habitude en développement de toujours filtrer les données.
C'est à dire: vérifier les caractères des variables avec des c_type ou des preg_.
C'est une protection supplémentaire, parfois non indispensable mais souvent la seule solution véritablement fiable.
On est jamais à l'abri d'une erreur, d'un oubli ou d'un élément inconnu...

Sinon:
mysql_real_escape_string n'échappe ni % , ni _ . Ce sont des jokers en MySQL si combinés avec LIKE , GRANT , ou REVOKE .
Si magic_quotes_gpc est activée, appliquez d'abord la fonction stripslashes à vos données
Face à la roche, le ruisseau l'emporte toujours, non pas par la force mais par la persévérance.

ViPHP
ViPHP | 1996 Messages

24 oct. 2009, 19:14

Pour compléter, j'utilise, un peu dans l'optique des ctype les fonctions is_X comme is_string () is_numeric(), ...
Sinon comme dit dr@ke : faire toujours un isset() ou un empty() avant c'est mieux.
Comme ceci, si la variable reçu n'existe pas ou si elle n'est pas dans le bon format en plus de la protection slashes (tu as aussi la foncion php addslashes()) tu es à peu près bien sécurisé.

Un ch'tio conseil : créé toi une fonction cela reviendra à être plus rapide.
It is nice to be important but it is more important to be nice
http://www.aureuswebfactory.fr

keviin1988
Invité n'ayant pas de compte PHPfrance

25 oct. 2009, 03:54

Merci énormément c'est très complet comme explication.Le problème c'est que je suis très débutant en php et pour terminer mon site sa ma pris un mois alors que l'un de vous le fera en moins d'une journée :(
voici un bout de mon code

Code : Tout sélectionner

<?php if( isset($_POST['email'])) { $email = (isset($_POST['email'])) ? trim($_POST['email']) : null; $email = (isset($_POST['pw'])) ? trim($_POST['pw']) : null; $_SESSION['email'] = $email ; $_SESSION['pw'] = $password; } else if (isset($_SESSION['email'])) { $email=$_SESSION['email']; $password=$_SESSION['pw']; } else { header('Location:index.php'); } //requête permettant de voir si l'utilisateur existe déja dans la base if(!empty($email)&&!empty($password)) { $sql = 'SELECT id_membres,statut FROM membres WHERE email = ' . "'" . mysql_real_escape_string($email) . "'" AND password = ' . "'" . mysql_real_escape_string($password) . "'" LIMIT 1'; } $query= mysql_query($sql); $result = mysql_fetch_array($query); $id=$result[0]; $_SESSION['id']=$id;
mais j'ai une erreur a cette ligne :(

Code : Tout sélectionner

$sql = 'SELECT id_membres,statut FROM membres WHERE email = ' . "'" . mysql_real_escape_string($email) . "'" AND password = ' . "'" . mysql_real_escape_string($password) . "'" LIMIT 1'; }
Pour ce qui es des fonction je sais pas trop comment les utilisés non plu :(
merci beaucoup de votre aide et d'avoir été là a chaque fois que j'ai u besoin d'aide :oops:

ViPHP
fab
ViPHP | 2657 Messages

25 oct. 2009, 15:02

Essaye plutôt :

$sql = 'SELECT id_membres,statut FROM membres WHERE email =  "'. mysql_real_escape_string($email) .'" AND password = "'.mysql_real_escape_string($password) .'" LIMIT 1'; 

Seul l'intelligent a le pouvoir de se trouver con
try { work(); } catch(FlemmeExeption $e) { sleep(84600); }

Mammouth du PHP | 985 Messages

25 oct. 2009, 16:02

Je te conseil de télécharger et de regarder les script de zones membres sur cette page:
http://www.manuelphp.com/scripts/script ... re&idaff=2.

Utilise un des scripts et adapte le à ton propre site.
Ton script actuel présente plusieurs erreurs et incohérences.
Cela sera donc plus simple et plus sécurisé comme base de départ.
Si ensuite tu as besoin d'aide pour l'adapter ou le sécuriser, tu pourras re-poster un autre sujet...
Face à la roche, le ruisseau l'emporte toujours, non pas par la force mais par la persévérance.

keviin1988
Invité n'ayant pas de compte PHPfrance

25 oct. 2009, 22:47

Salut et merci pour t'as réponse,
non je tiens vraiment que le site soit entièrement mon œuvre, et pour les zones membres ça fonctionne très bien avec moi je ne vois pas où est le problème.
pour ma requête je crois que c'est bon :
$sql = 'SELECT id_membres,statut FROM membres WHERE email = "'. "'".mysql_real_escape_string($email). "'".'" AND password = "'."'" .mysql_real_escape_string($password)."'" .'" LIMIT 1'; 


es que mon bout de code est sure la ? j'ai entendu dire qu'il faut utilisé une fonction pour protégé les variable lors de l'affichage pour éviter les attaque "xss" si je m'en souviens bien.quelqu'un peut me donné une info sur ça ?
merci énormément pour tot

Mammouth du PHP | 985 Messages

25 oct. 2009, 23:21

Non ton code n'est pas sur car, comme je te l'ai dis, il comporte plusieurs erreurs et incohérences...

Sinon pour ta requête:
$sql = 'SELECT id_membres,statut FROM membres WHERE email = ' . "'" . mysql_real_escape_string($email) . "'" . ' AND password = '  . "'" . mysql_real_escape_string($password) . "'" . ' LIMIT 1';
Pour les failles Xss, il faut utiliser la fonction htmlspecialchars(), au moment de l'affichage des données, par exemple avec echo.

http://php.net/manual/fr/function.htmlspecialchars.php

Exemple:
// Au lieu de:
echo $email;
// faire:
echo htmlspecialchars($email);
Face à la roche, le ruisseau l'emporte toujours, non pas par la force mais par la persévérance.

keviin1988
Invité n'ayant pas de compte PHPfrance

26 oct. 2009, 01:18

Merci beaucoup,
es que tu peut me dire une erreur ou une incohérence ?
merci

ViPHP
fab
ViPHP | 2657 Messages

26 oct. 2009, 05:14

Par exemple après ton select tu vérifies pas si il existe bien des résultats! Tu encodes pas les caractères HTML, le password transit par l'utilisateur
Seul l'intelligent a le pouvoir de se trouver con
try { work(); } catch(FlemmeExeption $e) { sleep(84600); }

ViPHP
ViPHP | 1996 Messages

26 oct. 2009, 09:08

J'ai pas lu les réponses en dessous mais tu écrases ta valeur récupérée en $_GET['email'] ?
if( isset($_POST['email']))
{
$email = (isset($_POST['email'])) ? trim($_POST['email']) : null;

$email = (isset($_POST['pw'])) ? trim($_POST['pw']) : null; // ICI
Edit : moi cela fait 4 ans que je bosses sur mon site. Dès que je pense avoir terminer : hop! nouveau script d'optimisation pour aller plus vite, plus sécurisé, plus... : tu n'en finira jamais selon moi. Surtout si tu suis l'informatique. C'est passionnant tu vas voir.
It is nice to be important but it is more important to be nice
http://www.aureuswebfactory.fr

Eléphanteau du PHP | 24 Messages

26 oct. 2009, 13:14

Bonjour,
Je me permet de m'immiscer dans la conversation car c'est un sujet qui m'intéresse beaucoup.

J'aurais une petite question, quelle est la différence entre isnumeric et ctype_digit ? J'utilise seulement isnumeric sur mon site pour vérifier des enregistrements qui ne peuvent contenir que des nombres entiers, est-ce suffisant ou faut-il aussi utiliser des htmlspecialchars et des mysql_real_escape_string ?
J'ai essayé de mettre une arobase ou un pourcentage, et la vérification fonctionne bien sans planter.

Et fab, qu'appelles-tu : "le password transit par l'utilisateur" ?

Merci

ViPHP
fab
ViPHP | 2657 Messages

26 oct. 2009, 13:17

Tu stockes le password dans une variable de SESSION et c'est jamais très recommandé pour des questions de sécurité en cas de vol de cookie
Seul l'intelligent a le pouvoir de se trouver con
try { work(); } catch(FlemmeExeption $e) { sleep(84600); }

Mammouth du PHP | 985 Messages

26 oct. 2009, 13:39

Bonjour,
J'aurais une petite question, quelle est la différence entre isnumeric et ctype_digit ? J'utilise seulement isnumeric sur mon site pour vérifier des enregistrements qui ne peuvent contenir que des nombres entiers, est-ce suffisant ou faut-il aussi utiliser des htmlspecialchars et des mysql_real_escape_string ?
Merci
is_numeric : http://php.net/manual/fr/function.is-numeric.php
ctype_digit: http://php.net/manual/fr/function.ctype-digit.php
$n = '1234.5';
$numeric_string = '42';
$integer        = 42;

var_dump(is_numeric($n));  // returns bool(true)
var_dump(ctype_digit($n)); // returns bool(false)

ctype_digit($numeric_string);  // true
is_numeric($numeric_string);   // true

ctype_digit($integer);         // false
is_numeric($integer);          // true

ctype_digit("-1")   //false
ctype_digit() n'accepte que des entiers (chiffres) positifs, cela dépend donc de ce que ta variable doit contenir...


mysql_real_escape_string : http://php.net/manual/fr/function.mysql ... string.php
mysql_real_escape_string() appelle la fonction mysql_escape_string() de la bibliothèque MySQL qui ajoute un slash aux caractères suivants : NULL, \x00, \n, \r, \, ', " et \x1a.
Donc si ta variable contient un entier, inutile d'utiliser mysql_real_escape_string().

htmlspecialchars: http://php.net/manual/fr/function.htmlspecialchars.php
Les remplacements effectués sont :
* "&" (et commercial) devient "&amp ;"
* """ (guillemets doubles) devient "&quot ;" lorsque ENT_NOQUOTES n'est pas utilisée.
* "'" (guillemet simple) devient "& #039;" uniquement lorsque ENT_QUOTES est utilisée.
* "<" (inférieur à) devient "&lt ;"
* ">" (supérieur à) devient "&gt ;"
Donc même chose, si ta variable contient un entier -> inutile d'utiliser htmlspecialchars().
Face à la roche, le ruisseau l'emporte toujours, non pas par la force mais par la persévérance.

Eléphanteau du PHP | 24 Messages

26 oct. 2009, 15:21

Ouahhh, Drake, ça c'est de la réponse complète et argumenté et plus compréhensible que le manuel, merci.
Donc ne stockant que des entiers positif, ctype_digit serait plus approprié.
Il n'y a qu'un détail que je ne comprends pas bien, pourquoi ctype renvoi faux pour $integer = 42; ? Je croyais que les nombres n'avaient pas besoin d'être mis entre crochet pour être reconnu ? Et donc j'essaierai ce soir, mais que va renvoyer $integer = $_tableau['nombre']; ?

Tu stockes le password dans une variable de SESSION et c'est jamais très recommandé pour des questions de sécurité en cas de vol de cookie
Je croyais que les sessions étaient générées coté serveur et que au niveau client l'identification restait dans la ram. Enfin c'est pas grave, moi je ne le fais pas. :)


Et désolé de squatter ton topic kevin, j'espère au moins que ça va te servir.