CVE-2020-25867 : SoPlanning Contournement de vérification de la clé de partage
Historique
- 26/06/2020 : Envoi du rapport à l’équipe de SoPlanning
- 21/07/2020 : Correction de la vulnérabilité
Risques
La vérification de la clé de sécurité est vulnérable à une attaque de confusion de type permettant à un attaquant d’accéder au contenu du calendrier sans connaître la clé de partage.
Prérequis
Pour être exploitable, le partage du calendrier par clé doit être activée.
Une fois ce partage activé, un utilisateur peut accéder au calendrier sans authentification en utilisant la clé de partage.
Bien sûr, si la clé est fausse, l’accès est refusé.
Exploitation
La validation de la clé se fait dans le fichier “includes/header.inc”
if ( CONFIG_SOPLANNING_OPTION_ACCES == 2 && isset($_GET['public']) && isset($_GET['cle']))
{
if (strcmp($_GET['cle'],CONFIG_SECURE_KEY)==0)
{
$_SESSION['public']=1;
$_SESSION['user_id']='publicspl';
}
}
La fonction strcmp est utilisée avec une comparaison non stricte. Le résultat de cette comparaison dépend du tableau disponible ici : PHP type comparison tables
Le résultat de la fonction strcmp est décrit dans la documentation : [strcmp]‘https://www.php.net/manual/en/function.strcmp.php)
Renvoi “< 0” si str1 est plus petit que str2; “> 0” si “str1” est supérieur à “str2”, et 0 si les deux valeurs sont identiques.
La fonction renvoi “NULL” si un des paramètres est un tableau.
En utilisant le tableau PHP type comparison tables, la comparaison non stricte “NULL” et 0 renvoie true
Ainsi, si $_GET[‘cle’] est un tableau, le résultat de la comparaison vaut true et l’accès est autorisé.
Ce lien défini $_GET[‘cle’] comme un tableau : https://demo.soplanning.org/planning.php?public=1&cle[]=
L’accès est permis en tant que “Invité”
Correction
Pour corriger cette vulnérabilité, une comparaison stricte doit être utilisée :
if ( CONFIG_SOPLANNING_OPTION_ACCES == 2 && isset($_GET['public']) && isset($_GET['cle']))
{
if (strcmp($_GET['cle'],CONFIG_SECURE_KEY)===0)
{
$_SESSION['public']=1;
$_SESSION['user_id']='publicspl';
}
}
Il est aussi possible de comparer sans la fonction strcmp.
if ( CONFIG_SOPLANNING_OPTION_ACCES == 2 && isset($_GET['public']) && isset($_GET['cle']))
{
if ($_GET['cle'] === CONFIG_SECURE_KEY)
{
$_SESSION['public']=1;
$_SESSION['user_id']='publicspl';
}
}