IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

FAQ PHP

FAQ PHPConsultez toutes les FAQ

Nombre d'auteurs : 68, nombre de questions : 580, dernière mise à jour : 18 septembre 2021 

 
OuvrirSommaireSécurité

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.

 
Sélectionnez
<?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é.

 
Sélectionnez
<?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();
    }
}
?>
Créé le 8 février 2007  par 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é.

 
Sélectionnez
<?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>";
}
?>
Créé le 8 février 2007  par 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.

 
Sélectionnez
<?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);
?>
Créé le 8 février 2007  par july

Cela se fait en deux temps. D'une part, le code PHP :

 
Sélectionnez
echo $_GET['login'];

Ou, si la directive magic_quotes est activée sur votre configuration :

 
Sélectionnez
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 :

 
Sélectionnez
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.

Créé le 7 janvier 2007  par Guillaume Rossolini

Il suffit d'envoyer au navigateur Web les caractères auxquels il s'attend. Si l'on souhaite afficher une variable numérique :

 
Sélectionnez
// Valeur numérique entière
echo intval(10.5); // conversion avec une fonction
echo (int) 10.5; // cast type C

// Valeur numérique flottante
echo floatval(10.5); // conversion avec une fonction
echo (float) 10.5; // cast type C

Si l'on souhaite afficher du texte (attention, la fonction strval() n'est pas suffisante) :

 
Sélectionnez
echo htmlentities("Je suis développeur PHP", ENT_QUOTES, 'ISO-8859-1');

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 est plus simple :

 
Sélectionnez
function html($string)
{
return htmlentities($string, ENT_QUOTES, 'ISO-8859-1');
}

echo html($_POST['username']);
echo html($_POST['title']);
echo html($_POST['message']);
 
Sélectionnez
function html($string)
{
return htmlspecialchars($string, ENT_QUOTES);
}

echo html($_POST['username']);
echo html($_POST['title']);
echo html($_POST['message']);

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.

Créé le 7 janvier 2007  par Guillaume Rossolini

Lien : Définition de cross-site scripting
Lien : Comment reproduire une faille XSS ?
Lien : Tutoriel sur la sécurité en développement Web, par Julien Pauli

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).
  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 :

     
    Sélectionnez
    <LIMIT GET POST> order deny,allow deny from all </LIMIT>
  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).
Créé le 8 août 2006  par Eusebius

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.

 
Sélectionnez
// 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);
Créé le 7 janvier 2007  par Guillaume Rossolini

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2003 Developpez.com Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.