Obfuscation JavaScript : escape et unescape
Certains sites tentent de dissimuler du code JavaScript sensible en remplaçant ses caractères par des séquences d’échappement via la fonction escape(). Cette méthode, obsolète depuis ES5, ne constitue pas une protection : un appel à unescape() restitue le code original en clair.
Le problème
Section titled “Le problème”escape() encode une chaîne en remplaçant les caractères par leur représentation hexadécimale ou unicode :
escape("if (password == 'secret') { login(); }")// → "if%20%28password%20%3D%3D%20%27secret%27%29%20%7B%20login%28%29%3B%20%7D"Le code livré dans la page ressemble alors à une suite de caractères encodés, ce qui donne l’illusion d’une protection.
Dans la pratique, la page doit bien exécuter ce code, donc elle appelle elle-même unescape() ou eval() pour le décoder au moment de l’exécution. Le code décodé transite dans le navigateur — il est accessible.
Exploitation
Section titled “Exploitation”Décoder depuis la console
Section titled “Décoder depuis la console”Copier la chaîne encodée trouvée dans le source de la page et l’exécuter dans la console DevTools :
unescape("if%20%28password%20%3D%3D%20%27secret%27%29%20%7B%20login%28%29%3B%20%7D")// → "if (password == 'secret') { login(); }"Intercepter l’évaluation
Section titled “Intercepter l’évaluation”Si le code obfusqué est passé à eval(), surcharger eval avant le chargement de la page pour lire ce qui lui est transmis :
const _eval = eval;window.eval = function(code) { console.log("eval intercepté :", code); return _eval(code);};Recharger la page : le code décodé s’affiche dans la console avant son exécution.
Via l’onglet Debugger
Section titled “Via l’onglet Debugger”Dans les DevTools, onglet Sources → poser un point d’arrêt sur la ligne contenant eval() ou unescape(). À l’exécution, inspecter la variable qui reçoit le résultat : le code original est lisible dans le panneau Scope.
Ce que ça révèle
Section titled “Ce que ça révèle”Ce schéma indique que le développeur a tenté de cacher quelque chose de précis dans ce bloc : des credentials, une logique d’autorisation, une clé API, ou une URL interne. Le code obfusqué mérite une lecture attentive une fois décodé.
Les patterns à chercher après décodage :
// Credentials en durif (user == "admin" && pass == "p@ssw0rd") { ... }
// Clé APIvar apiKey = "sk-live-abc123...";
// URL internefetch("https://internal.api.exemple.com/admin/users")
// Logique de contournementif (isPremium === true) { unlockContent(); }Pourquoi cette méthode est obsolète
Section titled “Pourquoi cette méthode est obsolète”escape() et unescape() sont dépréciées depuis ECMAScript 5 (2009). La MDN les classe comme fonctionnalités à ne pas utiliser en production — non pour des raisons de sécurité, mais parce qu’elles gèrent mal les caractères Unicode au-delà de U+00FF.
Leur usage comme mécanisme d’obfuscation repose sur l’hypothèse qu’un attaquant ne connaît pas unescape() — ce qui n’est pas une hypothèse valide.
D’autres méthodes d’obfuscation plus élaborées existent (substitution de variables, encodage en base64 imbriqué, packers comme p,a,c,k,e,d), mais elles restent toutes décodables : le navigateur doit pouvoir exécuter le code, donc le décoder.
Remédiation
Section titled “Remédiation”L’obfuscation ne remplace pas la sécurité. Les éléments sensibles — credentials, clés, logique d’autorisation — n’ont pas leur place dans le JavaScript livré au client, obfusqué ou non.
- Déplacer la logique sensible côté serveur : un endpoint API authentifié, pas une condition JavaScript
- Ne jamais stocker de secrets dans le code front-end : utiliser des variables d’environnement injectées au build, ou mieux, des appels authentifiés vers un backend
- Si une obfuscation est nécessaire pour des raisons de propriété intellectuelle, utiliser des outils reconnus (
terser,javascript-obfuscator) en sachant qu’ils ralentissent la lecture sans empêcher le décodage
À retenir
Section titled “À retenir”Tout ce que le navigateur peut décoder pour l’exécuter, un attaquant peut le décoder pour le lire. L’obfuscation via escape() ajoute trente secondes de travail à quelqu’un qui sait ce qu’il fait.