Aller au contenu principal

Protection contre les injections

Protection contre les injections SQL et XSS

Notions théoriques

Les attaques par injection SQL et XSS (Cross-Site Scripting) sont parmi les plus courantes contre les applications Web.

info

Les attaques par injection SQL et XSS exploitent des failles dans la manière dont les données sont traitées par une application.

Injection SQL

L'injection SQL est une attaque qui consiste à insérer du code SQL malveillant dans une requête afin d'en modifier le comportement.

Cette attaque survient généralement lorsque les entrées utilisateur ne sont pas correctement filtrées avant d'être utilisées dans une requête SQL.

Exemple d'injection SQL :

Si une application exécute la requête suivante sans vérification :

SELECT * FROM users WHERE username = '$username' AND password = '$password';

Un attaquant peut entrer admin' -- comme nom d'utilisateur, ce qui modifie la requête en :

SELECT * FROM users WHERE username = 'admin' --' AND password = '$password';

Le -- transforme le reste de la requête en commentaire, permettant à l'attaquant de se connecter sans connaître le mot de passe.

Protection contre l'injection SQL

  • Utiliser des requêtes préparées avec des paramètres pour éviter l'injection de code.
  • Filtrer et valider les entrées utilisateur avant de les utiliser dans une requête SQL.
  • Restreindre les permissions des comptes SQL utilisés par l'application.

Cross-Site Scripting (XSS)

L'attaque XSS consiste à injecter du code JavaScript malveillant dans une page Web afin de voler des informations ou d'exécuter des actions à l'insu de l'utilisateur.

Exemple d'attaque XSS :

Si un site affiche un commentaire sans filtrer les balises HTML, un attaquant peut insérer :

<script>alert('Vous êtes piraté !');</script>

Tous les visiteurs de la page verront cette alerte s'afficher.

Protection contre XSS

  • Échapper les données affichées pour empêcher l'exécution de code HTML et JavaScript.
  • Utiliser des Content Security Policy (CSP) pour limiter les scripts exécutables.
  • Filtrer les entrées utilisateur pour supprimer ou neutraliser les scripts malveillants.

Exemple pratique

Il est possible de sécuriser une application PHP contre l'injection SQL et le XSS en appliquant des bonnes pratiques.

Sécurisation contre l'injection SQL avec PDO

Au lieu d'insérer directement les entrées utilisateur dans une requête SQL, utiliser des requêtes préparées :

<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->execute([
'username' => $_POST['username'],
'password' => hash('sha256', $_POST['password'])
]);
$user = $stmt->fetch();
?>

Protection contre XSS avec htmlspecialchars()

Pour empêcher l'exécution de scripts malveillants, échapper les sorties utilisateur :

<?php
$comment = htmlspecialchars($_POST['comment'], ENT_QUOTES, 'UTF-8');
echo "<p>$comment</p>";
?>

Test de mémorisation/compréhension


Quel est le principal risque d'une injection SQL ?


Quel caractère est souvent utilisé dans les injections SQL ?


Pourquoi utiliser les requêtes préparées en SQL ?


Quelle fonction PHP permet d'échapper les caractères spéciaux pour prévenir le XSS ?


Que signifie XSS ?


Quel est l'effet d'un Content Security Policy (CSP) ?


Quel est le but d'un filtre d'entrée utilisateur ?


Quel langage est ciblé par une attaque XSS ?


Que fait le `--` dans une requête SQL malveillante ?


Quel est le meilleur moyen de protéger une application contre les injections SQL ?



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

Sécurisation d’un formulaire de connexion contre les injections SQL et XSS

Ce TP consiste à créer un formulaire de connexion en PHP et à le sécuriser contre les attaques par injection SQL et XSS.


Étape 1 : Création de la base de données et de la table des utilisateurs

Avant de créer le formulaire, il est nécessaire de disposer d’une base de données contenant une table pour stocker les utilisateurs.

