Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
French translation of the original article by @Shudrum

Correctif de sécurité

Il existe plusieurs manières d'implémente le dernier correctif de sécurité de PrestaShop. Choisissez celui avec lequel vous vous sentez le plus à l'aise !

  • Pour les utilisateurs de Git : faites du cherry-picking ;
  • Pour les utilisateurs de systèmes Unix : appliquez le correctif à l'aide des fichiers diff ;
  • Pour les autres : copiez les fichiers corrigés ;
  • Pour ceux qui aiment les défis : la méthode "Faite-le vous-même !"

Pour les autres situations (anciennes versions de PrestaShop, fichier Core fortement personnalisés), vous devriez le faire vous-même ! Si vous avez un peu d'expérience de PHP, c'est facile à faire.

Cherry-picker les commits

Si vous utilisez Git, vous pouvez simplement faire un cherry-pick des commits pour la bonne version.

1.6.0.14

Pour cette version, il y a deux commits à utiliser :

1.5.6.2

Pour la version 1.5.6.2, il n'y a qu'un commit à cherry-picker : f1ef8aa913ea013c42d9f2d702142caf031b4945

1.4.11.0

Pour la version 1.4.11.0, utilisez ce commit pour votre cherry-pick : 44b811cdd1266a31e8f6754f6fd5c1b10bdef690

Utiliser les fichiers diff

Si vous êtes un utilisateur de Linux/Unix, vous pouvez utiliser patch pour modifier les fichiers. Utilisez cette méthode uniquement si vous savez ce que vous faites !

Utiliser les fichiers corrigés

Voici les archives Zip pour chaque version :

Le nom du dossier d'administration peut différer du vôtre : assurez-vous bien de lui donner le bon nom !

Attention, si vous avez fait des modifications à certains de ces fichiers, vous les perdrez. Dans ce cas, plutôt que de copier les fichiers tels-quels, vous devriez modifier chaque fichier tel que la section "Faites-le vous-mêmes !" vous l'explique.

Faites-le vous-mêmes !

Les modifications à appliquer sont faciles à comprendre :

Observez le commit de PrestaShop 1.5.6.2 ici.

Suivez ces étapes :

Modifier le générateur de mot de passe de Tools

I. Modifuer la méthode passwdGen de Tools

La méthode passwdGen() prendra deux arguments: $length et $flag. Les versions plus anciennes n'en prennent qu'un seul ($length). Le code doit être un switch() à partir de $flag: s'il n'y a pas de switch() dans votre version, ajoutez-le.

Votre méthode doit maintenant disposer de ce bloc de code :

switch ($flag) {
    case 'NUMERIC':
        $str = '0123456789';
        break;
    case 'NO_NUMERIC':
        $str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
        break;
    case 'RANDOM':
        $num_bytes = ceil($length * 0.75);
        $bytes = Tools::getBytes($num_bytes);
        return substr(rtrim(base64_encode($bytes), '='), 0, $length);
    case 'ALPHANUMERIC':
    default:
        $str = 'abcdefghijkmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    break;
}

Ensuite, le générateur de mot de passe, juste après, doit ressembler à ceci :

$bytes = Tools::getBytes($length);
$position = 0;
$result = '';

for ($i = 0; $i < $length; $i++) {
    $position = ($position + ord($bytes[$i])) % strlen($str);
    $result .= $str[$position];
}

Parfait. Nous allons maintenant ajouter une méthode appelée getBytes($length). Ajoutez-la directement ! Copier-coller ceci :

public static function getBytes($length)
{
    $length = (int)$length;
    
    if ($length <= 0) {
        return false;
    }
    
    if (function_exists('openssl_random_pseudo_bytes')) {
        $bytes = openssl_random_pseudo_bytes($length, $crypto_strong);
        if ($crypto_strong === true) {
            return $bytes;
        }
    }

    if (function_exists('mcrypt_create_iv')) {
        $bytes = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
        if ($bytes !== false && strlen($bytes) === $length) {
            return $bytes;
        }
    }

    // Else try to get $length bytes of entropy
    $result         = '';
    $entropy        = '';
    $msec_per_round = 400;
    $bits_per_round = 2;
    $total          = $length;
    $hash_length    = 20;
    while (strlen($result) < $length) {
        $bytes  = ($total > $hash_length) ? $hash_length : $total;
        $total -= $bytes;
        for ($i=1; $i < 3; $i++) {
            $t1 = microtime(true);
            $seed = mt_rand();
            for ($j=1; $j < 50; $j++) {
                $seed = sha1($seed);
            }
            $t2 = microtime(true);
            $entropy .= $t1 . $t2;
        }
        $div = (int) (($t2 - $t1) * 1000000);
        if ($div <= 0) {
            $div = 400;
        }
        $rounds = (int) ($msec_per_round * 50 / $div);
        $iter = $bytes * (int) (ceil(8 / $bits_per_round));
        for ($i = 0; $i < $iter; $i ++) {
            $t1 = microtime();
            $seed = sha1(mt_rand());
            for ($j = 0; $j < $rounds; $j++) {
                $seed = sha1($seed);
            }
            $t2 = microtime();
            $entropy .= $t1 . $t2;
        }
        $result .= sha1($entropy, true);
    }
    return substr($result, 0, $length);
}

