From e8b40afaa81b2841af6667126a64231e5d6670e2 Mon Sep 17 00:00:00 2001 From: Florent Madelaine Date: Tue, 24 May 2022 15:00:21 +0200 Subject: [PATCH] securite --- 5TDSecurite.md | 16 ++++ 5TPSecurite.md | 160 +++++++++++++++++++++++++++++++++++++++ TP5/article_list.php | 38 ++++++++++ TP5/article_view.php | 72 ++++++++++++++++++ TP5/comment_create.php | 50 ++++++++++++ TP5/csrf.html | 9 +++ TP5/extra/db.sql | 136 +++++++++++++++++++++++++++++++++ TP5/lib/common.php | 18 +++++ TP5/templates/footer.php | 9 +++ TP5/templates/header.php | 9 +++ TP5/user_create.php | 51 +++++++++++++ TP5/user_login.php | 37 +++++++++ TP5/web_security.txt | 60 +++++++++++++++ 13 files changed, 665 insertions(+) create mode 100644 5TDSecurite.md create mode 100644 5TPSecurite.md create mode 100644 TP5/article_list.php create mode 100644 TP5/article_view.php create mode 100644 TP5/comment_create.php create mode 100644 TP5/csrf.html create mode 100644 TP5/extra/db.sql create mode 100644 TP5/lib/common.php create mode 100644 TP5/templates/footer.php create mode 100644 TP5/templates/header.php create mode 100644 TP5/user_create.php create mode 100644 TP5/user_login.php create mode 100644 TP5/web_security.txt diff --git a/5TDSecurite.md b/5TDSecurite.md new file mode 100644 index 0000000..4a2f92b --- /dev/null +++ b/5TDSecurite.md @@ -0,0 +1,16 @@ +# TD Sécurité Web. # + +## Exo (Quizz) ## +* Comment échappe-t-on les caractères spéciaux en sql? + +## Exo (Little Bobby Table) ## +* Allez lire le célèbre cartoon [exploits of a mum](https://xkcd.com/327/) +* Quel est le problème? +* Donnez un exemple de base de données et de requêtes nécessaires pour recréer ce qui est évoqué dans ce cartoon. + +**corection** +Voir [explain xkcd](https://www.explainxkcd.com/wiki/index.php/327:_Exploits_of_a_Mom)? + +## Exo (Pour aller plus loin) ## +Implémentez une base de donnée et un fichier d'inscription d'étudiant mal protégé pour réaliser concrètement l'attaque par inscription de *little bobby table*. + diff --git a/5TPSecurite.md b/5TPSecurite.md new file mode 100644 index 0000000..1d5bf3f --- /dev/null +++ b/5TPSecurite.md @@ -0,0 +1,160 @@ + +# Introduction à la sécurité des applis web en PHP. + + +Le tp utilise une application de mini-blog. Le code PHP est +volontairement simplifié et suffisamment laxiste pour illustrer les +failles de sécurité abordées en cours. + +Le site utilise un base de données sql. Vous pouvez directement +l'importer (répertoire `extra`). Les paramètres pour l'accès à la base +de données sont dans `lib/common.php`. + +Avant de démarrer, consultez les pages existantes, créez un compte et +authentifiez-vous. + +#### Formulaires et html + +##### Modification de contenu + +1. Postez un commentaire sur un article. +2. Modifiez votre commentaire. Modifiez le commentaire d'un autre + utilisateur. +
Aide + Regardez l'url ! +
+ +3. Sécurisez l'écriture du formulaire `comment_create.php` afin qu'on + ne puisse pas accéder à un commentaire d'un autre utilisateur. + +
Aide + Dans la requête de modification d'un commentaire, ajoutez à la + clause WHERE la vérification du user. +
+ +4. Le client peut-il modifier le formulaire, en changeant par exemple + l'id du commentaire à modifier ? comment ? + +
Aide + Il suffit d'écrire son propre formulaire, avec la possibilité de + saisir le champ id du commentaire ! +
+ +5. Pour se prémunir contre cela, on va, dans le formulaire, rajouter un + code d'authentification (hash avec une clé secrète) du champ + `id_comment` pour être sur que les données proviennent du formulaire + de l'application. Uilisez la fonction + [hash_mac](http://php.net/manual/fr/function.hash-hmac.php). + + Rajoutez, dans le formulaire, un hash que vous pourrez comparé au + hash re-calculé après l'envoie des données. +
Aide +
+ générez un hash avec une clé secrète : + + ```php + $hashCode = hash_hmac("sha256",$_REQUEST['id_comment'],"Ma clé"); + echo ''; + ``` + + Au moment du traitement du formulaire, quand on reçoit le champ + `id_comment`, on recalcule et compare le hash avec celui reçu. +
+
+ +##### XSS + +1. Ajoutez un commentaire qui masque tout ce qui suit son affichage + (uniquement de l'html svp !). Revenez à un fonctionnement normal. + +
Aide + Pensez à fermer des balises, et à en ouvrir une qui cachera tout le + reste au moyen d'une propriété css. +
+ +2. Ajoutez un commentaire qui modifie le titre `h1` de la page de + l'article. + +
Aide +
+ Le javascript permet de modifier le contenu HTML d'un élément : + + ```js + document.querySelector("h1").innerHTML = "hey !!!!"; + ``` +
+
+ +3. Empêchez la saisie de balises HTML (les supprimer) pour éviter les + attaques ci-dessus. Est-ce suffisant ? + +4. Echappez (protéger) les textes affichés dans le html + (htmlspecialchars). + +5. Créez un compte en donnant une url de façon à exploiter une faille + XSS sur la page `article_view.php`. + +
Aide +
+ ```js + javascript:alert(/XSS !/); + ``` +
+
+ +6. Proposez une url vers la page `user_login.php` qui affiche dans un + popup les login/mots de passe saisies dans le formulaire (cela + pourrait être plus dangereux, en les envoyant sur un serveur par + exemple ...) + +
Aide + La valeur de la variable login est écrite dans le formulaire, dans + l'attribut value du champ texte correspondant. + + Il donc tout à fait possible d'injecter du code javascript via un + attribut html, par exemple onchange ... +
+ +##### CSRF + +Les vunérabilités de type CSRF (Cross-Site Request Forgery) consiste à +forger de fausses requêtes à partir d'url authentifiées et à pousser le +client à exécuter des actions sans le savoir. + +Le client authentifié exécute à son insu une requête (suppression par +exemple) par un formulaire dissimuler ou une balise image contrôlée par +du javascript. + +1. Se rendre sur la page `csrf.html` (soyez authentifié). Que s'est-il + passé ? +2. Passer les données en POST résoudra le problème précédent. + Malheureusement, on pourra quand même créer une attaque avec du + javascript. (vous verrez l'année prochaine qu'on peut faire une + requête http à partir de javasscript. +3. Résoudre le problème en utilisant un token unique dans le + formulaire. + +#### Injection SQL {#injection-sql .alert} + +1. Sur la page `user_login.php`, connectez-vous sans mot de passe, + juste avec un login valide. +2. connectez-vous sans mot de passe ni login. +3. "Sécurisez" avec la méthode `quote` de PDO. +4. Sur la page `comment_create.php`, malgré l'échappement SQL, + prouvez que l'on peut toujours modifier les commentaires d'autrui. + +
Aide + Regerdez la clause WHERE dans la requête d'update d'un + commentaire. +
+ +5. Utilisez le [filtrage](http://fr.php.net/manual/fr/book.filter.php) + en entrée des données. +6. Sécurisez la page `comment_create.php` avec des requêtes + préparées. + +#### Sessions + +1. Utilisez une faille XSS pour afficher le contenu du cookie. Volez + alors la session associée. (Il suffit d'écrire depuis un autre + navigateur la valeur du cookie récupéré) diff --git a/TP5/article_list.php b/TP5/article_list.php new file mode 100644 index 0000000..8bb7ae2 --- /dev/null +++ b/TP5/article_list.php @@ -0,0 +1,38 @@ +query("SELECT * FROM article")->fetchAll(PDO::FETCH_OBJ); + +?> + + + + + +

Liste des articles

+ +Bonjour, " . $_SESSION['user']->name . ".

"; +} +?> + + + + + + + diff --git a/TP5/article_view.php b/TP5/article_view.php new file mode 100644 index 0000000..a3e5bb5 --- /dev/null +++ b/TP5/article_view.php @@ -0,0 +1,72 @@ +query("SELECT * FROM article WHERE id=" . $_GET['id']) + ->fetch(PDO::FETCH_OBJ); + +$article->comments = $db->query("SELECT c.*, u.login, u.url " + . "FROM comment c JOIN user u ON c.id_user=u.id" + . " WHERE id_article=" . $_GET['id']) + ->fetchAll(PDO::FETCH_OBJ); + +?> + + + +

Article

+ +' + . '

'. $article->title .'

' + . '
' . $article->content . '
'; + +echo '
Commentaires
'; +if (empty($article->comments)) { + echo '

Aucun

'; +} else { + foreach ($article->comments as $comment) { + echo '
'; + echo "".$comment->title."" + . (isset($_SESSION['user']->id) && $comment->id_user == $_SESSION['user']->id ? + ' Modifier ce commentaire' : + '') + . '

' . $comment->content ."

" + . "

url\">$comment->login

"; + echo "
"; + } +} +echo ""; + +if (empty($_SESSION['user'])) { + echo '

Il faut être identifié pour poster un commentaire.

'; +} else { + if ($article->closed) { + echo "

Article fermé, non modifiable.

"; + } else { + echo '

Ajouter un commentaire avec votre compte : ' . $_SESSION['user']->name + .'

'; + } +} +?> + +

Retour à la liste des articles

+ + + + + diff --git a/TP5/comment_create.php b/TP5/comment_create.php new file mode 100644 index 0000000..b639b24 --- /dev/null +++ b/TP5/comment_create.php @@ -0,0 +1,50 @@ +id.")"; + } else { + $sql = "UPDATE comment SET title='$title', content='$content', id_user=". $_SESSION['user']->id + ." WHERE id = " . $_GET['id_comment']; + } + if ($db->query($sql)) { + header('Location: article_view.php?id=' . $_GET['id_article']); + exit(); + } else { + die("Erreur : $sql"); + } +} +?> + + + +

