En-tête négligent

L'illusion du filtre : Armer et défendre le mécanisme de filtrage JavaScript

Dans l'architecture immaculée du développement web moderne, l'élément filtre javascript fonction (Array.prototype.filter()) est considéré comme la pierre angulaire de la programmation fonctionnelle. Il permet aux développeurs d'écrire un code déclaratif et propre pour manipuler des ensembles de données.

Cependant, pour l'ingénieur en sécurité hostile, le concept de "filtre" en JavaScript représente une dichotomie dangereuse. D'un côté, c'est la cause première de la généralisation des Contrôle d'accès côté client vulnérabilités. D'autre part, la flexibilité du langage JavaScript lui-même transforme les méthodes de filtrage en de puissantes méthodes de filtrage. gadgets pour contourner les pare-feu d'applications Web (WAF) et les dispositifs d'assainissement des entrées.

Ce guide va au-delà de la syntaxe. Nous disséquerons les défaillances architecturales du filtrage côté client, nous analyserons comment les attaquants utilisent les méthodes de la bibliothèque standard pour exécuter du code, et nous explorerons comment les plateformes basées sur l'IA comme Penligent automatisent la découverte de ces subtiles failles logiques.

La faille architecturale : le filtre Javascript côté client

La vulnérabilité la plus répandue associée à la filtre javascript n'est pas un bug dans le langage, mais un bug dans l'implémentation des modèles de sécurité. À l'ère des applications à page unique (SPA) et des clients lourds (React, Vue, Angular), les développeurs confondent souvent présentation avec sécurité.

Le modèle de la "sécurité par l'obscurité

Considérons un scénario standard : Un point de terminaison de l'API renvoie une liste d'utilisateurs. Le développeur du frontend doit afficher uniquement les utilisateurs actifs et masquer les administrateurs.

JavaScript

// LE MODÈLE VULNÉRABLE
fetch('/api/v1/users')
  .then(response => response.json())
  .then(data => {
    // Le développeur utilise un filtre javascript pour "sécuriser" la vue
    const visibleUsers = data.filter(user => user.role !== 'admin' && user.status === 'active') ;
    renderTable(visibleUsers) ;
  }) ;

Pour un scanner DAST générique, cette application semble sûre. L'interface utilisateur n'affiche pas de données administratives. Cependant, un ingénieur en sécurité utilisant Burp Suite ou de simples DevTools connaît la vérité.

Le vecteur d'attaque : IDOR et fuite d'informations personnelles

Les filtre javascript s'exécute dans le navigateur de l'utilisateur, qui est un environnement non fiable. La vulnérabilité réside dans le fait que le ensemble de données complet a été transmise par fil.

Étapes de l'exploitation :

  1. Interception : L'auteur de l'attaque se charge de l'acheminement du trafic par l'intermédiaire d'un proxy.
  2. Inspecter : La réponse JSON brute contient des objets tels que {"id" : 42, "role" : "admin", "pii_ssn" : "xxx-xx-xxxx" }.
  3. Bypass : L'attaquant ignore totalement la logique de l'interface utilisateur.

Il s'agit d'un échec de Minimisation des données. Une implémentation correcte effectue le filtrage au niveau de la requête de la base de données (SQL ), ce qui garantit que les octets sensibles ne quittent jamais le centre de données.

Armement de la syntaxe : Le filtre Javascript comme gadget XSS

Lorsque nous nous intéressons au Cross-Site Scripting (XSS), le terme filtre javascript prend un nouveau sens : les filtres défensifs (WAFs/Sanitizers) qui tentent de bloquer les codes malveillants.

Les attaquants recherchent constamment des "gadgets", c'est-à-dire des méthodes standard disponibles dans le moteur d'exécution JavaScript qui peuvent être utilisées de manière abusive pour exécuter un code arbitraire sans utiliser de mots-clés figurant sur la liste de blocage tels que eval(), Fonction()ou <script>.

Le contournement du chaînage des constructeurs

Les WAFs recherchent souvent des puits évidents. Mais JavaScript est dynamique. Les Array.prototype.filter est une fonction, et chaque fonction en JavaScript a un constructeur. Le constructeur d'une fonction est la fonction Fonction qui agit de la même manière que l'objet eval().

