✅ Day 03 - Santa's Magic Sack
- WEB HACKING GAME
- Date de résolution : 03/12/2024
Reconnaissance
Le chall commence par un jeu consistant à récupérer des cadeaux dans une hotte qui est bougé par l'utilisateur grâce aux flêches du clavier.
L'objectif est d'entrer dans le top 1 du scoreboard...
En particulier, on remarque l'appel à une API qui semble prometteuse :
1POST https://day3.challenges.xmas.root-me.org/api/scores
2{data:U2FsdGVkX1+aXbnHtRPR5L3Hu74Dl1T4EUBMetXr+eaZLuwjtzfAMUJE/YwqxnNxr2BLiPjB31e5IG4JjkoralCSX3i6fUvHYUqEWpzh1qqqeGEqb9n9EEbR7CAAF2BB8Oo3+bgO1aPORFdyzLf0qI1azYK3grvSCsCl34JDxlOL6BZtH9WcpNiQhVuMhR5X}
Exploit
Le décodage base64 de cette valeur data montre une chaine de bytes débutant par : Salted__ ce qui fait penser à un chiffrement symétrique.
Plongeons nous maintenant dans le code Javascript en cherchant des informations sur le chiffrement utilisé.
1var Md = hf.exports;
2const gf = Rf(Md)
3 , Ud = "S4NT4_S3CR3T_K3Y_T0_ENCRYPT_DATA";
4function Wd(e) {
5 const t = JSON.stringify(e);
6 return gf.AES.encrypt(t, Ud).toString()
7}
8function $d(e, t) {
9 const r = Math.floor(Math.random() * 9) + 1
10 , n = `${e}-${t}-${r}`;
11 return {
12 checksum: gf.SHA256(n).toString(),
13 salt: r
14 }
15}
16async function Vd(e, t) {
17 const {checksum: r, salt: n} = $d(e, t)
18 , l = Wd({
19 playerName: e,
20 score: t,
21 checksum: r,
22 salt: n
23 });
24 try {
25 return await (await fetch("/api/scores", {
26 method: "POST",
27 headers: {
28 "Content-Type": "application/json"
29 },
30 body: JSON.stringify({
31 data: l
32 })
33 })).json()
34 } catch (i) {
35 return console.error("Error submitting score:", i),
36 {
37 success: !1
38 }
39 }
40}
41async function Qd() {
42 try {
43 return await (await fetch("/api/scores")).json()
44 } catch (e) {
45 return console.error("Error fetching scores:", e),
46 []
47 }
48}
On trouve les informations suivantes :
- Le chiffrement est AES avec la clé en clair : S4NT4_S3CR3T_K3Y_T0_ENCRYPT_DATA
- La composition du token avant chiffrement est : {playername, score, checksum, salt}
- Le calcul d'un checksum ne permet pas de modifier la valeur score uniquement...
A ce stade, je n'ai pas retenu l'idée de continuer le reverse engineering mais plutôt de modifier l'execution du programme grâce au debugger chrome.
Voici le mode opératoire réalisé :
- Placer un breakpoint ligne 73, colonne 34975 (juste avant l'appel à l'API)
- Dans la console, on execute la fonction
Vd("totoiste", score: 100000000000000000) - On va chercher le flag dans le résultat de la requête API POST ...
The flag is : RM{S4NT4_H0PE_Y0U_D1DN'T_CHEAT}