# Démonstration : injection SQL avec Node.js, Express et SQLite Ce projet démontre comment une simple concaténation SQL peut rendre une application vulnérable à une injection SQL, et comment corriger cette faille à l'aide de requêtes préparées. Il propose **deux routes** : * `/demo-vulnerable/login` → version vulnérable * `/demo-secure/login` → version sécurisée --- ## Installation ```bash npm install nodemon ./bin/www ``` L'application démarre sur : ``` http://localhost:3000 ``` --- ## Objectifs pédagogiques Cette mini-démonstration permet de : * comprendre ce qu'est une **injection SQL** * observer clairement la différence entre : * une requête créée par concaténation (dangereux) * une requête préparée avec paramètres (sécurisé) * manipuler Express, SQLite et les routes API * visualiser l'impact d'une exploitation sur une base de données --- ## Structure du projet ```text project/ │── app.js │── db/ │ └── database.js │── routes/ │ ├── auth_vulnerable.js │ └── auth_secure.js └── bin/www ``` --- # Comprendre l'architecture ## 1. Initialisation de la base en mémoire ```javascript const db = new sqlite3.Database(':memory:'); ``` La base est volatile, recréée à chaque démarrage, et contient deux utilisateurs : * admin / password123 * user / userpass ### Diagramme — création de la base ```mermaid flowchart TD a["demarrage de l'application"] --> b["creation de la base en memoire"] b --> c["creation de la table users"] c --> d["insertion de l'utilisateur admin"] c --> e["insertion de l'utilisateur user"] ``` --- ## 2. Version vulnérable : concaténation SQL Dans `auth_vulnerable.js` : ```javascript const sqlQuery = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'"; ``` Cette méthode permet à un utilisateur d'injecter du code SQL. ### Diagramme — route vulnérable ```mermaid sequenceDiagram participant client participant serveur participant sqlite client->>serveur: envoi de donnees username et password serveur->>serveur: creation d'une requete concatenee serveur->>sqlite: execution de la requete non protegee sqlite-->>serveur: renvoi d'une ligne ou non serveur-->>client: reponse json ``` --- # Tests de démonstration ## Test 1 : attaque réussie (vulnérable) Envoyer un POST : ``` POST http://localhost:3000/demo-vulnerable/login ``` Body JSON : ```json { "username": "' OR 1=1 --", "password": "peu-importe" } ``` **Résultat attendu :** Connexion acceptée, vous devenez admin même sans connaître le mot de passe. --- ## Test 2 : l'attaque échoue (sécurisé) Même requête mais vers : ``` POST http://localhost:3000/demo-secure/login ``` Body identique : ```json { "username": "' OR 1=1 --", "password": "peu-importe" } ``` **Résultat attendu :** Connexion refusée : l'injection est traitée comme du texte. --- # 3. Version sécurisée : requêtes préparées Dans `auth_secure.js` : ```javascript const sqlQuery = "SELECT * FROM users WHERE username = ? AND password = ?"; const params = [username, password]; db.get(sqlQuery, params, (...)); ``` SQLite protège automatiquement les valeurs et empêche l'injection. ### Diagramme — route sécurisée ```mermaid flowchart TD a["reception de la requete http"] --> b["construction de la requete preparee"] b --> c["envoi de la requete avec parametres"] c --> d["sqlite assainit les valeurs"] d --> e["execution de la requete securisee"] ``` --- # Comprendre la faille SQL ### Exemple vulnérable Requête générée : ```sql SELECT * FROM users WHERE username = '' OR 1=1 --' AND password='peu-importe' ``` `OR 1=1` rend la condition **toujours vraie**. --- # Bonnes pratiques * toujours utiliser des requêtes préparées * jamais concaténer des valeurs utilisateur dans du SQL * toujours valider / nettoyer les entrées * activer des logs SQL en développement * éviter les messages d'erreurs trop détaillés en production ---