Chinese (People's Republic of China)  English  Français


Supinfo-Projects.com
Tous les projets des élèves ingénieurs de Supinfo



Projets
  Dernier Projet
  Les plus populaires
  Tous les Projets

67 Visiteurs
3168 Projets


My Supinfo-Projects

   Connectez-vous
   Créez un Compte


Synopsis

   23 Visites
   Note INTERNET : 20
    (2 Votants)
   0 Commentaires

   Lire l'article

Evaluez cet article

20
18
16
14
12
10
8
6
4
2
0


Commentez cet article

Auteur :

Email :

Votre commentaire :



 
2006 - Note de Synthèse Stage
Backoffice sécurisée en PHP
[30 mn de lecture - paru le 11/5/2006 6:13:45 PM - Public : Confirmé]

Auteur

45925Fabien AGRANIER
Elève-Ingénieur Supinfo Bourgogne
Promotion SUPINFO 2008

   Lui écrire
   Tous les projets de cet auteur
   Le mini-CV de cet auteur

2. Sécurisation des opérations (formulaires)

2.1. Avant propos

Toutes les opérations effectuées à partir de formulaires sont soumises à de nombreux risques car les données qu'elles traitent proviennent de l'extérieur et sont donc non sûres.

Il convient donc de vérifier que les types des données reçues sont bien du type attendu et de protéger toutes les données textes des caractères qui pourront être interprétés par le parseur de la base de données et conduire à des injections SQL. Les manières de contrôler et protéger vos données sont abordés dans cet article

Cependant, vérifier les données ne suffit pas ! En effet, toutes vos opérations partent du principe que votre application fait confiance à l'utilisateur et que toutes les actions qu'il initie sont de son propre fait.
C'est à partir de ce principe qu'un hacker va pouvoir abuser de cette confiance et automatiser certaines taches voir faire exécuter des tâches à un utilisateur à son insu via une attaque de Cross-Site Request Forgeries.

2.3. Cryptogramme visuel

Le principe du cryptogramme visuel est de présenter à l'utilisateur une image contenant un code qu'il devra recopier afin de valider l'exécution de l'action demandée.
Cette méthode est surtout utilisée pour protéger les formulaires d'inscription, mais elle peut aussi servir pour les formulaires d'identification ou de changement de mot de passe.

Le principe de fonctionnement est simple, on génère un code, que l'on affiche dans une image et sauvegarde dans la session, lors de la validation du formulaire, on vérifie que le code entré par l'utilisateur est le même que celui stocké dans la session.

Pour cela nous allons utiliser la classe suivante :

class VisualCryptogram
{                
    /*
     *    Méthode statique publique generate
     *    Génère  un code aléatoire et renvoit une image
     *    Aucune valeur de retour
     */
    public static function generate() {
        // Active la session PHP si ce n'est pas déjà fait
        if(session_id() == "")session_start();
        
        /*
         *    Entêtes de la réponse HTTP
         *    Spécifie qu'il s'agit d'une image et qu'elle ne doit pas être mise en cache
         */
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " gmdate("D, d M Y H:i:s") . " GMT");
        header("Cache-Control: no-store, no-cache, must-revalidate");
        header("Cache-Control: post-check=0, pre-check=0"false);
        header("Pragma: no-cache");
        header("Content-type: image/png");
        
        // Génération du code qui sera affiché (Les caractères trop semblables sont supprimés)
        $charset "23456789ABCDEFGHJKMNPQRSTUVWXYZ23456789";
        $secucode "";
        for($i $i $i++) $secucode .= $charset[mt_rand(0,strlen($charset)-1)];
        
        // Sauvegarde du code dans la session
        $_SESSION['visualcryptogram'] = $secucode;
        
        // Listing des polices utilisées pour l'affichage du code
        $fonts = array("fanta___.ttf""wobbly.ttf","BUNGNIPP.TTF");
        // Création de l'image
        $img    imagecreate(200100);
        $white    imagecolorallocate($img 255255255);
        $black    imagecolorallocate($img 000);
        
        // Ecriture des lettres
        for($i=$i strlen($secucode) ; $i++) {
            // Choix d'une police au hasard
            $font mt_rand(0count($fonts)-1);
            // Choix d'un angle au hasard
            $angle mt_rand(-13 13);
            // Ecriture de la lettre
            imagettftext($img20$angle+ (34 $i), 40$black$fonts[$font], $secucode[$i]);
        }
        
        // Renvoit de l'image
        // Le format jpeg permet d'avoir une image de qualité dégradée et donc d'autant plus dur à reconnaître par OCR
        imagejpeg($img);
        // Suppression de l'image en mémoire
        imagedestroy($img);
    }
    
    /*
     *    Méthode statique publique check()
     *    Vérifie que le code passé en paramètre correspond bien au cryptogramme visuel
     */
    public static function check($code) {
        // Active la session PHP si ce n'est pas déjà fait
        if(session_id() == "")session_start();
        
        if(!isset($_SESSION['visualcryptogram'])) return false;
        return $code == $_SESSION['visualcryptogram'];
    }
}

Nous pouvons donc afficher l'image avec une page contenant simplement le code suivant :

VisualCryptogram::generate();

Et nous pouvons contrôler si le code tapé est correct de cette manière :

if(VisualCryptogram::check($_POST['cryptogram_code']) {
// Code si OK
} else {
// Code si ERR
}

2.4. Système de jetons

Le système précédent permet d'empêcher les attaques de type Cross-Site Request Forgeries puisqu'elle nécessite que l'utilisateur valide lui même l'opération.
Cependant cette méthode est contraignante pour l'utilisateur et ne peut être utilisée pour confirmer toutes les opérations, en particulier celles effectuées dans les applications Web 2.0 qui sont pour la pluspart executées via AJAX sans que l'utilisateur ne s'en rende compte.

Il faut donc trouver un système permettant d'être sûr que les opérations demandées par l'utilisateurs interviennent dans un contexte normal et non dans le cadre d'une attaque.

Pour cela, nous allons mettre en place un système de jeton qui permettra de n'exécuter les opérations que si la demande est accompagnée d'un jeton valide.
Le principe est simple, prenons l'exemple d'une suppression d'élément. Dans la page de confirmation de suppression, nous allons créer un jeton utilisable qu'une seule fois qui devra être transmis lors de la demande de suppression définitive afin de valider son authenticité.
Prenons un deuxième exemple, nous avons une page permettant de déplacer des éléments d'un liste et enregistrons à chaque changement les modifications, il va falloir créer un jeton au chargement de cette page qui aura une durée de vie limitée; renouvelée à chaque utilisation qui devra être transmis lors de toutes les sauvegardes de modifications.

Nous allons utiliser les classes suivantes pour gérer nos jetons :

/*
 * Class Tokens
 * Fournit des méthodes statiques pour gérer les jetons de la sessions
 */
class Tokens
{        
    /*
     *    Méthode statique publique addToken()
     *    Sauvegarde un jeton dans la session en l'indexant par son code et une clef facultative
     */
    public static function addToken($token$key "") {
        if(!isset($_SESSION['token_list'])) $_SESSION['tokens_list'] = array();
        
        $tokencode Tokens::generateTokenCode();
        $_SESSION['token_list'][$key.'_'.$tokencode] = $token;
        return $tokencode;
    }
    
    /*
     *    Méthode statique publique getToken()
     *    Renvoit un jeton en fonction d'un code et d'une clef ou null si aucun jeton ne correspond
     */
    public static function getToken($tokencode$key "") {
        return isset($_SESSION['token_list'][$key.'_'.$tokencode]) ? $_SESSION['token_list'][$key.'_'.$tokencode] : null;
    }
    
    /*
     *    Méthode statique privée generateTokenCode()
     *    Renvoit un code unique pour identifier le jeton
     */
    private static function generateTokenCode() {
        // Ce couplage de fonction permet de générer un jeton quasi unique
        // Cependant ce code est plus simple que celui préconisé par la RFC 4122 
        return uniqid(mt_rand(), true);
    }
}

/*
 *    Interface Token
 *    Définit les méthodes que doivent implémenter les types de jetons
 */
interface TokenI
{
    public function __construct($restriction);
    public function isValid();
    public function consume();
}

/*
 *    Classe UsageToken
 *    Jeton limité en terme d'usage
 */
class UsageToken implements TokenI
{
    private $nbmax;
    private $nb;
    
    public function __construct($nb_use) {
        $this->nb 0;
        $this->nbmax $nb_use;
    } 
    
    public function isValid() {
        return $this->nb $this->nbmax;
    }
    
    public function consume() {
        $this->nb++;
    }
}

/*
 *    Classe UsageToken
 *    Jeton limité en terme de temps
 */
class TimeToken implements TokenI
{
    private $validity;
    private $lastconsumption;
    
    public function __construct($validity_time) {
        $this->validity $validity_time;
        $this->lastconsumption time();
    } 
    
    public function isValid() {
        return (time() - $this->lastconsumption $this->validity);
    }
    
    public function consume() {
        $this->lastconsumption time();
    }
}

Ainsi, dans votre page qui affiche les formulaire a sécuriser, vous pourrez mettre :

$tokencode Tokens::addToken(new UsageToken(1), 'votre_clef_interne');
echo 
'<input type="hidden" name="token" value="'.$token.'" />';

La clef interne vous permet de restreindre le champ d'application des jetons afin que tous vos jetons n'interfèrent pas entre eux et ne puissent servir que pour l'opération pour laquelle ils ont été créés. Ainsi, vous pouvez spécifier la clef 'del_elmt_4' pour votre jeton et vous saurez que ce jeton n'est valide que pour la supression de l'élément d'id 4.

Enfin, vous pourrez tester la validité d'un jeton de la manière suivante :

$token =  Tokens::getToken($_POST['tokencode'], 'del_elmt_'.$_POST['id']);
if(!
is_null($token) && $token->isValid()) {
    
$token->consume();
    
// Code si OK
} else {
    
// Code si ERR
}


Articles de la même catégorie

 Pages : Top


18 Visites
0 Commentaires
8 days - Jeu Flash et PHP
[10 mn de lecture - paru le 11/5/2006 6:09:24 PM - Public : Débutant]

En savoir plus


7 Visites
0 Commentaires
Build Excel documents with XSLT
[20 mn de lecture - paru le 11/5/2006 5:54:29 PM - Public : Confirmé]

En savoir plus


13 Visites
0 Commentaires
Générer des documents Excel avec XSLT
[20 mn de lecture - paru le 11/5/2006 5:53:31 PM - Public : Confirmé]

En savoir plus

   Tous les Articles


SUPINFO Training Center peut vous proposer une formation ...

   Devenez Ingénieur Système Microsoft en 35 jours avec SUPINFO Training Center
   Devenez Certifiés Cisco en 13 jours avec SUPINFO Training Center
   Devenez Administrateur Système Microsoft avec SUPINFO Training Center
   Devenez Développeur Microsoft .NET en 13 jours avec SUPINFO Training Center



Powered by Campus-Booster Technology
Conditions d'utilisation & Copyright | Respect de la vie privée
© Copyright 1965-2006 Supinfo Paris, Paris Academy of Computer Science
Supinfo, Ecole Supérieure d'Informatique et Paris Academy Of Computer Science are trade marks.
23, rue de Château LANDON - 75010 PARIS - Phone : +33 (0) 153359 700 Fax : +33 (0) 153359 701

Web site autided by :