Ajouter/modifier un commentaire

+
+
+\n"; +} ?> + +
+
+ +
+
+ + + diff --git a/TP5/csrf.html b/TP5/csrf.html new file mode 100644 index 0000000..39aa733 --- /dev/null +++ b/TP5/csrf.html @@ -0,0 +1,9 @@ + + + Sécurité PHP + + + + image + + diff --git a/TP5/extra/db.sql b/TP5/extra/db.sql new file mode 100644 index 0000000..fc77226 --- /dev/null +++ b/TP5/extra/db.sql @@ -0,0 +1,136 @@ +-- phpMyAdmin SQL Dump +-- version 4.7.0 +-- https://www.phpmyadmin.net/ +-- +-- Host: localhost +-- Generation Time: May 29, 2017 at 06:15 AM +-- Server version: 10.1.22-MariaDB +-- PHP Version: 7.1.4 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET AUTOCOMMIT = 0; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `securite` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `article` +-- + +CREATE TABLE `article` ( + `id` int(11) NOT NULL, + `title` text COLLATE utf8mb4_unicode_ci, + `closed` decimal(10,0) DEFAULT NULL, + `content` text COLLATE utf8mb4_unicode_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `article` +-- + +INSERT INTO `article` (`id`, `title`, `closed`, `content`) VALUES +(1, 'Premier', '1', 'Premier message, sans commentaire.'), +(2, 'Second', '0', 'Second message, avec des commentaires.'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `comment` +-- + +CREATE TABLE `comment` ( + `id` int(11) NOT NULL, + `id_article` decimal(10,0) DEFAULT NULL, + `title` text COLLATE utf8mb4_unicode_ci, + `id_user` decimal(10,0) DEFAULT NULL, + `content` text COLLATE utf8mb4_unicode_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `comment` +-- + +INSERT INTO `comment` (`id`, `id_article`, `title`, `id_user`, `content`) VALUES +(1, '2', 'Super', '2', 'Article très intéressant !'), +(2, '2', 'Un commentaire', '1', 'Pour tester !'), +(3, '2', 'Un deuxième commentaire', '1', 'ça casse pas trois pattes à un canard !'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `user` +-- + +CREATE TABLE `user` ( + `id` int(11) NOT NULL, + `login` varchar(60) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `name` varchar(60) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `password` text COLLATE utf8mb4_unicode_ci, + `url` text COLLATE utf8mb4_unicode_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- Dumping data for table `user` +-- + +INSERT INTO `user` (`id`, `login`, `name`, `password`, `url`) VALUES +(1, 'francois', 'François', 'mdp', 'http://fr.php.net'), +(2, 'denis', 'Denis', 'moi', 'http://lemonde.fr'); + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `article` +-- +ALTER TABLE `article` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `comment` +-- +ALTER TABLE `comment` + ADD PRIMARY KEY (`id`); + +-- +-- Indexes for table `user` +-- +ALTER TABLE `user` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `login` (`login`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `article` +-- +ALTER TABLE `article` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; +-- +-- AUTO_INCREMENT for table `comment` +-- +ALTER TABLE `comment` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=23; +-- +-- AUTO_INCREMENT for table `user` +-- +ALTER TABLE `user` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/TP5/lib/common.php b/TP5/lib/common.php new file mode 100644 index 0000000..db13c49 --- /dev/null +++ b/TP5/lib/common.php @@ -0,0 +1,18 @@ +getMessage()); + } + return $db; +} + diff --git a/TP5/templates/footer.php b/TP5/templates/footer.php new file mode 100644 index 0000000..3615298 --- /dev/null +++ b/TP5/templates/footer.php @@ -0,0 +1,9 @@ +
+

