En bref : nous avons découvert une autre RCE différée dans MECCHA CHAMELEON. En jouant sur la carte d'un attaquant, celui-ci peut exploiter une fonction exposée pour écrire arbitrairement des fichiers sur le système de la victime. Cela peut mener à une exécution de code à distance sur le système de la victime après un redémarrage. Nous avons signalé le problème aux mainteneurs du jeu, qui ont corrigé la vulnérabilité dans la mise à jour 4.0.0. Cette mise à jour s'installe automatiquement avant le lancement du jeu.
Si vous êtes gamer, vous avez probablement entendu parler de MECCHA CHAMELEON. Ce jeu de cache-cache en ligne est devenu un phénomène mondial, avec 15 millions d'exemplaires vendus dès son premier mois !
En tant que joueur, votre rôle est on ne peut plus simple : trouver une bonne cachette et peindre un personnage blanc uni pour qu'il s'accorde avec le décor. Ensuite, l'un de vos amis vient vous traquer. Vous gagnez si le chasseur ne parvient pas à vous trouver. C'est aussi simple que ça !

Les cartes créées par la communauté représentent une grande partie de l'attrait du jeu. N'importe qui peut créer une nouvelle carte pour y cacher des joueurs et la publier via le Steam Workshop. Ces nouvelles cartes peuvent être des galeries d'art, des zones nostalgiques issues d'autres jeux, etc.

Une fonctionnalité spécifique a retenu notre attention : lorsque vous jouez sur un serveur, l'hôte du salon choisit la carte et tous les joueurs présents sont incités à la télécharger (l'écran vous interpelle si vous ne l'avez pas encore téléchargée et que vous retardez le parti !). C'est très pratique, mais cela signifie également que rejoindre une partie peut impliquer de charger une carte conçue par quelqu'un que vous n'avez jamais rencontré. Nous voulions savoir ce que cette carte téléchargée était réellement autorisée à faire.
Par le passé, MECCHA CHAMELEON avait déjà souffert d'une RCE lors du chargement d'une carte, comme le détaille cet article de blog. Ce bug spécifique a depuis été corrigé, mais cela a-t-il éliminé toutes les voies d'accès à une RCE ?
Qu'est-ce qu'une carte MECCHA CHAMELEON en réalité ?
Vous pourriez supposer qu'une carte n'est qu'un ensemble d'actifs : des modèles pour le décor et des textures pour que tout ait l'air correct. C'est ainsi qu'une carte fonctionne dans de nombreux jeux, où le fichier téléchargé décrit le niveau tandis que le jeu lui-même contrôle la logique.
Les cartes de MECCHA CHAMELEON disposent d'un contrôle supérieur. Le jeu est construit avec Unreal Engine 5.6.1, et ses cartes peuvent contenir des Blueprints. Le Blueprint est le système de programmation visuelle d'Unreal. Vous pouvez connecter des nœuds pour déclencher une action lorsqu'un joueur appuie sur un bouton, entre dans une zone ou charge simplement la carte.

Bien évidemment, une carte ne peut pas appeler toutes les fonctions d'Unreal ou de MECCHA CHAMELEON. Une fonction native doit d'abord être exposée au Blueprint. Au démarrage de la carte, ses graphes s'exécutent au sein du processus MECCHA CHAMELEON. Si un graphe appelle une fonction exposée, le jeu exécute cette action en utilisant le compte et les permissions du joueur.
Cela signifie que les cartes personnalisées constituent une surface d'attaque intéressante :
- Un hôte de salon peut inciter tous les autres joueurs à télécharger et à exécuter une carte.
- Cette carte peut ensuite exécuter des graphes Blueprint à l'intérieur du jeu.
J'ai donc commencé à prêter attention aux fonctions du moteur auxquelles je pouvais accéder.
Recherche de fonctions appelables
Heureusement, nous n'avons pas à deviner quelles fonctions Unreal expose. Nous pouvons ouvrir un graphe Blueprint et faire un clic droit sur une zone vide. Unreal affiche alors un menu de nœuds consultable et interrogeable pouvant être ajoutés à ce graphe.

D'un point de vue de la sécurité, je m'intéressais principalement aux fonctions qui interagissaient d'une manière ou d'une autre avec le système d'exploitation. J'ai donc recherché celles contenant enregistrer, exporter, écrire, enregistrer, open, lancer, et load. Nous sommes passés d'une liste interminable d'API à une liste gérable que je pouvais analyser.
J'ai donc examiné ces fonctions une par une jusqu'à ce que je tombe sur Terminer l'enregistrement de la sortie. Celle-ci est sortie du lot car elle pouvait créer un fichier sur le système de fichiers avec un chemin pouvant être absolu ou relatif. Elle stocke également une sortie audio, que nous pouvons probablement contrôler d'une manière ou d'une autre.

Écriture de fichiers n'importe où
Ainsi, pour utiliser la fonction Terminer l'enregistrement de la sortie , un créateur de carte doit démarrer un enregistrement, diffuser un son, puis arrêter l'enregistrement. Nous fournissons ensuite un nom et un chemin d'enregistrement. La fonction est documentée plus en détail ici.

