Menu & Search

Créer des règles personnalisées dans Fail2Ban

1 septembre 2016

Dans un billet précédent, j’expliquais comment bloquer manuellement une attaque brute force sur le fichier xmlrpc.php de WordPress. Je reprendrais donc ce cas comme exemple afin d’expliquer comment automatiser le processus.

Pré-requis

Fail2ban est un service qui examine les fichiers log du serveur et permet de définir des actions de blocage à exécuter lorsqu’un motif est détecté. Il n’est pas installé par défaut sur Ubuntu:

$ sudo apt-get update
$ sudo apt-get install -y fail2ban

Déterminer le motif à surveiller

L’attaque sur le fichier xmlrpc.php est visible dans le fichier access.log d’Apache sous cette forme :

$ sudo cat /var/log/apache2/access.log | grep xmlrpc.php 
191.96.249.54 - [26/Aug/2016:21:59:56 -0400] "POST /xmlrpc.php HTTP/1.0" 403 471 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"

Il s’agit d’une requête de type POST envoyé à /xmlrpc.php et qui retourne un code HTTP 403. Le motif à surveiller, la failregex, est décrite sous forme d’expression régulière.

A l’aide de l’outil d’écriture d’expression régulière RegExr, on obtient plus ou mois rapidement ceci :

fail2ban-regexr
L’expression régulière est donc :

^\S+ .+POST \/xmlrpc\.php HTTP.+ 403

En remplaçant la portion \S+ par <HOST>, on obtient l’expression finale, où <HOST> sera l’adresse IP utilisée par fail2ban lors du blocage :

^<HOST> .+POST \/xmlrpc\.php HTTP.+ 403

Selon la configuration du système, il peut être nécessaire d’utiliser %(__prefix_line) après ^

Créer le filtre

Il faut ensuite créer un filtre pour permettre à fail2ban de détecter l’attaque dans les fichiers de log :

$ sudo nano /etc/fail2ban/filter.d/xmlrpc-bruteforce.conf
# Fail2Ban filter for WordPress bruteforce through xmlrpc.php file
#

[INCLUDES]

before = common.conf

[Definition]

failregex = ^<HOST> .+POST \/xmlrpc\.php HTTP.+ 403

ignoreregex =

Le contenu du filtre est assez sommaire, la valeur de failregex doit correspondre à l’expression régulière définie plus haut. L’inclusion du fichier common.conf permet l’utilisation de motifs de remplacement tel que %(__prefix_line).

Tester le filtre

Afin de préserver la santé mentale de l’utilisateur, fail2ban intègre un outil de test qui permet de s’assurer que l’expression régulière est correctement définie :

$ fail2ban-regex /var/log/apache2/access.log /etc/fail2ban/filter.d/xmlrpc-bruteforce.conf
Running tests
=============

Use   failregex file : /etc/fail2ban/filter.d/xmlrpc-bruteforce.conf
Use         log file : /var/log/apache2/access.log


Results
=======
...
Lines: 1720 lines, 0 ignored, 456 matched, 1264 missed

Le test indique combien de fois le motif défini par le filtre xmlrpc-bruteforce.conf est effectivement trouvé dans le fichier access.log. Pour faciliter cette vérification, il est préférable d’isoler une partie du log dans un autre fichier et de lancer le test sur un échantillon où l’on connait le nombre de correspondance qui devraient être détectées.

Associer le filtre à une action

Une fois le filtre créé, il faut l’ajouter à la fin du fichier de configuration jail.conf ou dans un fichier que l’on placera dans le répertoire /etc/fail2ban/jail.d/ :

$ sudo nano /etc/fail2ban/jail.conf
[xmlrpc-bruteforce]

enabled   = true
filter    = xmlrpc-bruteforce
logpath   = /var/log/apache2/access.log
maxretry  = 1
banaction = iptables-allports
bantime   = 604800
protocol  = all
port      = all

La valeur de maxretry détermine le nombre de nouvelles tentatives tolérées avant de bloquer l’adresse IP.
La valeur de bantime détermine la durée du blocage en secondes.

Activer le filtre

Pour que la nouvelle règle soit prise en compte, il faut impérativement recharger le service :

