Files
ENI-JSAdvanced_07/README.md
2025-12-18 15:17:27 +01:00

204 lines
4.0 KiB
Markdown

# 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
---