+ +

+

+ +

+ + diff --git a/TP5/templates/header.php b/TP5/templates/header.php new file mode 100644 index 0000000..4a2f280 --- /dev/null +++ b/TP5/templates/header.php @@ -0,0 +1,9 @@ + + + + + Sécurité PHP + + + + diff --git a/TP5/user_create.php b/TP5/user_create.php new file mode 100644 index 0000000..7ed1d82 --- /dev/null +++ b/TP5/user_create.php @@ -0,0 +1,51 @@ +query($sql)){ + header('Location: user_login.php'); + exit(); + }else{ + die("Erreur !!!!"); + } + } catch(PDOException $e) { + echo "Erreur: ".$e; + } +} + +?> + + + + + +

Création de compte

+
+
+
+ +
+
+ +
+
+ +
+
+ +

Retour à la liste des articles

+ + + + + diff --git a/TP5/user_login.php b/TP5/user_login.php new file mode 100644 index 0000000..5b5d16d --- /dev/null +++ b/TP5/user_login.php @@ -0,0 +1,37 @@ +query($sql)->fetch(PDO::FETCH_OBJ); + if ($user) { + $_SESSION['user'] = $user; + header('Location: article_list.php'); + exit(); + } +} + +?> + + + + +

Authentification et injection SQL

