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.
Si vous utilisez Git, vous pouvez simplement faire un cherry-pick des commits pour la bonne version.
Pour cette version, il y a deux commits à utiliser :
Pour la version 1.5.6.2, il n'y a qu'un commit à cherry-picker : f1ef8aa913ea013c42d9f2d702142caf031b4945
Pour la version 1.4.11.0, utilisez ce commit pour votre cherry-pick : 44b811cdd1266a31e8f6754f6fd5c1b10bdef690
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 !
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.
Les modifications à appliquer sont faciles à comprendre :
Observez le commit de PrestaShop 1.5.6.2 ici.
Suivez ces étapes :
I. Modifier 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 AdminLoginController, 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 contrôleur de l'administration qui s'appelle AdminLoginController, ou password.php dans les anciennes versions.
Trouvez le processus appelé (dans le contrôleur) 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 :
(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