Instructions :

  1. Ouvrir phpMyAdmin ou un terminal MySQL.
  2. Créer une base de données nommée securite_web avec la commande SQL suivante :
CREATE DATABASE securite_web;
  1. Sélectionner cette base de données :
USE securite_web;
  1. Créer une table users avec les champs id, username et password :
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL
);
  1. Ajouter un utilisateur test avec un mot de passe haché :
<?php
$pdo = new PDO('mysql:host=localhost;dbname=securite_web', 'root', '');
$password = password_hash('monmotdepasse', PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (:username, :password)");
$stmt->execute([
'username' => 'admin',
'password' => $password
]);
?>

Étape 2 : Création du formulaire de connexion

Un formulaire HTML permet aux utilisateurs de saisir leur nom d’utilisateur et leur mot de passe.

Instructions :

  1. Créer un fichier login.html.
  2. Ajouter le code suivant :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Connexion</title>
</head>
<body>
<form action="login.php" method="POST">
<label for="username">Nom d'utilisateur :</label>
<input type="text" name="username" id="username" required>

<label for="password">Mot de passe :</label>
<input type="password" name="password" id="password" required>

<input type="submit" value="Se connecter">
</form>
</body>
</html>

Étape 3 : Traitement des données avec protection contre l’injection SQL

Le fichier login.php doit récupérer les données du formulaire et vérifier si l’utilisateur existe dans la base de données.

Instructions :

  1. Créer un fichier login.php.
  2. Ajouter le code suivant :
<?php
$pdo = new PDO('mysql:host=localhost;dbname=securite_web', 'root', '', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);

if ($_SERVER["REQUEST_METHOD"] === "POST") {
$username = $_POST['username'];
$password = $_POST['password'];

$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username");
$stmt->execute(['username' => $username]);
$user = $stmt->fetch();

if ($user && password_verify($password, $user['password'])) {
echo "Connexion réussie. Bienvenue, " . htmlspecialchars($username, ENT_QUOTES, 'UTF-8') . "!";
} else {
echo "Identifiants incorrects.";
}
}
?>

Étape 4 : Protection contre XSS

Les entrées utilisateur doivent être échappées avant d’être affichées sur la page.

Instructions :

  1. Modifier login.php pour protéger l’affichage du nom d’utilisateur :
<?php
if ($user && password_verify($password, $user['password'])) {
echo "Connexion réussie. Bienvenue, " . htmlspecialchars($username, ENT_QUOTES, 'UTF-8') . "!";
} else {
echo "Identifiants incorrects.";
}
?>

Étape 5 : Amélioration de la sécurité avec une redirection et une session

Une connexion réussie doit rediriger l’utilisateur vers une page sécurisée.

Instructions :

  1. Modifier login.php pour démarrer une session et rediriger l’utilisateur :
<?php
session_start();

if ($user && password_verify($password, $user['password'])) {
$_SESSION['username'] = $user['username'];
header("Location: dashboard.php");
exit;
} else {
echo "Identifiants incorrects.";
}
?>
  1. Créer un fichier dashboard.php :
<?php
session_start();
if (!isset($_SESSION['username'])) {
header("Location: login.html");
exit;
}
echo "Bienvenue, " . htmlspecialchars($_SESSION['username'], ENT_QUOTES, 'UTF-8') . "!";
?>

Conclusion

Ce TP a permis de créer un système de connexion sécurisé en PHP en appliquant plusieurs mesures de protection :

  • Utilisation de requêtes préparées pour éviter l’injection SQL.
  • Utilisation de password_hash() et password_verify() pour stocker et vérifier les mots de passe de manière sécurisée.
  • Protection contre XSS en échappant les sorties utilisateur avec htmlspecialchars().
  • Mise en place d’un système de session pour gérer l’authentification des utilisateurs.
attention

Ce type de protection est essentiel pour sécuriser les applications Web contre les attaques courantes.