Trouver le point d'injection SQL : repérer le SQL construit par concaténation en Node.js

Sécurité Web & API Niveau 2/4 ~3 min 9 juillet 2026

Le défi

Cette route Node construit une requête SQL en collant l'entrée utilisateur directement dans la chaîne. Un appel exécute ce SQL non filtré contre la base de données. Lisez les deux fichiers et tapez le nom de cet appel.

Ce que tu vas apprendre

  • Reconnaître le SQL construit par concaténation de l'entrée utilisateur comme point d'injection SQL
  • Suivre un paramètre de requête depuis son point d'entrée jusqu'à l'appel qui l'exécute
  • Distinguer une requête concaténée (db.query) d'une requête paramétrée (db.execute avec des placeholders)
  • Lire deux routes similaires et identifier celle qui est exploitable
  • Expliquer pourquoi les paramètres liés empêchent l'injection

Compétences testées

Revue de code sourceReconnaissance d'injection SQLSuivi du flux de données

Prérequis

  • Lecture de base en JavaScript
  • Connaissance des paramètres de requête HTTP
  • Connaître la structure d'une requête SQL SELECT

Comment ça marche

L'injection SQL se produit lorsqu'une entrée non fiable est mélangée au texte d'une instruction SQL au lieu d'être envoyée comme donnée. L'analyseur de la base de données ne peut pas distinguer quelle partie de la chaîne était censée être une valeur et quelle partie est une commande, si bien qu'un attaquant qui contrôle la valeur peut modifier le sens de toute la requête.

Dans users.js, la route lit req.query.id et construit l'instruction avec "SELECT ... WHERE id=" + id, puis l'exécute avec db.query(sql). Un ?id=42 anodin fonctionne bien, c'est pour cela que le bug passe inaperçu. Mais ?id=0 OR 1=1 rend la clause WHERE toujours vraie et extrait tous les utilisateurs, et un payload UNION SELECT peut lire d'autres tables, voire des identifiants. La valeur n'est jamais échappée, elle est donc interprétée comme du SQL.

La correction se trouve dans orders.js. Elle utilise un placeholder ? et passe la valeur dans un tableau séparé : db.execute(sql, [req.query.user]). Le pilote lie la valeur en tant que paramètre typé, elle ne peut donc jamais s'échapper de son emplacement pour devenir du SQL. Repérer le bug en revue de code consiste à suivre la valeur utilisateur et à remarquer qu'elle se retrouve dans la chaîne de la requête plutôt que dans la liste des paramètres.

Erreurs fréquentes

  • Accuser req.query.id. Lire l'entrée n'est pas un problème ; la vulnérabilité consiste à la concaténer dans le SQL et à l'exécuter. Nommez l'appel qui exécute la requête.
  • Choisir db.execute. C'est la route sûre et paramétrée : elle lie les valeurs, ce n'est donc pas le point d'injection.
  • Supposer qu'un id entier est sûr. Rien ne valide que id est numérique ; c'est une chaîne brute provenant de l'URL.
  • Penser qu'un ORM ou un framework échappe automatiquement cela. La concaténation brute contourne toute protection offerte par le pilote.

Comment s'en protéger

Ne construisez jamais de SQL en concaténant l'entrée utilisateur. Passez toujours les valeurs comme paramètres liés afin que la base de données les traite comme des données, et non comme du code.

  • Utilisez des requêtes paramétrées ou des instructions préparées (db.execute(sql, [value])) pour chaque valeur fournie par l'utilisateur.
  • Validez et convertissez le type des entrées (par exemple, forcez un id en nombre) avant qu'elles n'atteignent la couche de données.
  • Appliquez le principe du moindre privilège aux comptes de base de données afin qu'une requête injectée ne puisse pas lire des tables non liées.
  • Ajoutez une règle de lint ou de revue de code qui signale la concaténation de chaînes à côté de db.query.

Solution complète

Les membres Pro et Max débloquent la solution complète étape par étape.

Passer Pro

Statistiques de la communauté

81 résolutions
70% taux de réussite
kevine Premier sang

Hacks du jour associés

25 000+ Hackers 100+ Labs & Cours Gratuit
Commencer Gratuitement