Accueil
Accueil Le Club Delphi Kylix C C++ Java J2EE DotNET & C# Visual Basic Access Pascal Dev Web PHP ASP XML UML SQLSGBD Windows Linux Autres
logo
Sommaire > Sécurité
        Comment protéger les mots de passe ?
        Comment se protéger du vol de session ?
        Comment déconnecter automatiquement un utilisateur à la fin de sa navigation ?
        Comment générer un captcha ?
        Comment reproduire une faille XSS ?
        Comment se protéger de la faille XSS ?
        Que puis-je faire pour protéger les fichiers source dans lesquels apparaissent en clair des informations sensibles ?
        Comment se protéger des failles d'injection ?
        14.1. Sessions(18)
                Où trouver de la documentation sur les sessions ?
                Comment conserver des variables de page en page ?
                Pourquoi utiliser les sessions ?
                Comment fonctionne une session ?
                Comment démarrer une session ?
                Comment sauvegarder une variable dans une session ?
                Comment savoir si une variable appartient déjà a la session ?
                Comment supprimer une variable d'une session ?
                Quelle est la durée de vie d'une session ?
                Comment fermer une session ?
                Quelles sont les méthodes PHP associées aux sessions ?
                Quelles sont les erreurs possibles ?
                Que sont les en-têtes HTTP ?
                Comment configurer php.ini ?
                Cas particulier de l'hébergeur FREE.FR
                Comment faire cohabiter sur le même serveur deux applications utilisant les sessions ?
                Pourquoi mon site n'est plus valide XHTML depuis que j'utilise des sessions ?
                Pourquoi mes sessions ne fonctionnent plus avec EasyPhp 1.7 ?

precedent    sommaire    suivant   


Comment protéger les mots de passe ?
auteur : july
Les pirates peuvent parfois réussir à voler le contenu d'une base de données. Les noms d'utilisateur et les mots de passe de l'ensemble des utilisateurs leur sont alors accessibles. Les mots de passe doivent donc être stockés, hashés, dans la base de données. Ainsi, en cas de vol de la base, le pirate n'a pas accès aux mots de passe. Ceux-ci devraient être codés avec l'algorithme du SHA 256 car le MD5 a été craqué, ce qui le rend moins efficace. Lorsque l'utilisateur saisit son mot de passe, il est codé et la vérification s'effectue avec les deux versions codées : celle de la base de données et celle saisie.

De cette manière, l'administrateur de la base de données n'a pas non plus accès aux mots de passe en texte clair.

Dès lors, le pirate aura pour but de récupérer les mots de passe en clair en sniffant le réseau. En fait, ils récupèrent les données transitant entre le client et le serveur puisque les mots de passe sont codés côté serveur.

Pour éviter ce problème, il est possible grâce à un JavaScript d'encoder les mots de passe côté client. Le champ mot de passe est vidé grâce au JavaScript donc, dans la requête, seul le mot de passe crypté transite. L'avantage est que si un pirate récupère les données qui voyagent entre le client et le serveur, il récupère un mot de passe crypté et ne peut pas l'utiliser. Le problème est que le JavaScript peut être désactivé par l'utilisateur. Il faut donc, côté serveur, prévoir deux types de vérification de mot de passe : ceux en clair et en crypté.
<?php
$sql = "SELECT U.login, U.password FROM user U WHERE U.login ='".mysql_real_escape_string($_POST['login'])."'";
$result_user = mysql_query($sql);
if ($user = mysql_fetch_object($result_user))
{
    if ($user->password == mhash(MHASH_SHA256, $_POST['password'])
        or $_POST['sha1'] == mhash(MHASH_SHA256, user->password.$_SESSION['grain_de_sel']) )
    {
        ...
        // On redirige vers la rubrique d'accueil après la connexion
        header('HTTP/1.1 204 No Content');
        header('location: index.php');
        exit;
    }
    else
    { 
        // On retourne le même message que cela soit le nom d'utilisateur ou le mot de passe qui soit erroné
        return "<div class=MessErr>Erreur, veuillez essayer de nouveau !</div>";
    }
}
else
{
    // On retourne le même message que cela soit le nom d'utilisateur ou le mot de passe qui soit erroné
    return "<div class=MessErr>Erreur, veuillez essayer de nouveau !</div>";
}
?>