Il s'agit donc d'un cas typique de « Fournissez simplement n'importe quel répertoire et n'importe quel nom de fichier, et nous pouvons enregistrer ces fichiers n'importe où sur le système », n'est-ce pas ?
Eh bien, oui. Vous pouvez simplement fournir C:\Users\Public\ comme chemin de fichier et y écrire des fichiers, ou vous pouvez fournir un chemin relatif. Le répertoire par défaut utilisé est C:\Users\<user>\AppData\Local\Chameleon\Saved\BouncedWavFiles, donc en fournissant un chemin commençant par ../../../../../, nous pouvions accéder au dossier utilisateur sans avoir à connaître son nom d'utilisateur.
Nous pouvions donc désormais écrire des fichiers n'importe où sur le système de fichiers. Le moyen le plus simple d'escalader cela en une exécution de code à distance différée est d'écrire un exécutable dans C:\Users\<user>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup. Chaque fois que votre appareil démarre, il exécute automatiquement tous les fichiers de ce dossier.
Nous avons donc fourni cette valeur comme nom d'enregistrement :
..\..\..\..\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\poc.exeEt lorsque nous avons empaqueté et exécuté notre carte, nous avons remarqué...

Ça a marché, en quelque sorte ? Nous avons effectivement écrit un fichier dans le dossier de démarrage. Mais notre extension .exe n'a pas été conservée. Unreal Engine ajoute l'extension .wav à n'importe quel nom de fichier que nous fournissons, et par conséquent, Windows traite toujours le fichier comme un fichier WAV et non comme un exécutable.
Suppression du suffixe .wav
Je me suis demandé comment nous pouvions contourner ce problème. Nous sommes ici face à un cas classique d'hypothèses divergentes entre deux systèmes. Unreal Engine gère les chemins d'accès à sa manière, tandis que Windows les interprète différemment. Il me suffisait de trouver une divergence entre les deux.
Pour Unreal Engine, c'est on ne peut plus simple : il lit une chaîne de caractères et y ajoute .wav à la suite. Windows se montre un peu plus complexe. Il impose des limites de longueur de nom de fichier ainsi que des caractères interdits dans les chemins, comme le caractère nul (U+0000).
Mais que se passe-t-il lorsque l'on tente de créer un fichier dont le nom contient un caractère nul ? La plupart du temps, on obtient une erreur :

Cependant, toutes les API ne déclenchent pas d'erreur. Certaines API de plus bas niveau considèrent les octets nuls comme un caractère de fin et ignorent tout ce qui suit :

Et si nous essayions d'utiliser notre map malveillante pour enregistrer un fichier audio à l'emplacement suivant :
POC.exe\u0000IGNORED
On constate que cela fonctionne ! Il est désormais possible d'enregistrer des fichiers avec des noms arbitraires à des emplacements arbitraires sur le système de fichiers !
Un problème de taille subsiste toutefois. Nous écrivons simplement les octets d'un enregistrement audio WAV dans un fichier doté d'une extension .exe Il nous faut également réussir à contrôler le contenu de ce fichier pour le rendre exécutable !

