306 lines
6.6 KiB
Markdown
306 lines
6.6 KiB
Markdown
% 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 :
|
|
|
|
```
|
|
<RequireAll>
|
|
Require all granted
|
|
Require not ip 10.252.46.165
|
|
</RequireAll>
|
|
```
|
|
|
|
---
|
|
|
|
Tout bloquer sauf si connexion valide OU adresse IP spécifique :
|
|
|
|
```
|
|
<RequireAll>
|
|
Require all denied
|
|
<RequireAny>
|
|
Require ip 192.168.1.12
|
|
Require valid-user
|
|
</RequireAny>
|
|
</RequireAll>
|
|
```
|
|
|
|
---
|
|
|
|
## 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 :
|
|
|
|
```
|
|
<Directory />
|
|
Options -Indexes -ExecCGI -FollowSymLinks -Includes
|
|
</Directory>
|
|
```
|
|
|
|
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 |