Si un WAF bloque eval() mais autorise les méthodes de type tableau, un attaquant peut construire une charge utile à l'aide de la méthode filtre elle-même.

La logique de contournement :

  1. [] crée un tableau.
  2. [].filtre permet d'accéder à la fonction de filtrage.
  3. [].filter.constructor accède à la base de données globale Fonction constructeur.
  4. Fonction('code')() exécute le code.

La charge utile :

JavaScript

// Charge utile standard (bloquée par le WAF)
eval('alert(1)')

// Evasion à l'aide d'un filtre javascript gadget
[].filter.constructor('alert(1)')()

L'illusion du filtre : Armer et défendre le mécanisme de filtrage JavaScript

Tableau : Techniques courantes d'évasion du filtre Javascript

TechniqueStructure de la charge utileMécanismeContexte de sécurité
Chaînage de constructeurs[].filter.constructor('code')()Utilise la chaîne de prototypes pour atteindre le Fonction constructeur.Contourner les filtres de mots-clés sur eval.
Abus d'itérateur[].map.constructor('code')()Similaire au filtre ; fonctionne avec n'importe quelle méthode de prototype Array.Redondance si filtre fait l'objet d'une surveillance particulière.
Obfuscation des chaînes de caractères[].filter['c'+'onstructor']Décompose le mot-clé "constructeur" en chaînes de caractères concaténées.Contourne les règles WAF basées sur des expressions rationnelles.
Codage Unicode\u0061lert(1)Utilise les échappements unicode pour les noms de fonctions.Les analyseurs JavaScript décodent cette information, ce qui n'est pas le cas des filtres simples.

Quand les filtres échouent : Pollution des prototypes (CVE-2019-10744)

Le concept de "filtrage" est essentiel lors de la fusion d'objets. Si une application accepte des données JSON et les fusionne avec un objet existant sans respecter strictement la règle du filtrage les clés, il ouvre la porte à la pollution par les prototypes.

L'un des exemples les plus marquants de cette démarche est le suivant CVE-2019-10744 dans l'ouvrage largement utilisé lodash bibliothèque.

L'anatomie de la vulnérabilité

La fonction defaultsDeep a été conçu pour fusionner des objets de manière récursive. Cependant, il n'a pas réussi à mettre en place un filtre de sécurité pour rejeter la clé constructeur.

L'exploitation :

Un attaquant fournit une charge utile JSON qui contient une propriété de constructeur pointant vers un prototype.

JavaScript

const payload = '{"constructor" : {"prototype" : {"isAdmin" : true}}}' ;
_.defaultsDeep({}, JSON.parse(payload)) ;

L'impact :

L'entrée n'étant pas filtrée, l'affectation a pollué la base Object.prototype. Soudain, tous les objets de l'exécution JavaScript ont hérité de la propriété isAdmin : true.

Si l'application avait une logique d'authentification comme :

JavaScript

if (user.isAdmin) { grantAccess() ; }

L'attaquant obtient instantanément un accès administratif, créant un déni de service ou un RCE selon le contexte Node.js.

Remédiation : Un solide filtre javascript pour les clés d'objets, doit figurer sur la liste de blocage __proto__, constructeuret prototype.

Découverte logique automatisée : L'approche négligente

Les vulnérabilités décrites ci-dessus - filtrage côté client et pollution par prototype - sont notoirement difficiles à détecter avec les outils DAST (Dynamic Application Security Testing) traditionnels.

  • Scanners traditionnels : Vérifiez les plantages, les codes d'erreur (500) ou les simples chaînes XSS reflétées. Ils ne comprennent pas que utilisateurs.filtre() cache des données sensibles.
  • Le fossé de l'IA : Pour trouver ces problèmes, vous avez besoin d'un moteur qui comprend sémantique du code et flux de données.

C'est ici que Penligent.ai modifie fondamentalement le flux de travail de l'ingénieur en sécurité.

Fuzzing sémantique et analyse logique

