Contrôles d'accès défaillants
Principe de l'attaque
Les contrôles d'accès sont des mécanismes qui limitent l'accès à une ressource dans un système informatique. Lorsque ces contrôles sont défaillants, un attaquant peut accéder à des informations sensibles ou effectuer des actions sans avoir les autorisations appropriées.
Un exemple courant de ce type d'attaque est le "privilège escalation" où un utilisateur avec des privilèges limités arrive à obtenir des privilèges plus élevés, comme ceux d'un administrateur.
Une application Web vulnérable
Code source de la version vulnérable
Voici un exemple simple d'une application Web vulnérable écrite en PHP :
<?php
session_start();
if (isset($_GET['admin'])) {
$_SESSION['admin'] = $_GET['admin'];
}
if ($_SESSION['admin'] == 1) {
echo "Bienvenue, administrateur!";
} else {
echo "Vous n'êtes pas autorisé à accéder à cette page.";
}
?>
Dans ce code, l'application vérifie si un paramètre admin
est passé dans l'URL. Si c'est le cas, il est stocké dans la session de l'utilisateur. Ensuite, l'application vérifie si la valeur de admin
dans la session est égale à 1 pour déterminer si l'utilisateur est un administrateur.
Déroulement de la démo (attaque possible)
Un attaquant pourrait facilement exploiter cette vulnérabilité en ajoutant simplement ?admin=1
à l'URL, ce qui lui donnerait des privilèges d'administrateur.
Les étapes de l'attaque
- L'attaquant visite l'URL
http://example.com/vulnerable_page.php?admin=1
. - L'application enregistre la valeur
1
pouradmin
dans la session de l'utilisateur. - L'application vérifie la valeur de
admin
dans la session, la trouve égale à1
, et donne donc à l'utilisateur l'accès à la page d'administration.
Correction de la vulnérabilité
Code source de la version corrigée
Pour créer la base de données
Voici un exemple de fichier SQL pour créer la base de données avec une table users
:
CREATE DATABASE IF NOT EXISTS webapp;
USE webapp;
CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
role VARCHAR(255) NOT NULL
);
INSERT INTO users (username, password, role)
VALUES
('user', PASSWORD('userpassword'), 'user'),
('admin', PASSWORD('adminpassword'), 'admin');
Notez que la fonction PASSWORD()
de MySQL/MariaDB n'est pas aussi sécurisée que Bcrypt ou Argon2. De plus, elle est obsolète dans les versions récentes de MySQL/MariaDB. Dans un contexte réel, vous devriez utiliser une bibliothèque de hachage de mot de passe plus sécurisée et stocker le sel (une donnée utilisée lors du hachage) séparément.
Pour créer le fichier index.php
:
Voici un exemple simple de l'application Web corrigée :
<?php
session_start();
if (isset($_SESSION['user_id'])) {
$user_id = $_SESSION['user_id'];
$user = getUserFromDatabase($user_id); // On suppose que cette fonction récupère les informations de l'utilisateur depuis la base de données
if ($user['role'] == 'admin') {
echo "Bienvenue, administrateur!";
} else {
echo "Vous n'êtes pas autorisé à accéder à cette page.";
}
} else {
echo "Vous devez vous connecter pour accéder à cette page.";
}
?>
Voici une implémentation très simplifiée de la fonction getUserFromDatabase()
:
function getUserFromDatabase($user_id) {
// On suppose que la connexion à la base de données est déjà établie
global $db;
// Préparation de la requête SQL
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $user_id);
// Exécution de la requête
$stmt->execute();
// Récupération du résultat
$result = $stmt->get_result();
$user = $result->fetch_assoc();
return $user;
}
Dans cette fonction, nous utilisons les méthodes prepare()
, bind_param()
, execute()
et get_result()
pour prévenir les attaques d'injection SQL.
C'est une bonne pratique de sécurité à toujours respecter lorsque vous travaillez avec des bases de données.
Déroulement de la démo (attaque impossible)
Même si l'attaquant tente d'accéder à http://example.com/vulnerable_page.php?admin=1
, il ne recevra pas les privilèges d'administrateur car l'application ne se fie pas à la valeur admin
passée par l'URL.
Principe de la correction
La correction consiste à ne jamais faire confiance aux données fournies par l'utilisateur sans les avoir vérifiées.
Dans la version corrigée, l'application ne fait plus confiance à une valeur passée par l'URL. Au lieu de cela, elle vérifie les informations de l'utilisateur dans la base de données pour déterminer si l'utilisateur est un administrateur.
Risques liés à cette vulnérabilité
Si un attaquant parvient à exploiter une vulnérabilité de contrôle d'accès, il peut accéder à des informations sensibles, effectuer des actions non autorisées, et même prendre le contrôle total de l'application.
Code de bonne conduite
Il est crucial de toujours vérifier les permissions de l'utilisateur avant de lui donner accès à une ressource. Ne faites jamais confiance aux données fournies par l'utilisateur sans les avoir vérifiées.
Test de mémorisation/compréhension
N'oubliez pas, la cybersécurité est un domaine en constante évolution. Restez curieux et continuez à apprendre !