CVE-2020-25867 : SoPlanning Contournement de vérification de la clé de partage

CVE CVE-2020-25867

SoPlanning 1.46.01 SoPlanning > 1.47

Historique

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.

EnableSharingKey

Une fois ce partage activé, un utilisateur peut accéder au calendrier sans authentification en utilisant la clé de partage.

NormalBehavior

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[]=

Exploit

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';
  }
}