Penligent utilise des agents d'intelligence artificielle avancés qui vont au-delà du filtrage. Lors de l'analyse d'une application cible, le moteur de Penligent effectue les opérations suivantes Analyse contextuelle:

  1. Inspection du flux de données : Penligent surveille les réponses de l'API par rapport au rendu du DOM. Si l'API renvoie 50 champs mais que le DOM n'en restitue que 5, l'IA en déduit qu'il s'agit d'une erreur potentielle. filtre javascript et la signale comme un risque de fuite de données.
  2. La génération des gadgets : Au lieu d'utiliser une liste statique de charges utiles XSS, Penligent génère des charges utiles de manière dynamique en fonction des objets disponibles dans l'environnement. S'il détecte que Array.prototype.filter est disponible mais eval est bloqué, il construit le [].filter.constructor la charge utile de la dérivation.
  3. Prototype Fuzzing : L'IA analyse intelligemment les points d'extrémité JSON avec des vecteurs de pollution prototypiques, en surveillant l'état de l'application pour détecter les héritages de propriétés inattendus, en identifiant les failles de style CVE-2019-10744, même dans le code personnalisé.

En automatisant l'"intuition du hacker", Penligent permet aux équipes de sécurité d'identifier des failles logiques profondes qui nécessitent habituellement un examen manuel du code.

Défense en profondeur : durcissement de l'exécution

Se défendre contre les armes filtre javascript Pour éviter les gadgets et les failles logiques, nous devons adopter une stratégie de défense à plusieurs niveaux.

1. La règle d'or : Validation côté serveur

Ne vous fiez jamais à la logique côté client pour assurer la sécurité. Le filtrage doit se faire au niveau de la base de données.

  • Audit : Vérifiez tous les points de terminaison de l'API. Assurez-vous qu'ils ne renvoient que les données que l'utilisateur est autorisé à voir. dès maintenant.
  • DTO : Utilisez les objets de transfert de données sur le backend pour supprimer les champs sensibles avant la sérialisation.

2. Prototypes immuables

Pour éliminer une classe entière de vulnérabilités de type Prototype Pollution, figez les prototypes d'objets standard au démarrage de l'application.

JavaScript

// Défense contre la pollution par les prototypes
Object.freeze(Object.prototype) ;
Object.freeze(Array.prototype) ;

Cela permet de s'assurer que même si un filtre javascript ne parvient pas à bloquer une clé malveillante, le système d'exécution envoie une erreur au lieu d'autoriser la modification.

3. Politique de sécurité du contenu (PSC)

La CSP est l'ultime filet de sécurité. Pour éviter que la [].filter.constructor vous devez désactiver l'exécution des chaînes de caractères en tant que code.

En-tête recommandé :

Content-Security-Policy : default-src 'self' ; script-src 'self' ; object-src 'none' ;

C'est un point essentiel, éviter ajoutant 'unsafe-eval' (évaluation non sécurisée). Sans 'unsafe-eval' (évaluation non sécurisée)le navigateur refusera d'exécuter le code généré par l'application Fonction ce qui rend le gadget de filtrage inutile.

4. Assainissement des entrées avec DOMPurify

N'écrivez pas vos propres filtres regex. Ils sont facilement contournés. Utilisez DOMPurify pour assainir les entrées HTML. Il crée un bac à sable, analyse le HTML et supprime les balises/attributs malveillants sur la base d'une liste d'autorisation stricte, neutralisant ainsi les XSS avant qu'ils n'atteignent le DOM.

Conclusion

Le terme filtre javascript est trompeur. Pour un développeur débutant, il s'agit d'un utilitaire. Pour un ingénieur en sécurité chevronné, c'est un signal - un signal pour vérifier les fuites de données, un gadget pour l'évasion XSS et un point de contrôle critique pour la validation des entrées.

Les applications modernes devenant de plus en plus complexes, il n'est plus possible de s'appuyer sur des tests manuels pour détecter ces subtiles failles logiques. En s'appuyant sur une compréhension approfondie de l'architecture combinée à une automatisation pilotée par l'IA à partir de plateformes telles que Penligent est le seul moyen de garder une longueur d'avance.

Des ressources fiables

Partager l'article :
Articles connexes