Sécurisons Apache avec fail2ban
Un matin, en regardant mes logs, j’ai vu ça :
[Tue Feb 02 14:16:54 2010] [error] [client 192.168.1.20] File does not exist: /var/www/favicon.ico [Tue Feb 02 14:16:57 2010] [error] [client 192.168.1.20] File does not exist: /var/www/favicon.ico [Tue Feb 02 14:28:36 2010] [error] [client 82.230.79.111] File does not exist: /var/www/favicon.ico [Tue Feb 02 14:28:39 2010] [error] [client 82.230.79.111] File does not exist: /var/www/favicon.ico [Tue Feb 02 18:27:07 2010] [error] [client 88.164.111.127] File does not exist: /var/www/favicon.ico [Tue Feb 02 18:27:10 2010] [error] [client 88.164.111.127] File does not exist: /var/www/favicon.ico [Wed Feb 03 05:55:12 2010] [error] [client 84.244.181.86] File does not exist: /var/www/roundcubemail [Wed Feb 03 05:55:12 2010] [error] [client 84.244.181.86] File does not exist: /var/www/rc [Wed Feb 03 05:55:12 2010] [error] [client 84.244.181.86] File does not exist: /var/www/webmail [Wed Feb 03 05:55:12 2010] [error] [client 84.244.181.86] File does not exist: /var/www/roundcube [Wed Feb 03 05:55:12 2010] [error] [client 84.244.181.86] File does not exist: /var/www/mail [Wed Feb 03 05:55:13 2010] [error] [client 84.244.181.86] File does not exist: /var/www/README
Ce qui signifie plusieurs choses :
Pas de favicon
Je n’ai pas de favicon, et le navigateur la demande. Résolvons l’erreur, ça coûte rien et ça rend mes logs plus lisibles ; on se déplace dans le répertoire web par défaut /var/www/, puis on crée un fichier vide appelé favicon.ico, et enfin on lui attribue les bons droits :
~$ cd /var/www/ ~$ sudo touch favicon.ico ~$ sudo chown 777 favicon.ico
Ouh le coquin
Un petit canaillou s’amuse à essayer de trouver un dossier qui n’existe pas. À la lecture du log, on voit bien qu’il ne me veut pas que du bien. J’avais déjà installé fail2ban, mais je n’avais créé de jail que pour SSH. Il va falloir en créer pour Apache : d’après mes recherches, il existe quelques jails classiques. On va éditer le fichier de config de fail2ban pour les ajouter.
sudo vim /etc/fail2ban/jail.local
Tant qu’on y est, on va faire en sorte de ne pas pouvoir bannir une adresse locale : chez moi, une adresse locale a la forme
192.168.1.*
On va donc compléter la ligne ignoreip comme suit :
ignoreip = 127.0.0.1 192.168.1.0/24
Et on ajoute nos jails :
# Jail pour les attaques dictionnaire qui visent phpmyadmin [apache-admin] enabled = true port = http filter = apache-admin logpath = /var/log/apache*/error*.log maxretry = 6 # Jail pour les curieux qui essaient de trouver un dossier au pif [apache-404] enabled = true port = http filter = apache-404 logpath = /var/log/apache*/error*.log maxretry = 10 # Jail pour les attaques par requêtes DFind w00tw00t [apache-w00tw00t] enabled = true filter = apache-w00tw00t action = iptables[name=Apache-w00tw00t,port=80,protocol=tcp] logpath = /var/log/apache2/access*.log maxretry = 1
Maintenant, les filtres associés à ces jails :
On crée le fichier pour la jail apache-admin
~$ sudo vim /etc/fail2ban/filter.d/apache-admin.conf
Et on y colle
# Fail2Ban configuration file # # Author: Cyril Jaquier # # $Revision: 471 $ # [Definition] # Option: failregex # Notes.: regex to match the password failure messages in the logfile. The # host must be matched by a group named "host". The tag "<HOST>" can # be used for standard IP/hostname matching. # Values: TEXT # [client x.x.x.x] File does not exist: /home/www/admin/admin, failregex = [[]client <HOST>[]] File does not exist: .*admin|PMA|mysql # # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. # Values: TEXT # ignoreregex =
Ensuite on crée le fichier pour la jail apache-404
~$ sudo vim /etc/fail2ban/filter.d/apache-404.conf
Et on y colle
# Fail2Ban configuration file # # Author: Cyril Jaquier # # $Revision: 471 $ # [Definition] # Option: failregex # Notes.: regex to match the password failure messages in the logfile. The # host must be matched by a group named "host". The tag "<HOST>" can # be used for standard IP/hostname matching. # Values: TEXT # [client x.x.x.x] File does not exist: /home/www/admin/admin, failregex = [[]client <HOST>[]] File does not exist: .* # # Option: ignoreregex # Notes.: regex to ignore. If this regex matches, the line is ignored. # Values: TEXT # ignoreregex =
Et puis on crée le fichier pour la jail apache-w00tw00t
~$ sudo vim /etc/fail2ban/filter.d/apache-w00tw00t.conf
Et on y colle
[Definition] failregex = ^<HOST> -.*"GET \/w00tw00t\.at\.ISC\.SANS\.DFind\:\).*".* ignoreregex =
Ça, c’est fait. On recharge les préférences de fail2ban :
~$ sudo fail2ban-client reload
Et on vérifie que nos jails on bien été créées :
~$ sudo fail2ban-client status Status |- Number of jail: 4 `- Jail list: apache-admin, apache-w00tw00t, ssh, apache-404
On retrouve bien nos trois nouvelles jails (celle pour ssh était déjà là avant), tout va bien !
Un plugin Munin pour fail2ban
C’est bien beau tout ça, mais comment je sais si j’ai attrapé quelqu’un dans mes filets ?
Très simple, on va dire à Munin qu’il faut aussi surveiller fail2ban.
Créer le fichier /usr/share/munin/plugins/fail2ban
~$ sudo vim /usr/share/munin/plugins/fail2ban
On y colle :
#! /bin/bash # # script venant de Majorxtrem’s Blogs (merci) # http://www.majorxtrem.be/2009/08/14/plugins-fail2ban-pour-munin/ PROGNAME=fail2ban STATEDIR=/var/lib/munin/plugin-state LISTJAIL=$(fail2ban-client status | grep " Jail list:" | sed 's/`- Jail list:\t\t//g' | sed 's/,//g') if [ "$1" = "config" ] then echo 'system.type ABSOLUTE' echo 'graph_title Fail2ban' echo 'graph_vlabel Number of ban' echo 'graph_category Security' for f in $LISTJAIL; do # replace - with _ echo "$(echo "$f.label" | tr - _) $f" done exit 0 fi for f in $LISTJAIL; do # replace - with _ echo "$(echo "$f.value" | tr - _) $(fail2ban-client status $f | grep " Currently banned:" | sed 's/ |- Currently banned:\t//g')" done
Comme Munin n’aime pas les tirets (?), le plugin les remplace par des underscores.
On fait un lien symbolique du plugin dans le dossier des plugins Munin :
~$ sudo ln -s /usr/share/munin/plugins/fail2ban /etc/munin/plugins/
Et on rend le plugin exécutable :
sudo chmod +x /usr/share/munin/plugins/fail2ban
Pour que Munin puisse utiliser fail2ban, il doit avoir des privilèges plus élevés. On édite
~$ sudo vim /etc/munin/plugin-conf.d/munin-node
Et on ajoute
[fail2ban] user root
Il n’y a plus qu’à redémarrer Munin :
~$ sudo /etc/init.d/munin-node restart
Et peu de temps après, bingo ! On a notre premier client :
~$ sudo vim /var/log/fail2ban.log
2010-02-08 11:21:49,698 fail2ban.filter : ERROR No 'host' found in '[Mon 2010] [error] [client 205.244.148.43] File does not exist: /var/www/mysql' using '<_sre.SRE_Pattern object at 0xb17c50>' 2010-02-08 11:21:51,312 fail2ban.actions: WARNING [apache-404] Ban 205.244.148.43 2010-02-08 11:31:52,146 fail2ban.actions: WARNING [apache-404] Unban 205.244.148.43
Du côté de Munin :
Bon évidemment, il n’ a été banni que 600 secondes, durée par défaut (ça fait 10 minutes, croyez-le ou non). Je vais augmenter ce temps, histoire de lui apprendre qu’on ne foule pas impunément mon territoire.
~$ sudo vim /etc/fail2ban/jail.local
Trouver la ligne bantime et mettre un nombre de secondes dissuasif :
bantime = 86400 #te voilà en taule pour 24h, brigand !
On recharge la configuration de fail2ban :
~$ sudo fail2ban-client reload
Et nous voilà débarrassés de cette engeance.
Billet tiré des pages suivantes :
- Configuration et règles fail2ban : http://j2c.org/informatique/linux/fail2ban.php
- Règle w00tw00t : http://doc.ubuntu-fr.org/fail2ban
- Plugin fail2ban pour Munin : http://www.majorxtrem.be/2009/08/14/plugins-fail2ban-pour-munin/
- Plugin corrigé pour régler le problème des tirets : dans les commentaires de la page ci-dessus, d’après Didier Mission, mais le formatage casse le plugin. Ma version fonctionne pour de vrai
[apache-admin]
enabled = true
port = http
filter = apache-admin
logpath = /var/log/apache*/error*.log
maxretry = 6
[apache-404]
enabled = true
port = http
filter = apache-404
logpath = /var/log/apache*/error*.log
maxretry = 10

Ecrire un commentaire