22 KiB
Sécurité des applications Web
William Petit - S.C.O.P. Cadoles
La fondation OWASP
Open Web Application Security Project
- Fondé en 2001
- Organisation internationale à but non lucratif
Quelques projets en particulier
- OWASP Top Ten - Top 10 des failles impactant les applications Web
- OWASP Code Review Guide - Guide de la revue de code appliquée à la sécurité
- OWASP ASVS - Standard des vérifications de sécurité des applications Web
- OWASP Webgoat - Application(s) volontairement faillible(s) illustrant les principales failles de sécurité actuelles.
Les principales failles
Epicfaild
https://forge.cadoles.com/wpetit/epicfaild
Lancer avec Docker
docker run -it --rm -p 8888:8080 bornholm/epicfaild
# Puis ouvrir l'URL http://localhost:8888/
# dans votre navigateur
OWASP WebGoat
https://github.com/WebGoat/WebGoat
Lancer avec Docker
docker run -p 8080:8080 -it --rm webgoat/webgoat-8.0 /home/webgoat/start.sh
# Puis ouvrir l'URL http://localhost:8080/WebGoat/
# dans votre navigateur
Injections SQL (SQLI)
Pratique
Epicfaild: Gate 3 et 4 WebGoat: Injection Flaws (- XEE)
Risques
- Vol de données
- Altération de données
- Prise de contrôle du serveur
Mitigation
- Exécuter le moteur de base de données avec un utilisateur dédié.
- Valider TOUTES les entrées utilisateur.
- Utiliser des requêtes préparées.
- Installer un NIDS au niveau du serveur HTTP
Contournement de la session
Pratique
Epicfaild: Gate 3 WebGoat: Authentication Bypass
Risques
- Vol de session
- Vol de données
- Prise de contrôle de l'application
Mitigation
- Valider TOUTES les entrées utilisateurs
- Journaliser les origines des connexions
Cross Site Scripting (XSS)
Pratique
Epicfaild: Gate 1 WebGoat: Cross Site Scripting
Risques
- Vol de sessions
- Hameçonnage
Mitigation
- Valider TOUTES les entrées utilisateurs
- Assainir les données avant de faire leur rendu
Mauvais contrôle des accès
Pratique
WebGoat: Access Control Flaws
Risques
- Accès non autorisés à des fonctionnalités critiques
- Vol de données
- Prise de contrôle de l'application
Mitigation
- Journaliser tous les accès à des ressources critiques (qui, quoi, quand, quel contexte ?)
- Utiliser une double authentification pour l'accès aux ressources critiques
Attention L'obfuscation des accès n'est pas une méthode de sécurisation des points d'entrée.
Fuite d'informations sensibles
Pratique
Epicfaild: Gate 4/5
WebGoat: Insecure communication, Client Side/Client side filtering
Risques
- Vol de données
Mitigation
- Ne retourner à l'utilisateur que les données dont il a besoin (approche "frugale").
- Limiter la zone d'action de l'utilisateur à ses seuls besoins.
Cross Site Request Forgery (CSRF)
Pratique
WebGoat: Request Forgeries
Risques
- Hameçonnage
- Vol de session
- Vol d'identité
Mitigation
- Utilisation de
nonce
(aussi appelé CSRF Token) - Utilisation de requêtes
POST|PUT|DELETE
pour toutes les actions autres que la "consultation" - S'assurer que les mécanismes de type "HTTP Method Override" ne sont pas activés en production (Exemple pour Symfony3)
Mauvaise politique de maintenance
Pratique
WebGoat: Vulnerable components
Risques
Les risques dépendent du composant faillible...
Mitigation
- Activer les mécanismes de mise à jour automatique
- Vérifier les mises à jour des librairies de manière automatisée.
- Suivre la publication des CVE/NVD
Métrologie applicative appliquée à la sécurité
Méthodologie générale
Modélisation de menace
Identification des flux de données
Les facteurs d'une bonne métrique
Exemple d'outil: Prometheus
Méthodologie générale
- Définir le modèle de menace
- Identifier et isoler les scénarios d'attaque pour les différentes menaces
- Trouver les indicateurs "clés" pour ces scénarios i.e. identifier les métriques pertinentes pour la détection des comportements suspects
- Mettre en place les sondes pour les métriques
- Définir les seuils d'alerte et les réponses à apporter
La modélisation de menace
- Identification des dépendances externes. Exemple: serveur GNU/Linux, base de données
- Identification des points d'entrées Exemple: formulaire de contact, port de la base de données
- Identification des assets Exemple: Comptes utilisateurs de l'application, données personnelles, droits d'accès
- Identification des niveaux de confiance Exemple: Utilisateur anonyme, administrateur
Identification des flux de données
Les facteurs d'une bonne métrique
- Concision Le domaine de mesure est il correctement défini ? La métrique n'essaye t-elle pas de mesurer trop de choses ?
- Fidélité La mesure est elle reproductible ? Mesure t-elle toujours la même chose ?
- Intégrité Le processus de mesure est il vulnérable à la falsification ?
- Utilité La métrique apporte elle une information utile au processus décisionnel ?
Exemple d'outil: Prometheus
Téléchargement
https://prometheus.io/download/#prometheus
Configuration générale
Instrumentation de l'application
Modèle de données
Les différents types de métriques
Les requêtes
Modèle de données
Prometheus stocke des échantillons (mesures) sous la forme de séries temporelles. Il créait une nouvelle série pour chaque association (nom_métrique, label1=value, label2=value, ...).
Chaque couple (label, valeur) est appelée dimension de la métrique.
Représentation
http_total_requests{ method="POST", path="/test" }
| name | labels |
Les différents types de métriques
Compteur (1)
Un compteur est une métrique dont la valeur ne peut faire qu'augmenter au cours du temps.
Exemple Nombre total de connexions d'un compte sur un site
Jauge
Une jauge est une métrique dont la valeur peut augmenter ou diminuer au cours du temps.
Exemple La température d'une pièce
Histogramme (1)
Un histogramme est une métrique répartissant les données dans des "seaux" (ou "buckets" en anglais) configurables et comptant le nombre total et par "paquet" d'échantillons ainsi que leur somme.
Exemple Le temps de réponse des requêtes HTTP
Histogramme (2)
Scénario d'exemple
Soit la métrique http_request_duration_seconds
un histogramme avec les "buckets" suivants: 0.5, 1, 2, 3, 5.
3 requêtes sont effectuées sur l'application avec des temps de 1s, 2s et 3s respectivements.
On aura sur /metrics
:
http_request_duration_seconds_bucket{le="0.5"} 0
http_request_duration_seconds_bucket{le="1"} 1
http_request_duration_seconds_bucket{le="2"} 2
http_request_duration_seconds_bucket{le="3"} 3
http_request_duration_seconds_bucket{le="5"} 3
http_request_duration_seconds_bucket{le="+Inf"} 3
http_request_duration_seconds_sum 6
http_request_duration_seconds_count 3
Les requêtes
Types de données
-
scalar
Un nombre à virgule flottante Exemple:5.1
-
instant vector
Un ensemble de séries temporelles contenant un seul échantillon pour chaque série temporelle, toutes partageant le même horodatage. Exemple:http_request_duration_seconds
-
range vector
Un ensemble de séries temporelles contenant une gamme de points de données au fil du temps pour chaque série temporelle. Exemple:http_request_duration_seconds[5m]
-
string
Une chaine de caratères. Exemple:"hello world"
Les opérateurs
Opérateurs arithmétiques
+
, -
, *
, /
, %
(modulo), ^
(puissance)
Opérateurs de comparaison
==
, !=
, >
, >=
, <
, <=
Opérateurs d'aggrégation
sum
, min
, max
, avg
, stddev
, stdvar
, count
, count_values
, bottomk
, topk
, quantile
Opérateurs logiques
and
, or
, unless
Voir la documentation du projet
Fonctions
Quelques exemples
rate(range vector)
Retourne la fréquence moyenne d'augmentation par seconde de la série temporelle dans l'espace de temps donné. À utiliser uniquement avec les compteurs.time()
Retourne le nombre de secondes depuis l'Epoch Unix.increase(range vector)
Retourne l'augmentation de la série temporelle dans l'interval de temps donné. À utiliser uniquement avec les compteurs.
Et aussi histogram_quantile(), predict_linear(),...
Voir la documentation du projet
Configuration de l'alertmanager
Téléchargement
https://prometheus.io/download/#alertmanager
Écriture de règles d'alertes
Exercice: métrologie orientée sécurité d'une application Symfony3
- Créer une nouvelle application Symfony3 et configure une authentification de type "Basic Auth" sur une route.
- Implémenter une
Listener
pour l'évènementsecurity.authentication.failure
(voir ce tutoriel) - Installer et configurer le bundle tweedegolf/prometheus-bundle
- Mettre en place une sonde pour détecter les tentatives répétées d'authentification échouées pour une adresse IP donnée.
- Mettre en place une alerte lorsque le nombre d'authentifications échouées dépasse un certain seuil dans un espace de temps donné.
Sécurité de l'infrastructure pour l'hébergement Web
Sécurité et configuration du serveur GNU/Linux
Configuration du serveur HTTP
Monitoring
Sécurité et configuration du serveur GNU/Linux
Installation du serveur
Politique d'accès et configuration SSH
Règles de pare-feu
Politique de sauvegarde
Installation du serveur
Règles générales de partitionnement (1)
- Utiliser LVM
- ~300/500M pour
/boot
- Partition séparée pour
/var
( via un volume logique) - Partition séparée pour
/home
(via un volume logique) - Partition séparée pour
/
(via un volume logique) - Garder de l'espace pour pouvoir agrandir au besoin une partition LVM
Règles générales de partitionnement (2)
Exemple Pour 10G de disque
Point de montage | Système de fichier | Taille |
---|---|---|
/boot |
ext4 (Primaire) | 500M |
/ |
ext4 (LVM) | 4G (~30/40%) |
/home |
ext4 (LVM) | 1G (10%) |
/var |
ext4 (LVM) | 3G (~30/40%) |
swap |
swap (LVM) | round(sqrt(RAM) < swap < 2*RAM |
Et garder ~10% d'espace libre pour pouvoir agrandir un volume logique au besoin.
Activation des mises à jour automatiques
Si à l'installation l'option n'est pas proposée (sur Debian et dérivées)
apt-get install unattended-upgrades apt-listchanges
Voir la documentation Debian pour plus d'informations
Politique d'accès et configuration SSH
Installation du serveur OpenSSH
apt install openssh-server
Désactivation de l'authentification SSH avec l'utilisateur root
vim /etc/ssh/sshd_config
# ...
# PermitRootLogin no
# ...
systemctl restart ssh
Désactivation de la connexion SSH avec un mot de passe
vim /etc/ssh/sshd_config
# ...
# PasswordAuthentication no
# ...
systemctl restart ssh
Restreindre les utilisateurs et/ou groupes autorisés à se connecter en SSH
vim /etc/ssh/sshd_config
# ...
# AllowUsers jdoe bob
# AllowGroups jdoe bob
# ...
systemctl restart ssh
Augmenter la taille des clés SSH du serveur
vim /etc/ssh/sshd_config
# ...
# ServerKeyBits 2048
# ...
rm /etc/ssh/ssh_host_*
systemctl restart ssh
Créer des comptes utilisateurs avec un mot de passe expiré (1)
adduser <uid>
chage -d 0 <uid>
Puis penser à copier la clé SSH publique de l'utilisateur dans /home/<uid>/.ssh/authorized_keys
.
Créer des comptes utilisateurs avec un mot de passe expiré (2)
Attention, OpenSSH est très "chatouilleux" avec les droits sur les répertoires .ssh
et le fichier .ssh/authorized_keys
. En cas de doute:
chmod go-w <uid> <uid>/.ssh
chmod 600 <uid>/.ssh/authorized_keys
chown <uid> $HOME/.ssh/authorized_keys
Règles de pare-feu
Installation d'UFW
Uncomplicated Firewall
apt install ufw
Activation du pare-feu
iptables -L # Afficher les règles iptables
ufw allow 22/tcp # Pour éviter de perdre la connexion SSH actuelle
ufw enable # Activer le pare-feu
iptables -L # Vérifier l'application des règles
Vérifier le statut des règles
ufw status verbose
Gestion des règles par défaut
ufw default deny # Refuser tous les paquets par défaut
ufw default allow # Accepter tous les paquets par défaut
ufw default allow outgoing # Accepter les connexions sortantes par défaut
ufw default allow ingoing # Accepter les connexions entrantes par défaut
Ajouter des règles
# Connexions entrantes
# Autoriser toutes les connexions depuis 192.168.0.4 sur le port 22
ufw allow from 192.168.0.4 to any port 22
# Refuser toutes les connexions depuis 207.46.232.182
ufw deny from 207.46.232.182
# Connexions sortantes
# Autoriser les connexions UDP sur le port 53 (requêtes DNS)
ufw allow out 53/udp
# Autoriser les connexions MySQL (3306/tcp) vers l'adresse 192.168.0.43
ufw allow out to 192.168.0.43 port mysql
Supprimer une règle
ufw status numbered # Afficher les identifiants des règles
ufw delete <id> # Supprimer une règle par son identifiant
Exercice
Avec UFW, configurer votre serveur pour:
- Refuser toutes les connexions entrantes/sortantes par défaut
- Autoriser la connexion SSH uniquement depuis l'IP de votre poste de travail et celle d'un de vos collègues présent à la formation.
- Autoriser les connexions sortantes HTTP/HTTPS vers l'adresse 192.168.0.30 (i.e. un serveur fournissant une API REST utilisée par votre application)
- Autoriser les connexions sortantes MongoDB vers l'adresse 192.168.0.45 (i.e. une base de données MongoDB utilisée par votre application)
Politique de sauvegarde
Installation de rsync/rsnapshot
Sur le serveur
apt install rsync
Sur le client
apt install rsnapshot rsync
Configuration de rsnapshot (1)
Sur le serveur
- Créer un utilisateur dédié à la sauvegarde
- S'assurer que le compte de sauvegarde a les droits de lecture sur les répertoires à sauvegarder
- Déployer une clé SSH pour le compte de sauvegarde (à utiliser sur le client)
Configuration de rsnapshot (2)
Sur le client
# Éditer la configuration
vim /etc/rsnapshot.conf
# Définition de la rotation des sauvegardes
#
# retain hourly 24 # Une sauvegarde par heure hourly.0 -> hourly.23
# retain daily 7 # Si le rép. existe, copie hourly.23 vers daily.0
# retain weekly 4 # Si le rép. existe, copie daily.6 vers weekly.0
# retain monthly 12 # Si le rép. existe, copie weekly.3 vers monthly.0
# Vérifier la configuration
rsnapshot configtest
# Exécuter un "dry-run"
rsnapshot -t hourly # Ou daily/weekly/monthly
# Configurer les tâches CRON
crontab -e
# @hourly rsnapshot hourly
# @daily rsnapshot daily
# @weekly rsnapshot weekly
# @monthly rsnapshot monthly
Restaurer une sauvegarde
rsync -av \
/var/cache/rsnapshot/<level>.<iteration> \
user@server-host:/path/to/dest
Configuration du serveur HTTP
Apache2
Certificats TLS/SSL
Apache2
Installation
apt install apache2
Désactivation des entêtes d'informations
vim /etc/apache2/apache2.conf
# ...
ServerSignature Off
ServerTokens Prod
# ...
systemctl reload apache2
Désactivation de l'indexation automatique des dossiers
vim /etc/apache2/apache2.conf
# ...
<Directory /var/www/html>
Options -Indexes
</Directory>
# ...
systemctl reload apache2
Désactivation des modules inexploités
# Afficher les directives de chargement des modules
grep LoadModule /etc/apache2/mods-enabled/*.load
# Désactiver un module
rm /etc/apache2/mods-enabled/<module>.load
# Recharger la configuration Apache2
systemctl reload apache2
Modules souvent inclus mais peu utilisés: mod_imap, mod_include, mod_info, mod_userdir, mod_autoindex
Activation du module mod_evasive
# Installation du module
apt install apache2-mod-evasive
# Activer le module (si non activé par défaut)
a2enmod evasive
# Configurer le module
vim /etc/apache2/mods-enabled/evasive.conf
# Recharcher la configuration Apache2
systemctl reload apache2
Activation du module mod_security
# Installation du module
apt install libapache2-mod-security2
# Activer le module (si non activé par défaut)
a2enmod security2
# Configurer le module
vim /etc/modsecurity/modsecurity.conf-recommended
# Activer la configuration recommandée
mv /etc/modsecurity/modsecurity.conf-recommended \
/etc/modsecurity/modsecurity.conf
# Recharcher la configuration Apache2
systemctl reload apache2
SSL/TLS
Générer un certificat autosigné
openssl req \
-x509 \
-newkey rsa:4096 \
-keyout key.pem \
-out cert.pem \
-days 365 \
-nodes
Utilisation du certificat avec Apache2
# /etc/apache2/sites-enabled/my-site.conf
NameVirtualHost *:80
<VirtualHost *:80>
ServerName www.example.com
Redirect / https://secure.example.com/
</VirtualHost>
<VirtualHost _default_:443>
ServerName secure.example.com
DocumentRoot /var/www/html
SSLEngine On
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
# etc...
</VirtualHost>
Tester la configuration TLS/SSL
Avec le projet TestSSL
# Récupération du script
wget -O- https://testssl.sh/ > testssl.sh
# Rendre exécutable le script
chmod +x ./testssl.sh
# Tester une URL
./testssl.sh <URL>
Supervision du système
Installation, configuration et usage de fail2ban (NIDS)
Supervision du système avec Prometheus
Installation de fail2ban
apt install fail2ban
Configuration
Principaux fichiers et répertoires
/etc/fail2ban/fail2ban.conf
- Fichier de configuration général/etc/fail2ban/jail.conf
- Définition des "jails" par défaut/etc/fail2ban/jail.d
- Définitions de "jails" additionnelles/etc/fail2ban/filter.d
- Filtres d'activation des "jails"/etc/fail2ban/action.d
- Définition des actions potentielles à exécuter en cas d'activation d'une "jail".
La personnalisation de la configuration se fait en créant des fichiers <nom_fichier>.local
.
Exercice
Configurer fail2ban pour bannir les IP à l'origine de tentatives de connexion échouées sur un site Wordpress.
- Installer et configurer Wordpress sur votre serveur (voir page suivante)
- Créer une
failregex
pour détecter les tentatives échouées de connexion à votre Wordpress. Quelle est la différence dans les logs entre un échec et un succès ? - Créer votre filtre
/etc/fail2ban/filter.d/wordpress.conf
avec votre expression régulière. Pour tester:fail2ban-regex --print-all-match <logfile> \ /etc/fail2ban/filter.d/<filter>.conf
- Créer votre propre section "wordpress" dans le fichier
/etc/fail2ban/jail.local
en vous inspirant des exemples déjà présents.
Préparation
- Sur votre machine virtuelle, installer Wordpress et MySQL
apt install wordpress mysql-server
- Activer Wordpress
ln -s /usr/share/wordpress /var/www/html/wordpress
- Copier la configuration Wordpress par défaut
cp /usr/share/wordpress/wp-config-sample.php \ /etc/wordpress/config-<votre_ip>.php
- Créer un compte utilisateur dans la base de données MySQL
mysql -u root -p mysql> CREATE DATABASE wordpress; mysql> GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress'@'localhost' IDENTIFIED BY '<password>'; mysql> quit
- Modifier la configuration pour que Wordpress utilise sa base de données (fichier
/etc/wordpress/config-<votre_ip>.php
)
Supervision du système avec Prometheus
Exercice
- Sur votre machine virtuelle, installer l'exporteur de métriques
Node Exporter
et créer un nouveau servicesystemd
pour celui ci. - Installer et configurer un serveur Apache2 avec un VirtualHost exposant via la directive
ProxyPass
du modulemod_proxy
. - Mettre en place une règle d'alerte sur votre instance Prometheus locale afin de prévenir le remplissage du disque de votre serveur via la fonction
predict_linear()
(par exemple 4 heures ?)