Synology SA-18-15 : Photo Station - Élévation de privilèges et CRLF
Accéder à l’album partagé avec d’autres groupes
Résumé
En modifiant sa description, un utilisateur est en mesure d’accéder à l’album partagé avec un groupe spécifique.
Compromission
Pour réaliser cette attaque, nous avons besoin de plusieurs choses :
- Créer un utilisateur “test” sans droit spécifique
- Créer un groupe “restricted”
Tout d’abord, nous allons obtenir l’identifiant du groupe “restricted” :
# cat /etc/group | grep restricted
restricted:x:65537:
Le groupe “restricted” a l’identifiant 65537.
Maintenant, nous pouvons ajouter un album dans la PhotoStation et le partager avec le groupe restricted.
Nous pouvons voir que l’utilisateur test n’a pas d’accès à cet album.
Maintenant, sur le compte test, nous pouvons nous déconnecter de PhotoStation et changer la description de l’utilisateur avec cette valeur :
(65537)
Si nous retournons sur la PhotoStation avec l’utilisateur test, nous avons maintenant accès à l’album partagé.
Explication
La vulnérabilité est présente dans toutes les fonctions de parsing de synophoto_dsm_user.
if (preg_match('/\((\d+)\)/', $item, $match)) {
$groups[] = $match[1];
}
Pendant le processus de connexion, la commande /usr/syno/bin/synophoto_dsm_user est appelée avec le paramètre “–getinfo $user”.
Le résultat de cette commande est :
# /usr/syno/bin/synophoto_dsm_user --getinfo test
User Name: [test]
User Type: [AUTH_LOCAL]
User uid : [1027]
User gid : [100]
Fullname : []
User Dir : [/var/services/homes/test]
User Shell: [/sbin/nologin]
Expired : [false]
User Mail: []
Alloc Size: [110]
AdminGroup: [0]
Member Of: [1]
(100) users
Nous pouvons voir tous les groupes de cet utilisateur à la fin.
Avec la Description modifiée, le résultat est le suivant :
# /usr/syno/bin/synophoto_dsm_user --getinfo test
User Name: [test]
User Type: [AUTH_LOCAL]
User uid : [1027]
User gid : [100]
Fullname : [(65537)]
User Dir : [/var/services/homes/test]
User Shell: [/sbin/nologin]
Expired : [false]
User Mail: []
Alloc Size: [117]
AdminGroup: [0]
Member Of: [1]
(100) users
La regex utilisée pour faire correspondre les groupes correspond également à notre description modifiée.
La fonction de parsing est utilisée sur plusieurs fichiers :
- photo_login.php
- webapi/authutil.php
- include/photo/synophoto_csPhotoMisc.php
- login.php
Correction
Comparer la taille du tableau groups en PHP avec la taille des groupes donnée par le programme synophoto_dsm_user.
Videz le tableau groups lorsque Member Of: est atteint.
CRLF dans DSM permet d’obtenir un accès administrateur à la station photo.
Résumé
Une vulnérabilité CRLF (Carriage Return Line Feed) affecte le champ Description des utilisateurs dans le DSM.
Cette vulnérabilité permet de modifier le résultat du programme /usr/syno/bin/synophoto_dsm_user utilisé par PhotoStation pour obtenir l’identité de l’utilisateur depuis le DSM. Cette vulnérabilité permet d’obtenir les privilèges d’un administrateur sur l’application.
Exploitation
Nous pouvons réutiliser l’utilisateur de test créé dans la dernière vulnérabilité.
Comme pour l’autre vulnérabilité, nous allons modifier le champ de description de l’utilisateur DSM, mais avec des caractères spéciaux.
Avec un intercepteur de requête, nous allons modifier le champ de description avec cette valeur :
%0AUser Name: [root
Le caractère %0A permet un retour à la ligne.
Maintenant, nous devons nous connecter avec le lien DSM (avec les paramètres sid, usr et SynoToken). Une connexion à partir de l’interface PhotoStation ne permet pas l’exploitation de la vulnérabilité.
Nous sommes automatiquement connectés en tant que admin.
Mais nous pouvons voir dans les logs que l’utilisateur connecté est notre utilisateur test.
Explication
Cette vulnérabilité est située dans la fonction loginFromDsm du fichier login.php.
Lorsque l’utilisateur test utilise le lien DSM pour entrer dans la PhotoStation, la fonction loginFromDsm est appelée. L’utilisateur est authentifié avec la commande suivante :
# /usr/syno/bin/synophoto_dsm_user --current test aMrmsYG8F8LW.DWTY7O3CO72HI 192.168.0.8 AMijHxIFDF9R
true
Si l’utilisateur est valide sur DSM, toutes les informations sur l’utilisateur sont récupérées :
# /usr/syno/bin/synophoto_dsm_user --getinfo test
User Name: [test]
User Type: [AUTH_LOCAL]
User uid : [1027]
User gid : [100]
Fullname : []
User Dir : [/var/services/homes/test]
User Shell: [/sbin/nologin]
Expired : [false]
User Mail: []
Alloc Size: [129]
AdminGroup: [0]
Member Of: [1]
(100) users
Avec ces informations, la fonction de parsing SYNOPHOTO_LoginUserDataPaser est appelée pour extraire des données de ce résultat.
Cette fonction lit les lignes dans l’ordre. Avec ce comportement, si nous injectons un nouveau Nom d’utilisateur: ,nous sommes capables de manipuler le nom d’utilisateur extrait.
Avec la description modifiée de l’utilisateur, voici le résultat de la commande :
# /usr/syno/bin/synophoto_dsm_user --getinfo test
User Name: [test]
User Type: [AUTH_LOCAL]
User uid : [1027]
User gid : [100]
Fullname : []
User Name: [root]
User Dir : [/var/services/homes/test]
User Shell: [/sbin/nologin]
Expired : [false]
User Mail: []
Alloc Size: [129]
AdminGroup: [0]
Member Of: [1]
(100) users
Le code PHP suivant définit la valeur de la session qui nous donne les privilèges d’administrateur.
if (strtoupper($user) == "ADMIN" || strtoupper($user_info[0]) == strtoupper(SYNOPHOTO_ADMIN_NAME) ) {// admin
$_SESSION[SYNOPHOTO_ADMIN_USER]['admin_syno_user'] = SYNOPHOTO_ADMIN_PASS;
}
Nous ne pouvons pas changer la valeur $user, mais nous pouvons changer la valeur $user_info[0]. La valeur SYNOPHOTO_ADMIN_NAME est root.
Avec ce champ de session, nous sommes considérés comme administrateur sur toute l’application PhotoStation.
Correction
La correction doit être faite sur DSM et l’application PhotoStation.
Il est possible que cette vulnérabilité ait un impact sur d’autres applications ou fonctionnalités de DSM.
Pour DSM, une limitation des caractères côté serveur peut être appliquée pour n’autoriser que les bons caractères.
Sur la PhotoStation, la fonction d’analyse doit être modifiée pour éviter toute valeur indésirable.
Voici un exemple de correctif :
function SYNOPHOTO_LoginUserDataPaser($pUser,$user,$ip)
{
global $SYNOPHOTO_DSM_USER_INFO;
$result = array();
if (!is_array($pUser)) {
return null;
}
$groups = array();
$groups_size = 0;
foreach ($pUser as $item) {
if (preg_match('/^\((\d+)\)/', $item, $match)) { //^ -> The group line have to start with (num)
$groups[] = $match[1];
}
if (!preg_match('/(^\w+\s?\w+)\s*\:/', $item, $match) || !preg_match('/\[(.*)\]/', $item, $match_val)) {
continue;
}
if (preg_match('/Member Of: \[(.*)\]/',$item,$group_match)){ // Get number of group
$groups = array();
$groups_size = $group_match[1];
if(sizeof($groups) != 0){
PhotoLog::Add($user." wants to access secret pictures... "."[".$ip."].", false, $user);
}
}
if (false !== $index = array_search($match[1], $SYNOPHOTO_DSM_USER_INFO)) {
if(isset($result[$index])){ // If field is overwrite.
PhotoLog::Add($user." try to attack the platform... "."[".$ip."].", false, $user);
exit(0);
}
$result[$index] = $match_val[1];
}
}
$result['groups'] = implode(',', $groups);
if(sizeof($groups) != $groups_size){
PhotoLog::Add($user." wants to access secret pictures... "."[".$ip."].", false, $user);
exit(0);
}
return $result;
}
Ce correctif nécessite de passer deux variables supplémentaires à la fonction d’analyse ($user, $ip). Si ce patch est utilisé sans ajouter ces paramètres, il est possible de simplement les supprimer et de changer le message du journal.
On peut voir sur la page de log que les deux types d’attaque sont bloqués.
CSRF dans PhotoStation permettant à un attaquant d’obtenir un compte administrateur sur PhotoStation.
La partie administration de l’application PhotoStation n’est pas protégée contre le CSRF (Cross-Site Request Forgery) et permet à un attaquant d’obtenir un compte d’administrateur sur la PhotoStation en envoyant une page web malveillante à l’administrateur.
Correction
Ajouter un jeton anti-CSRF à tous les formulaires sensibles.