Formidable, le plus dur est fait !

II. [Seulement pour les versions 1.4] Modifier la validité du mot de passe

Cette version utilise une expression régulière pour vérifier la validité du mot de passe. Remplacez-la avec la avec la méthode suivante dans la classe Validate :

public static function isPasswd($passwd, $size = 5)
{
 return (strlen($passwd) >= $size && strlen($passwd) < 255);
}

III. Modifier l'appel de génération de mot de passe utilisateur

Maintenant, trouvez la class Customer, et sa méthode processForgot(), qui est appelée quand l'utilisateur veut générer un nouveau mot de passe.

Elle devrait contenir un appel vers notre méthode de Tools, comme suit :

$password = Tools::passwdGen(MIN_PASSWD_LENGTH)

Remplacez-la avec celle-ci :

$password = Tools::passwdGen(MIN_PASSWD_LENGTH, 'RANDOM')

IV. Modifier l'appel au générateur de mot de passe admin

L'étape finale vise l'appel pour les administrateurs (le même que pour le client).

Il y a un controller de l'administration qui s'appelle AdminLoginController, ou password.php dans les anciennes versions.

Trouvez le processus appelé (dans le controller) processForgot(), et l'appel vers notre méthode de Tools :

$pwd = Tools::passwdGen();

Et remplacez-la par :

$pwd = Tools::passwdGen(10, 'RANDOM');

C'est fini, vous l'avez fait !

Bonjour,
Dans la partie "Faites-le vous-mêmes !", il y a quelques erreurs :

  • III s'applique à PasswordController.php (et non Customer.php)
  • V absent, s'appliquant à Customer.php

(aussi bien sur le version française qu'anglaise de la page).
Il est aussi possible de regarder le 'commit' (comme indiqué au début du chapitre) pour voir les modifications en couleurs.
Bonne journée,
Ruben

kvnbra commented Aug 19, 2015

Bonjour,

Cette partie me semble incomplète :

$bytes = Tools::getBytes($length);
$position = 0;
$result = '';

for ($i = 0; $i < $length; $i++) {
    $position = ($position + ord($bytes[$i])) % strlen($str);
    $result .= $str[$position];
}

Il vaudrait mieux écrire :

$bytes = Tools::getBytes($length);
$position = 0;
$result = '';

for ($i = 0; $i < $length; $i++) {
    $position = ($position + ord($bytes[$i])) % strlen($str);
    $result .= $str[$position];
}

return $result;

Si l'on oublie de changer la variable du "return" cela crée une erreur lors des commandes ou même des faux positifs.

sarda31 commented Aug 24, 2015

Bonjour, j'ai un prestashop 1.4.8.3, comment fais-je? J'ai regardé la préocédure et je n'ai pas

$bytes = Tools::getBytes($length);
$position = 0;
$result = '';

for ($i = 0; $i < $length; $i++) {
$position = ($position + ord($bytes[$i])) % strlen($str);
$result .= $str[$position];
}

dans le fichier tool.

Pouvez vous m'aider

Important : pensez à supprimer le fichier /cache/class_index.php pour être sûr que les modifications soient bien prises en compte.

J'ai comparé le tuto avec les fichiers contenus dans le ZIP. Vous ne parlez pas du fichier controllers/front/PasswordController.php (1.6.0.14). Il faut apparemment remplacer :

$customer->passwd = Tools::encrypt($password = Tools::passwdGen(MIN_PASSWD_LENGTH));
Par
$customer->passwd = Tools::encrypt($password = Tools::passwdGen(MIN_PASSWD_LENGTH, 'RANDOM'));
La question est la suivante : peut-on suivre ce tuto pour n'importe quelle version 1.6 ???

Je vous embête encore. J'ai continué ma comparaison du ZIP et de ce tuto. Pour la classe customer, le zip comporte cette ligne :

$password = Tools::passwdGen(8, 'RANDOM')

et non $password = Tools::passwdGen(MIN_PASSWD_LENGTH, 'RANDOM').

Ce n'est pas très grave mais c'est bizarre de donner deux versions différentes.

Dans la classe tools, la méthode passwdGen() comporte tout au début :

if ($length <= 0)
return false;

Alors que vous n'en faites pas mention. Ne sachant pas à quelle version me fier (ZIP ou tuto) Je n'ai pas comparé toute la méthode getBytes.

Ma question est donc la suivante : sur quelle version doit-on se baser pour faire les correctifs à la main ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment