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
1pouradmindans la session de l'utilisateur. - L'application vérifie la valeur de
admindans 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.