Aller au contenu principal

Sécurisation des BD

Protection des données stockées contre les accès non autorisés et les fuites d'information

Notions théoriques

Les bases de données contiennent des informations sensibles qu'il est essentiel de protéger contre les attaques et les accès non autorisés.

Plusieurs techniques permettent d'améliorer la sécurité des bases de données.

Chiffrement des données

Le chiffrement permet de rendre les données illisibles sans la clé de déchiffrement. Il existe deux types de chiffrement couramment utilisés :

  • Chiffrement au niveau des colonnes : Seules certaines colonnes contenant des données sensibles sont chiffrées (exemple : numéros de carte bancaire).
  • Chiffrement au niveau du disque ou du fichier : L'ensemble de la base de données est chiffré pour empêcher la lecture des fichiers de stockage.

Les algorithmes les plus utilisés sont AES (Advanced Encryption Standard) et RSA (Rivest-Shamir-Adleman).

Hashage des mots de passe

Les mots de passe ne doivent jamais être stockés en clair. Le hashage permet de transformer un mot de passe en une empreinte unique et irréversible.

  • Algorithmes de hashage courants : bcrypt, Argon2, SHA-256.
  • Ajout d'un sel : Un sel est une valeur aléatoire ajoutée au mot de passe avant le hashage pour éviter les attaques par dictionnaire.

Contrôle des accès et authentification

Limiter l'accès aux bases de données est essentiel :

  • Utilisation de rôles et permissions : Chaque utilisateur doit avoir uniquement les droits nécessaires.
  • Authentification forte : Utilisation de méthodes comme l'authentification multi-facteurs (MFA).
  • Sécurisation des connexions : Utilisation de TLS/SSL pour chiffrer les communications entre l'application et la base de données.

Prévention des injections SQL

Les injections SQL permettent à un attaquant d'exécuter des commandes malveillantes sur la base de données.

  • Utilisation de requêtes préparées : Empêche l'injection de code SQL en séparant les données des commandes SQL.
  • Validation des entrées utilisateur : Vérification stricte des données saisies avant de les utiliser dans une requête.

Exemple pratique

Il est possible de sécuriser une base de données MySQL en appliquant plusieurs mesures de protection.

1) Chiffrement des colonnes sensibles

  1. Se connecter à MySQL :
mysql -u root -p
  1. Créer une table avec une colonne chiffrée :
CREATE TABLE utilisateurs (
id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) NOT NULL,
mot_de_passe VARBINARY(255) NOT NULL
);
  1. Insérer un mot de passe chiffré avec AES :
INSERT INTO utilisateurs (email, mot_de_passe)
VALUES ('user@example.com', AES_ENCRYPT('monMotDePasse', 'cleSecrete'));
  1. Vérifier que le mot de passe est stocké sous forme chiffrée :
SELECT * FROM utilisateurs;

2) Hashage des mots de passe avec bcrypt en PHP

  1. Installer la bibliothèque password_hash en PHP :
$motDePasse = "monMotDePasse";
$hash = password_hash($motDePasse, PASSWORD_BCRYPT);
echo $hash;
  1. Vérifier un mot de passe saisi par un utilisateur :
if (password_verify("monMotDePasse", $hash)) {
echo "Mot de passe correct";
} else {
echo "Mot de passe incorrect";
}

3) Protection contre les injections SQL avec des requêtes préparées

  1. Exemple d'injection SQL dangereuse :
SELECT * FROM utilisateurs WHERE email = 'admin@example.com' OR '1'='1';
  1. Utilisation d'une requête préparée en PHP pour éviter l'injection :
$stmt = $pdo->prepare("SELECT * FROM utilisateurs WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();

Test de mémorisation/compréhension


Quel est l'objectif principal du chiffrement des données en base de données ?


Quel algorithme est recommandé pour le hashage des mots de passe ?


Pourquoi faut-il ajouter un sel lors du hashage d'un mot de passe ?


Quel est le risque principal des injections SQL ?


Quelle méthode permet d'éviter les injections SQL ?


Quel protocole permet de sécuriser la communication entre une application et une base de données ?


Quel est le problème de stockage d'un mot de passe en clair ?


Quel est l'intérêt du chiffrement au niveau des colonnes de la base de données ?


Pourquoi faut-il limiter les permissions des utilisateurs sur une base de données ?


Quelle est la meilleure façon de vérifier un mot de passe stocké de manière sécurisée ?


TP pour réfléchir et résoudre des problèmes

Ce TP permet d'expérimenter différentes techniques de sécurisation des bases de données, en appliquant le chiffrement, le hashage et la protection contre les injections SQL.

1) Création d'une base de données sécurisée

  1. Ouvrir un terminal et se connecter à MySQL :
mysql -u root -p
  1. Créer une base de données nommée securite_bd :
CREATE DATABASE securite_bd;
  1. Utiliser cette base de données :
USE securite_bd;

2) Création d'une table avec un stockage sécurisé des mots de passe

  1. Créer une table utilisateurs avec un stockage sécurisé des mots de passe :
