Bonnes pratiques en dev.
Bonnes pratiques de développement sécurisé : Sécuriser une application contre les failles courantes
Notions théoriques
Développer une application sécurisée est essentiel pour protéger les utilisateurs et leurs données.
De nombreuses attaques exploitent des failles courantes dans le code.
Il est donc important d’adopter des bonnes pratiques dès la conception.
1. Validation et filtrage des entrées utilisateur
Les données saisies par un utilisateur ne doivent jamais être utilisées directement sans contrôle. Une entrée malveillante peut provoquer des comportements inattendus, voire dangereux.
- Filtrer les entrées : Supprimer ou remplacer les caractères spéciaux pouvant être utilisés dans des attaques.
- Valider les formats : Vérifier que les données correspondent au type attendu (exemple : une adresse e-mail doit contenir
@
et un domaine valide). - Limiter la longueur : Restreindre la taille des entrées pour éviter des attaques par dépassement de mémoire.
2. Protection contre l’injection SQL
L’injection SQL est une attaque qui consiste à insérer du code SQL malveillant dans une requête. Pour s’en protéger :
- Utiliser des requêtes préparées : Séparer les données de la requête SQL.
- Éviter la concaténation de chaînes : Ne jamais insérer directement des variables utilisateur dans une requête SQL.
3. Sécurisation contre les attaques XSS (Cross-Site Scripting)
Le XSS permet à un attaquant d’exécuter du JavaScript malveillant sur une page Web. Pour éviter cela :
- Échapper les sorties : Convertir les caractères spéciaux (
<
,>
,&
, etc.) en entités HTML. - Utiliser une politique de sécurité du contenu (CSP) : Restreindre les scripts autorisés.
4. Gestion des mots de passe
Les mots de passe doivent être protégés pour éviter leur vol en cas de fuite de données :
- Utiliser un algorithme de hachage sécurisé (
bcrypt
,argon2
). - Ne jamais stocker un mot de passe en clair.
- Appliquer une politique de complexité (longueur minimale, caractères spéciaux, etc.).
5. Protection contre les attaques CSRF (Cross-Site Request Forgery)
Une attaque CSRF force un utilisateur authentifié à effectuer une action non désirée. Pour s’en prémunir :
- Utiliser des jetons CSRF : Un token unique est généré et vérifié pour chaque requête critique.
- Limiter la durée de validité des sessions.
Exemple pratique
Il est possible de sécuriser un formulaire d’authentification en appliquant ces bonnes pratiques.
Création du formulaire
Créer un fichier login.html
:
<form action="login.php" method="POST">
<input type="text" name="username" placeholder="Nom d'utilisateur" required>
<input type="password" name="password" placeholder="Mot de passe" required>
<input type="submit" value="Se connecter">
</form>
Traitement sécurisé des données (login.php
)
<?php
session_start();
$pdo = new PDO('mysql:host=localhost;dbname=securite', 'root', '', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$username = htmlspecialchars($_POST['username'], ENT_QUOTES, 'UTF-8');
$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'])) {
$_SESSION['username'] = $user['username'];
header("Location: dashboard.php");
exit;
} else {
echo "Identifiants incorrects.";
}
}
?>
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Ce TP a pour objectif de créer un formulaire d'inscription sécurisé en appliquant les bonnes pratiques de développement sécurisé.
É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 d'avoir une base de données pour stocker les utilisateurs.
Instructions :
- Ouvrir phpMyAdmin ou un terminal MySQL.
- Créer une base de données nommée
securite_web
:
CREATE DATABASE securite_web;
- Sélectionner cette base de données :
USE securite_web;
- Créer une table
users
avec les champs suivants :id
: Identifiant unique, auto-incrémenté.username
: Nom d'utilisateur unique.password
: Mot de passe haché.
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL
);
Une solution
Vous devez être connecté pour voir le contenu.
Étape 2 : Création du formulaire d'inscription
Un formulaire HTML permet aux utilisateurs de s'inscrire en fournissant un nom d'utilisateur et un mot de passe.
Instructions :
- Créer un fichier
register.html
. - 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>Inscription</title>
</head>
<body>
<form action="register.php" method="POST">
<label for="username">Nom d'utilisateur :</label>
<input type="text" name="username" id="username" required minlength="3" maxlength="50">
<label for="password">Mot de passe :</label>
<input type="password" name="password" id="password" required minlength="8">
<input type="submit" value="S'inscrire">
</form>
</body>
</html>
Une solution
Vous devez être connecté pour voir le contenu.
Étape 3 : Traitement sécurisé des données
Le fichier register.php
doit récupérer les données du formulaire et les stocker de manière sécurisée.
Instructions :
- Créer un fichier
register.php
. - 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 = trim($_POST['username']);
$password = $_POST['password'];
// Vérification des entrées
if (strlen($username) < 3 || strlen($username) > 50) {
die("Le nom d'utilisateur doit contenir entre 3 et 50 caractères.");
}
if (strlen($password) < 8) {
die("Le mot de passe doit contenir au moins 8 caractères.");
}
// Échapper les entrées pour éviter les attaques XSS
$username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
// Hachage du mot de passe
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
try {
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (:username, :password)");
$stmt->execute([
'username' => $username,
'password' => $hashedPassword
]);
echo "Inscription réussie.";
} catch (PDOException $e) {
if ($e->getCode() == 23000) {
echo "Ce nom d'utilisateur est déjà pris.";
} else {
echo "Erreur lors de l'inscription.";
}
}
}
?>
Une solution
Vous devez être connecté pour voir le contenu.
Étape 4 : Vérification de l'inscription
Une fois l'inscription réussie, il est possible de vérifier si un utilisateur peut se connecter.
Instructions :
- Créer un fichier
login.html
. - 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>
Une solution
Vous devez être connecté pour voir le contenu.
Étape 5 : Traitement de la connexion sécurisée
Créer un fichier login.php
:
<?php
session_start();
$pdo = new PDO('mysql:host=localhost;dbname=securite_web', 'root', '', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$username = htmlspecialchars($_POST['username'], ENT_QUOTES, 'UTF-8');
$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'])) {
$_SESSION['username'] = $user['username'];
header("Location: dashboard.php");
exit;
} else {
echo "Identifiants incorrects.";
}
}
?>
Une solution
Vous devez être connecté pour voir le contenu.