Synology SA-18-15 : Photo Station - Élévation de privilèges et CRLF

CVE CVE-2018-8925 CVE CVE-2018-8926 Synology SA-18:15

DSM 6.5.1-15254 PhotoStation 6.8.4-3468

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 :

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.

5f0be826addb7fe2a02395c3cf52e38c.png

c191d878052082893602a596e1778fa0.png

Nous pouvons voir que l’utilisateur test n’a pas d’accès à cet album.

347722a12f68662171ab8625f79e422f.png

Maintenant, sur le compte test, nous pouvons nous déconnecter de PhotoStation et changer la description de l’utilisateur avec cette valeur :

(65537)

1fb163fd295cba45557bb066239b2227.png

Si nous retournons sur la PhotoStation avec l’utilisateur test, nous avons maintenant accès à l’album partagé.

b28a81e302377204c78c37424cf05791.png

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 :

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

03b16635e8f932eafafb5db1a421b130.png

Le caractère %0A permet un retour à la ligne.

d7553fe2103280afd204df895977ea8f.png

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.

c76aad246111d1911dff4273f68c985d.png

Mais nous pouvons voir dans les logs que l’utilisateur connecté est notre utilisateur test.

86add36d7730cca1118af80df81fd3f0.png

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.

d54c0be952de97bea5086699d3679eac.png

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.