+
+
+
+
+
+ +
+
+ + + diff --git a/TP5/web_security.txt b/TP5/web_security.txt new file mode 100644 index 0000000..550a8d6 --- /dev/null +++ b/TP5/web_security.txt @@ -0,0 +1,60 @@ +[ Une liste de ressources partagée par Théo Debauvais ] + +XSS: + explication: + https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A7-Cross-Site_Scripting_(XSS) + https://www.acunetix.com/websitesecurity/xss/ + défense: + + site pour s'entrainer (que des DOM-XSS et client-side XSS): https://xss.pwnfunction.com/ + +Injection SQL: +explication: + explication: + https://owasp.org/www-project-top-ten/OWASP_Top_Ten_2017/Top_10-2017_A1-Injection + https://owasp.org/www-community/attacks/SQL_Injection + https://www.w3schools.com/sql/sql_injection.asp + défense: + https://www.php.net/manual/en/mysqli.real-escape-string.php ou une fonction similaire en fonction du language que vous utilisez + Preparez vos requests, ou echappez les entrée comme ci-dessus + Programme pour tester automatiquement : http://sqlmap.org/ + +Local File Inclusion (LFI) / Remote File Inclusion (RFI): + https://en.wikipedia.org/wiki/File_inclusion_vulnerability + +CSRF: + explication: + https://portswigger.net/web-security/csrf + https://owasp.org/www-community/attacks/csrf + défense: + https://thisinterestsme.com/php-csrf-protection/ , surtout le principe utilisé + +OS injection: + explication: + https://portswigger.net/web-security/os-command-injection + https://owasp.org/www-community/attacks/Command_Injection + défense: + + +Pourquoi il ne faut pas essayer de cacher des fichiers sur un serveur http: +https://github.com/OJ/gobuster +https://tools.kali.org/web-applications/dirbuster +https://tools.kali.org/web-applications/dirb + +Liste de vulnérabilitées (PortSwigger est une référence avec OWASP, ils développent https://tools.kali.org/web-applications/burpsuite, download=https://portswigger.net/burp): +https://portswigger.net/web-security/all-materials + +Liste des failles web les plus connues (référence): +https://owasp.org/www-project-top-ten/ + +Applications vulnérables pour s'entrainer: +http://www.dvwa.co.uk/ +http://itsecgames.com/ + +Site connus pour apprendre et s'entrainer (très axé sur le pentest, moins sur la défense): +https://www.root-me.org/ +https://www.hackthebox.eu/ +https://tryhackme.com/ + +Lectures de Stanford sur la sécurité web (très récent: commence en septembre 2019; très bon et explique plein d'autres failles et sujets sur la sécurité web): +https://www.youtube.com/watch?v=5JJrJGZ_LjM&list=PLMF2PpA06Sb26oYT-dfNOt3Y4wwoLAho0