CREATE TABLE utilisateurs (
id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(255) NOT NULL UNIQUE,
mot_de_passe VARBINARY(255) NOT NULL
);
info

La table utilisateurs est maintenant créée avec trois colonnes :

  • id : Un identifiant unique pour chaque utilisateur, généré automatiquement.
  • email : Un champ pour stocker l'adresse e-mail, avec la contrainte UNIQUE pour éviter les doublons.
  • mot_de_passe : Un champ de type VARBINARY(255) pour stocker les mots de passe sous forme chiffrée.

L'utilisation de VARBINARY permet de stocker des données binaires comme des mots de passe chiffrés ou hashés.


3) Chiffrement des mots de passe lors de l'inscription

  1. Insérer un utilisateur avec un mot de passe chiffré en utilisant AES :
INSERT INTO utilisateurs (email, mot_de_passe)
VALUES ('user@example.com', AES_ENCRYPT('MonMotDePasseSecurise', 'cleSecrete'));
  1. Vérifier que le mot de passe est bien chiffré :
SELECT * FROM utilisateurs;
info

La requête INSERT ajoute un nouvel utilisateur avec un mot de passe chiffré.

La fonction AES_ENCRYPT('MonMotDePasseSecurise', 'cleSecrete') chiffre le mot de passe en utilisant la clé cleSecrete.

En consultant la table avec SELECT * FROM utilisateurs;, on remarque que le mot de passe n'est pas stocké en clair, mais sous forme chiffrée.


4) Récupération et déchiffrement du mot de passe

  1. Récupérer et déchiffrer le mot de passe d'un utilisateur :
SELECT email, AES_DECRYPT(mot_de_passe, 'cleSecrete') AS mot_de_passe_dechiffre FROM utilisateurs;
info

La fonction AES_DECRYPT(mot_de_passe, 'cleSecrete') permet de retrouver le mot de passe en clair en utilisant la même clé de chiffrement.

Cette méthode est utile pour vérifier un mot de passe, mais elle n'est pas recommandée en production. Il est préférable d'utiliser un hashage sécurisé.


5) Implémentation du hashage des mots de passe en PHP

  1. Créer un fichier hashage.php et y insérer le code suivant :
<?php
$motDePasse = "MonMotDePasseSecurise";
$hash = password_hash($motDePasse, PASSWORD_BCRYPT);
echo "Mot de passe hashé : " . $hash;
?>
  1. Exécuter le fichier avec PHP :
php hashage.php
info

Le script PHP utilise password_hash() avec l'algorithme bcrypt pour générer un hash sécurisé du mot de passe.

Lors de l'exécution, un hash est affiché. Ce hash est unique à chaque exécution car bcrypt génère un sel aléatoire automatiquement.


6) Vérification d'un mot de passe en PHP

  1. Modifier le fichier hashage.php pour ajouter la vérification du mot de passe :
<?php
$motDePasse = "MonMotDePasseSecurise";
$hash = password_hash($motDePasse, PASSWORD_BCRYPT);

if (password_verify("MonMotDePasseSecurise", $hash)) {
echo "Mot de passe correct";
} else {
echo "Mot de passe incorrect";
}
?>
  1. Exécuter le fichier :
php hashage.php
info

La fonction password_verify() compare le mot de passe en clair avec son hash.

Si le mot de passe est correct, le message "Mot de passe correct" s'affiche. Sinon, "Mot de passe incorrect" apparaît.

Cette méthode est plus sécurisée que le chiffrement réversible car elle ne permet pas de retrouver le mot de passe en clair.


7) Protection contre les injections SQL

  1. Créer un fichier protection_sql.php et y insérer le code suivant :
<?php
$pdo = new PDO("mysql:host=localhost;dbname=securite_bd", "root", "");

// Requête sécurisée avec requête préparée
$email = "user@example.com";
$stmt = $pdo->prepare("SELECT * FROM utilisateurs WHERE email = ?");
$stmt->execute([$email]);
$user = $stmt->fetch();

if ($user) {
echo "Utilisateur trouvé : " . $user['email'];
} else {
echo "Utilisateur non trouvé";
}
?>
  1. Exécuter le fichier :
php protection_sql.php
info

Le script utilise PDO et une requête préparée pour éviter les injections SQL.

La valeur de $email est passée en paramètre sécurisé avec execute([$email]), empêchant les attaques de type injection SQL.

Si un utilisateur avec cet e-mail existe, il est affiché. Sinon, un message indique qu'il n'est pas trouvé.


8) Tentative d'injection SQL et protection

  1. Modifier le fichier protection_sql.php pour tester une injection SQL :
$email = "admin@example.com' OR '1'='1";
  1. Exécuter le fichier et observer le résultat.
info

Si la requête n'était pas protégée, cette injection SQL permettrait de récupérer tous les utilisateurs de la base.

Grâce à l'utilisation de requêtes préparées, l'injection SQL ne fonctionne pas et la requête reste sécurisée.

Cela prouve l'importance de ne jamais concaténer directement des entrées utilisateur dans une requête SQL.