% Introduction à la sécurité d'un serveur web % Sylvain Eliade — S.C.O.P. Cadoles ## Introduction à la sécurité d'un serveur web ## Fail2ban S'il ne faut en retenir qu'un c'est celui-là ! `apt install fail2ban` Il lit les logs en permanence et détecte les tentatives d'intrusion (mauvais mot de passe SSH, email, HTTP…) et bloque les IP automatiquement ! Activer les filtres dans `/etc/fail2ban/jail.conf` (passer `enabled` à `true`). Normalement la plupart des filtres nécessaires sont activés par défaut, mais ça vaut le coup de regarder si on peut en activer d'autres, ou de faire les siens ! ## Mises à jours de sécurité Ça semble évident, mais ça ne l'est pas pour tout le monde. Activer les mises à jour automatique de sécurité avec `unattended-upgrades`. ``` apt install unattended-upgrades ``` --- ## Pare-feu (firewall) Sous Linux, les ports sont fermés par défaut si un service n'écoute pas dessus, donc c'est "sécurisé" par défaut. Alors pourquoi un firewall ? Parce que si un attaquant parvient à ouvrir un port sur votre machine il peut s'en servir pour lui donner des ordres, ou faire des requêtes vers d'autres machines (par exemple transformer votre serveur en attaquant DDoS). Du coup un firewall est utile pour restreindre le risque en cas d'attaque. --- ## Pare-feu Linux Le noyau Linux contient déjà un pare-feu, c'est Netfilter, accessible via la commande `iptables`. Comme elle est un peu complexe, on conseille en général d'utiliser `ufw` (Uncomplicated FireWall), qui est une interface iptables simplifiée. --- ## UFW Installer avec `apt install ufw`, et activer avec `ufw enable`. Consulter le statut avec `ufw status verbose`. ``` Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip ``` Lister les règles disponibles : `ufw app list` --- (Dés)Activer le blocage par défaut : ``` ufw default allow incoming ufw default deny outgoing ``` Activer un service : ``` ufw allow in WWW ufw allow out VNC ``` --- Autoriser un port : ``` ufw allow 53 ufw allow 25/tcp ``` Bloquer une IP : ``` ufw deny from X.X.X.X to any ``` --- ## Restriction par IP Si on veut restreindre l'accès à un serveur web à certaines IP il y a plusieurs stratégies possibles : * au niveau du firewall (mieux, car le plus tôt dans la connexion réseau) * via TCP Wrappers ou systemd * via le serveur web --- ## Avec UFW ``` ufw deny 80 ufw allow from X.X.X.X to any port 80 ``` --- ## TCP Wrappers Mécanisme ancien, simple, mais aujourd'hui on utilise un firewall. Malgré le nom, il gère aussi UDP. La configuration se fait dans les fichiers `/etc/hosts.allow` et `/etc/hosts.deny`. N'est plus supporté par systemd. --- ``` # /etc/hosts.allow sshd: 192.168.1.0/255.255.255.0 # /etc/hosts.deny sshd: ALL ```` --- ## Restriction avec systemd Se fait au niveau du fichier `.service` : ``` IPAddressDeny=1.1.1.1 IPAddressAllow=8.8.8.8 ``` Encore une fois, mieux vaut préférer un firewall. --- ## Restriction avec Apache Avantage : peut se faire par répertoire, vhost, fichier… Tout autoriser sauf une IP : ``` Require all granted Require not ip 10.252.46.165 ``` --- Tout bloquer sauf si connexion valide OU adresse IP spécifique : ``` Require all denied Require ip 192.168.1.12 Require valid-user ``` --- ## Ne pas se tirer une balle dans le pied * Utiliser PHP 7.2 ou 7.3 ! Abandonnez PHP 5 et PHP 7.0 (plus supportés !) ! Enfin si c'est possible… * Configurer le serveur web pour n'écouter que sur l'interface / port nécessaire (`/etc/apache2/ports.conf`) * Ne pas exposer sa version de PHP ou Apache (ou nginx) * Désactiver le vhost par défaut d'apache, dont la page HTML peut contenir des infos utiles à un attaquant * Bloquer l'accès aux répertoires .svn et .git ! ``` RedirectMatch 404 /\.git RedirectMatch 404 /\.svn ``` --- ## Cacher les versions Pourquoi ? Contre les bots qui scannent les serveurs pas à jour. Dans `/etc/apache2/conf-enabled/security.conf` : ``` ServerTokens Prod ServerSignature Off ``` --- Avant : `Server: Apache/2.4.25 (Debian)` Après : `Server: Apache` --- Dans `/etc/php/7.0/apache/conf.d/local.ini` ajouter : ``` expose_php = off ``` --- ## Restreindre la surface d'attaque (Apache) Désactiver les index de répertoires, l'exécution de CGI, les liens symboliques et les inclusions : ``` Options -Indexes -ExecCGI -FollowSymLinks -Includes ``` Désactiver les .htaccess si possible. --- ## Restreindre la surface d'attaque (PHP) Restreindre les répertoires accessibles de PHP (dans le vhost Apache) : ``` php_admin_value open_basedir /var/www/monsite.com ``` Interdire l'exécution de programme externe : ``` disable_functions = exec,passthru,shell_exec,system,proc_open,popen ``` à mettre dans le `/etc/php/7.0/apache/conf.d/local.ini`, ou dans un `php_admin_value` par vhost. --- ## Aller plus loin Vérifier sa config : * Audit automatisé : mieux que ne rien faire, mais à ne pas faire en prod, laisse pas mal de traces (logs), peut surcharger le serveur * Audit manuel : de bonnes connaissances en sécu, ou un bon chéquier ! * Hardening PHP : ça restreint certaines fonctions et attaques, mais c'est bien mais ça peut casser des applis :( * WAF (Web Application Firewall) : idem, ça détecte des attaques connues, bonne stratégie défensive, mais attention aux effets de bord. --- * [Auditer son site avec Nikto](https://doc.ubuntu-fr.org/nikto) * [Hardening PHP : snuffleupagus (Apache)](https://github.com/nbs-system/snuffleupagus) * [Tester son certificat SSL avec SSL Labs](https://www.ssllabs.com/ssltest/) * [Mise en place de WAF avec mod_security pour Apache](https://www.it-connect.fr/installation-de-mod_security-devant-un-serveur-web-apache/) * [WAF pour nginx avec naxsi](https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-naxsi-on-ubuntu-16-04) --- ## Exercice 1 Installer `ufw` et n'autoriser que le port 80 en entrée. Vérifier avec : ``` nmap -p 80 ADRESSE_IP nmap -p 443 ADRESSE_IP ``` La première doit renvoyer que le port est ouvert, mais pas la seconde. --- ## Exercice 2 Modifier le `.htaccess` du répertoire `secret` précédemment créé pour autoriser aussi l'adresse IP `127.0.0.1` à y accéder sans mot de passe. Vérifier avec curl. --- ## Exercice 3 Cacher les versions de PHP et Apache. Vérifier avec Curl. --- ## Exercice 4 (facultatif) Installer Nikto et scanner les vhosts du serveur web. Nikto est dans les dépôts `non-free` de Debian : https://debian-facile.org/doc:systeme:apt:sources.list:sources.list-non-free