Comment se protéger du vol de session ?
auteur : july
Une méthode peut être mise en place. Le numéro de session ne change jamais. À chaque page, un autre numéro de session aléatoire est généré. Il est stocké dans une variable session et dans un cookie envoyé au client. À la page suivante, on vérifie que le numéro stocké dans la session est bien le même que celui dans le cookie. S'ils sont différents, la session est détruite et les deux (pirate et utilisateur) sont déconnectés. Le délai d'action du pirate qui aurait volé un numéro de session est donc réduit. L'inconvénient est que si l'utilisateur consultait sa dernière page (donc qu'il a fermé son navigateur sans fermer sa session) le numéro reste disponible. La seule solution reste d'éduquer les utilisateurs pour qu'ils cliquent systématiquement sur "se déconnecter" en quittant le site.
<?php
if($logged_in)
{
    // Test des valeurs extérieures afin de vérifier qu'elles n'ont pas été modifiées
    if(!ctype_digit($_COOKIE['id_aleatoire']) or !ctype_digit($_SESSION['id_aleatoire']))
    {
        // Ce ne sont pas des valeurs automatiques => tentative de piratage
    }
    else
    {
        // Récupération l'id dans le cookie
        $id2 = $_COOKIE['id_aleatoire'];

        // Vérification de l'existance
        if( isset($_SESSION['id_aleatoire']) )
        {
            // Comparaison de l'id du cookie avec l'id de la session
            if($id2 != $_SESSION['id_aleatoire'])
            {
                // Si les deux valeurs sont différentes, on détruit la session
                logout();
            }
            else
            {
                // On génère une nouvelle valeur de cookie et dans la variable session
                // Définition de la durée du cookie tjs en secondes dont la date d'expiration est un jour
                $expire = time()+24*3600;

                // Création d'un nb aléatoire que l'on stocke en session et dans le cookie
                $nb_aleatoire = mt_rand();

                // Stockage de ce nombre en session
                $_SESSION['id_aleatoire'] = $nb_aleatoire;

                // Stockage de ce nombre dans le cookie
                setcookie("id_aleatoire", $nb_aleatoire, $expire);
            }
        }
    }
}
?>

Comment déconnecter automatiquement un utilisateur à la fin de sa navigation ?
auteur : july
Un session_timeout doit être implémenté afin de fermer la session si l'utilisateur quitte le site sans se déconnecter (en fermant son navigateur) ou si le temps d'inactivité est trop long.

La fonction de déconnexion doit détruire l'objet $_SESSION de l'utilisateur. Ainsi si un pirate vole la session, elle sera inutilisable. Il faut faire de même avec le cookie, sauf qu'il n'est pas possible de supprimer un cookie (puisqu'il est côté client et qu'il n'est pas possible d'agir sur les fichiers côté client). Il faut donc remplir le cookie d'une valeur volontairement fausse. Si ce cookie était volé, il serait inutilisable puisqu'il ne contiendrait qu'une valeur fausse.
<?php
// Fonction de déconnexion
function logout()
{
    // On remplit le cookie par une valeur fausse pour ne pas être réutilisé
    setcookie("sid", "session ended", time()+3600);

    // Invalidation de l'objet $_SESSION
    session_unset();

    // Destruction de l'objet $_SESSION
    session_destroy();

    // On redirige l'utilisateur vers la page d'accueil
    header('HTTP/1.1 401 Unauthorized ou Authorization required');
    header('location: index.php');
    exit;
}
?>
Ensuite à chaque affichage de page, il faut vérifier si le temps d'inactivité a été dépassé.
<?php
define ('SESSION_TIMEOUT', "1800");
if (isset($_SESSION['login']))
{
    // On vérifie si le temps d'inactivité n'a pas été dépassé
    if(time()-$_SESSION['last_access'] > SESSION_TIMEOUT)
    {
        logout();
    }
    else
    {
        // On stocke l'heure de dernière connexion
        // time s'exprime en secondes à partir du 01/01/70 à 00:00:00
        $_SESSION['last_access'] = time();
    }
}
?>

Comment générer un captcha ?
auteur : july
Il faut utiliser la libgd pour générer une image volontairement dégradée. Bien sûr, moins la fonte utilisée est connue, plus le système est efficace. Il existe des systèmes encore plus efficaces avec des images GIF animées.
<?php

$length = 5; // Longueur de la chaîne générée en image
$alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // Liste des caractères possibles
$nb_characters = strlen($alphabet); // Nombre de caractères possibles

// La variable code contient la chaîne qui sera générée en image
$string = '';
for($i = 0; $i < $length; ++$i)
{
    $string .= $alphabet[mt_rand(0, $nb_characters-1)];
}

// Récupération de la longueur de la chaine à afficher
$str_length = strlen($string);

// Création de la zone image en fonction de la longueur de texte à afficher
$image = imagecreatetruecolor(30 * $str_length, 50);

// Création du fond de l'image
for($x = 0; $x < imagesx($image); ++$x)
{
    for($y = 0; $y < imagesy($image); ++$y)
    {
        if (mt_rand(1,5) == 4 )
        {
            $vred = mt_rand(0, 100);
            $vgreen = mt_rand(0, 100);
            $vblue = mt_rand(0, 100);
        }
        else
        {
            $vred = mt_rand(100, 150);
            $vgreen = mt_rand(100, 150);
            $vblue = mt_rand(100, 150);
        }

        // Allocation d'une couleur au fond
        $color = imagecolorallocate($image, $vred, $vgreen, $vblue);

        // Affichage d'un pixel ayant la couleur du fond
        imagesetpixel($image, $x, $y, $color);

        // Suppression de la couleur du fond allouée
        imagecolordeallocate($image, $color);
    }
}

// Création de la bordure
$vred = mt_rand(0, 240);
$vgreen = mt_rand(0, 240);
$vblue = mt_rand(0, 240);

// Allocation d'une couleur à la bordure
$color = imagecolorallocate($image, $vred, $vgreen, $vblue);

// Tracé de la bordure
imagerectangle($image, 0, 0, imagesx($image)-1 , imagesy($image)-1, $color);

// Suppression la couleur de la bordure allouée
imagecolordeallocate($image, $color);

// Création du texte
for($i = 0; $i < $str_length; ++$i)
{
    $vred = mt_rand(150, 240);
    $vgreen = mt_rand(150, 240);
    $vblue = mt_rand(150, 240);

    $size = mt_rand(20, 30);
    $angle = mt_rand(-10, 20);
    $x = 13 + (20 * $i);
    $y = mt_rand(30, imagesy($image) - 10);
    $color = imagecolorallocate($image, $vred, $vgreen, $vblue);
    $font = 'comic.ttf';

    // Dessin du texte
    imagettftext($image, $size, $angle, $x, $y, $color, $font, $string[$i]);

    // Suppression de la couleur du texte allouée
    imagecolordeallocate($image, $color);
}

// Création de l'image complète au format PNG
header("Content-type: image/png");
imagepng($image);
?>

Comment reproduire une faille XSS ?
auteur : Yogui
Cela se fait en deux temps. D'une part, le code PHP :
echo $_GET['login'];
Ou, si la directive magic_quotes est activée sur votre configuration :
echo stripslashes($_GET['login']);
Ensuite, il suffit d'appeler ce script dans le navigateur avec le paramètre "page" et de lui donner du code JavaScript à exécuter :
http://localhost/test.php?login=<script>alert("Je t'ai eu !");</script>
À partir de là, il ne reste plus qu'à être inventif. Il est par exemple possible de récupérer le contenu des cookies du navigateur pour ce site et d'utiliser Ajax pour s'envoyer le tout... Une faille XSS est simplement l'affichage de valeurs soumises par l'utilisateur, directement dans le navigateur sans aucun filtrage.


Comment se protéger de la faille XSS ?
auteur : Yogui
Il suffit d'envoyer au navigateur Web les caractères auxquels il s'attend. Si l'on souhaite afficher une variable numérique entière :
echo intval($id);
Si l'on souhaite afficher du texte :
echo htmlentities($host, ENT_QUOTES, 'UTF-8');
echo htmlentities($login, ENT_QUOTES, 'UTF-8');
echo htmlentities($password, ENT_QUOTES, 'UTF-8');
echo htmlentities($database, ENT_QUOTES, 'UTF-8');
Notez l'utilisation des deux paramètres optionnels, fondamentaux pour une bonne sécurité. Notez également que le paramètre charset (le dernier) doit être le même dans tout le script. À la longue, cette syntaxe devient fastidieuse. Il est donc préférable de définir une fonction dont l'usage sera plus simple :
function html($string)
{
  return htmlentities($string, ENT_QUOTES, 'UTF-8');
}
echo html($host);
echo html($login);
echo html($password);
echo html($database);
Important : Se protéger de la faille XSS permet de se protéger d'une très grosse partie des failles de sécurité des applications Web.

lien : Définition de cross-site scripting
lien : faq Comment reproduire une faille XSS ?

Que puis-je faire pour protéger les fichiers source dans lesquels apparaissent en clair des informations sensibles ?
auteur : Eusebius
Tout d'abord, il faut bien être conscient que dans le cas d'une configuration saine, le code source n'est pas accessible directement. Seul le code HTML (ou autre) généré par le parseur sera envoyé au client. Ainsi vos identifiants de connexion (par exemple) sont normalement protégés. En supposant que c'est un fichier sur lequel vous faites un include, on peut cependant augmenter le niveau de sécurité.
  • Niveau 1 : vous laissez tel quel, en prenant bien soin de nommer ce fichier en .php et pas en .inc (qui pourraient être lus sans être interprétés).
  • Niveau 2 : vous mettez ce script dans un répertoire protégé par un .htaccess. Par exemple, pour interdire tout accès au répertoire, le fichier .htaccess pourra contenir :
<LIMIT GET POST> order deny,allow deny from all </LIMIT>
  • Niveau 3 (pas forcément réalisable sur n'importe quel hébergement) : vous mettez ce script dans un répertoire non accessible par le serveur web (c'est à dire, pour apache, à l'extérieur du DocumentRoot spécifié dans le httpd.conf), tout en prenant garde qu'il soit toujours accessible par PHP (si open_basedir est spécifié, il doit pointer vers un répertoire parent du répertoire choisi).


Comment se protéger des failles d'injection ?
auteur : Yogui
Il faut échapper les paramètres des fonctions de manière adéquate. Dans le cas d'une requête SQL, il vous faut utiliser le mécanisme mis à disposition par votre SGBD. Certaines classes comme PDO proposent un mécanisme bien plus fiable (les paramètres liés) qui nous évite d'utiliser de telles fonctions.
// MySQL
$string = mysql_real_escape_string($string);

// postgreSQL (string)
$string = pg_escape_string($string);

// postgreSQL (byte)
$string = pg_escape_bytea($string);

// SQLite
$string = sqlite_escape_string($string);

// Expression régulière (remplacez le slash par votre véritable délimiteur)
$string = preg_quote($string, '/');

// Argument de commande shell
$string = escapeshellarg($string);

// Commande shell
$string = escapeshellcmd($string);

// Numérique entier
$int = intval($int);

// Numérique flottant
$float = floatval($float);

precedent    sommaire    suivant   

Consultez les autres F.A.Q's


Les sources présentés sur cette pages sont libre de droits, et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Copyright ©2003  Developpez LLC. Tout droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérets. Cette page est déposée à la SACD.

Vos questions techniques : forum d'entraide Accueil - Publiez vos articles, tutoriels, cours et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones. Nous contacter - Copyright 2000..2005 www.developpez.com