$ sudo fail2ban-client reload
2015-04-18 16:12:08,321 fail2ban.jail   : INFO   Jail 'xmlrpc-bruteforce' started

Fail2ban en action

Le rôle de fail2ban peut être observé avec tcptrack:

$ tcptrack -i venet0
191.96.249.54:55646   169.125.128.112:80    SYN_SENT     4s     0 B/s
191.96.249.54:41928   169.125.128.112:80    SYN_SENT     8s     0 B/s
191.96.249.54:46015   169.125.128.112:80    SYN_SENT     5s     0 B/s
191.96.249.54:59913   169.125.128.112:80    SYN_SENT     30s    0 B/s
191.96.249.54:60861   169.125.128.112:80    SYN_SENT     23s    0 B/s
191.96.249.54:54418   169.125.128.112:80    SYN_SENT     5s     0 B/s
191.96.249.54:36830   169.125.128.112:80    SYN_SENT     18s    0 B/s
191.96.249.54:49217   169.125.128.112:80    RESET        1s     901 B/s
191.96.249.54:34727   169.125.128.112:80    SYN_SENT     8s     0 B/s
191.96.249.54:41896   169.125.128.112:80    SYN_SENT     22s    0 B/s
191.96.249.54:41030   169.125.128.112:80    SYN_SENT     28s    0 B/s
191.96.249.54:60184   169.125.128.112:80    SYN_SENT     15s    0 B/s
191.96.249.54:34732   169.125.128.112:80    SYN_SENT     17s    0 B/s
191.96.249.54:59848   169.125.128.112:80    SYN_SENT     9s     0 B/s
191.96.249.54:45143   169.125.128.112:80    RESET        2s     0 B/s
191.96.249.54:46398   169.125.128.112:80    SYN_SENT     14s    0 B/s
191.96.249.54:38565   169.125.128.112:80    SYN_SENT     8s     0 B/s
191.96.249.54:34247   169.125.128.112:80    SYN_SENT     21s    0 B/s
191.96.249.54:33887   169.125.128.112:80    SYN_SENT     12s    0 B/s
191.96.249.54:46035   169.125.128.112:80    SYN_SENT     12s    0 B/s
191.96.249.54:51541   169.125.128.112:80    SYN_SENT     6s     0 B/s
191.96.249.54:44857   169.125.128.112:80    SYN_SENT     19s    0 B/s
191.96.249.54:59520   169.125.128.112:80    SYN_SENT     16s    0 B/s
191.96.249.54:34900   169.125.128.112:80    SYN_SENT     8s     0 B/s
191.96.249.54:51756   169.125.128.112:80    SYN_SENT     22s    0 B/s
191.96.249.54:38575   169.125.128.112:80    SYN_SENT     19s    0 B/s

Le temps de blocage a été réglé à 20 secondes pour la démonstration.

Les connexions qui ont un statut à SYN_SENT sont bloqués par le firewall et les connexions qui ont un statut à RESET sont les deux tentatives tolérées par fail2ban. Celui-ci devrait être à ESTABLISHED mais l’accès au fichier xmlrpc.php est bloqué par la configuration du virtualhost.

Épilogue

L’attaque présentée ici n’est pas distribuée ce qui rend l’action de fail2ban plus facile.

Dans le cas d’une attaque venant de plusieurs adresses IP, il est possible de rendre le blocage plus restrictif en interdisant les nouvelles tentatives (maxretry = 0) et en bloquant définitivement les connexions (bantime = -1)

Configuration du serveur utilisé pour la démonstration :

  • Ubuntu 14.04.5 LTS
  • Fail2Ban v0.8.11
  • tcptrack v1.4.2
Article Tags
Jonathan Experton

En tant qu'architecte et développeur de solutions web et mobile open-source, je crée des applications et des sites web à l'aide d'outils tels que Laravel, Drupal, Wordpress, VueJS et jQuery.

Related article
Un exemple d’attaque DoS et comment s’en protéger

Un exemple d’attaque DoS et comment s’en protéger

Il y a quelques jours, j’ai été amené à intervenir…

Type your search keyword, and press enter to search