Des octets malveillants dans un enregistrement audio
Un nouveau défi s'offrait alors à nous. Nous enregistrions un véritable flux audio au format WAV vers un emplacement arbitraire. Mais pour que cette exploitation réussisse, nous devions également être en mesure de contrôler les données écrites dans ce fichier.
Pour y parvenir, nous allons utiliser un fichier WAV PCM non compressé. Le format WAV fait office de conteneur, abritant des métadonnées suivies des données audio. Les fichiers WAV peuvent stocker l'audio selon différents formats, de sorte que l'extension .wav à elle seule ne suffit pas à déterminer comment les échantillons sont encodés.
PCM signifie Pulse-Code Modulation (modulation par impulsion et codage). Avec le PCM, chaque mesure de l'onde sonore est enregistrée directement sous forme de nombre. Notre preuve de concept utilisait du PCM 16 bits, ce qui signifie que chaque échantillon occupait exactement deux octets. Le terme « non compressé » indique que ces valeurs numériques ont été écrites sans passer par un codec tel que le MP3.
Un fichier WAV PCM non compressé se compose de valeurs d'échantillons audio. Si nous maîtrisons ces valeurs avec précision, nous contrôlons par conséquent les octets utilisés pour les stocker.
C'est un point capital, car la compression audio classique s'efforce de préserver la perception du son et non les octets exacts de chaque échantillon. Une version compressée peut donc sembler identique tout en contenant des octets très différents.
Voici la structure simplifiée d'un fichier WAV :
+-------------------------------+
| En-tête RIFF/WAVE | Créé par Unreal
| Format, canaux, taux d'échantillonnage |
| Taille de la section de données |
+-------------------------------+
| Échantillon PCM 0 | Contrôlé via l'onde sonore
| Échantillon PCM 1 |
| Échantillon PCM 2 |
| ... |
Unreal contrôle l'en-tête, y compris RIFF et WAVE identifiants. Nous ne pouvons pas les modifier car notre contrôle sur le fichier ne commence qu'à la section des données PCM. Cela élimine un grand nombre d'exécutables pour notre exploit. Nous ne pouvons pas télécharger un fichier normal .exe ou .dll, étant donné que tous deux nécessitent un en-tête PE valide pour s'exécuter.
Nous avions donc besoin d'un type de fichier dont l'analyseur ne cherchait pas impérativement son en-tête au premier octet. Les applications HTML Windows se sont avérées idéales.
Un Application HTML est un ancien format Windows doté de l'extension .hta . Le fichier ressemble beaucoup à une page web : il peut contenir du HTML, du CSS et du JScript ou du VBScript. Windows l'ouvre avec mshta.exe (Microsoft HTML Application Host).
La différence majeure par rapport à une page web classique réside dans l'emplacement d'exécution de ce script. Un fichier HTA est traité comme une application de bureau plutôt que comme une page confinée dans le bac à sable du navigateur. Son script peut créer des objets COM Windows, notamment WScript.Shell, qui peut démarrer un autre processus.
Une version simplifiée de notre charge utile de preuve de concept ressemble à ceci :
[RIFF/WAVE header ...]
<html>
<head>
<hta:application />
<script>
new ActiveXObject("WScript.Shell").Run("calc.exe");
</script>
</head>
</html>
Lorsque ce fichier est ouvert, mshta.exe ignore les métadonnées WAV au début et exécute le script. Ensuite, WScript.Shell lance la Calculatrice.
Le défi restant consistait à placer ce code HTML et ce script dans les échantillons PCM du fichier WAV.
Our payload used 16-bit PCM. Each sample is a 16-bit number stored in little-endian order, meaning the least significant byte is written first. Take the sample value 0x683C: it appears in the WAV as 3C 68, which also happens to be the ASCII text <h.
The same conversion works for a longer string. The text <html> has these ASCII bytes:
3C 68 74 6D 6C 3EEn les regroupant par paires, nous obtenons trois valeurs d'échantillons de 16 bits :
Bytes: 3C 68 | 74 6D | 6C 3E
Samples: 0x683C 0x6D74 0x3E6C
Lorsque ces échantillons sont réécrits dans un fichier WAV au format little-endian, les octets d'origine réapparaissent. En réalité, il a fallu de nombreux ajustements pour que cela fonctionne, mais nous avons fini par réussir à créer un véritable fichier WAV contenant notre hta charge utile.

Assemblage de la carte
À ce stade, chaque élément fonctionnait de manière autonome. La dernière étape consistait à tout regrouper dans une carte capable d'exécuter l'attaque complète en une seule fois au chargement du niveau.
Nous nous connectons donc à BeginPlay et effectuons les opérations suivantes :
StartRecordingOutputsur un sous-mixage privé (pour éviter les interférences avec l'audio habituel du jeu)PlaySound2Davec notre fichier PCM non compressé préparéStopRecordingOutputen utilisant../../../../Roaming/Microsoft/Windows/Menu Démarrer/Programmes/Démarrage/poc.exe\u0000IGNORÉcomme nom de fichier

Nous avons créé la carte et l'avons mise en ligne (en privé !) sur Steam.

Et c'est ainsi que nous en sommes arrivés à cette vidéo de démonstration :
Alors, est-ce que MECCHA CHAMELEON est désormais sécurisé ?
La vulnérabilité que nous avons signalée a été corrigée et ne peut plus être exploitée. La StopRecordingOutput Cette fonction ne crée plus aucun fichier (même ceux qui sont prévus).
Nous avons également passé en revue toutes les cartes du Steam Workshop pour vérifier si certaines exploitaient déjà cette faille, mais nous n'en avons trouvé aucune.
Toutefois, alors que nous travaillions sur cette démonstration de faisabilité (PoC), plusieurs personnes nous ont contactés pour nous signaler l'existence éventuelle d'autres vulnérabilités dans MECCHA CHAMELEON. Elles n'ont pas fourni de détails et ces informations n'ont pas été vérifiées ni confirmées par nos soins.
Nous vous invitons donc à faire preuve de prudence et de vigilance lorsque vous jouez à ce jeu en utilisant des cartes personnalisées. Nous vous recommandons de ne jouer que sur les cartes officielles fournies par MECCHA CHAMELEON.
Chronologie de la divulgation
- 11 août 2026 : J'ai essayé de prendre contact via Twitter
- 12 août 2026 : J'ai essayé de prendre contact via Discord
- 13 août 2026 : J'ai tenté de contacter le service client de Steam et l'adresse e-mail du développeur.
- 17 août 2026 : J'ai réussi à les contacter à nouveau via Twitter. Le développeur m'a répondu qu'il allait corriger le problème.
- 20 août 2026 : MECCHA CHAMELEON 4.0.0 a été publié avec un correctif pour cette vulnérabilité