Menu & Search

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

1 septembre 2016

Il y a quelques jours, j’ai été amené à intervenir sur un site WordPress qui affichait une erreur de connexion à la base de données: Error establishing a database connection.

Je conseille au propriétaire du serveur de redémarrer le système afin de redémarrer MySQL, mais le problème réapparait rapidement en affichant cette fois-ci une erreur 500. Je me connecte finalement au serveur pour en savoir plus.

Diagnostic

En vérifiant la charge du serveur, un premier indice apparaît :

$ top
top - 18:44:48 up 3 days, 21:51,  1 user,  load average: 3.61, 0.84, 0.30
Tasks:  74 total,  14 running,  56 sleeping,   4 stopped,   0 zombie
%Cpu(s):  0.6 us,  0.1 sy,  0.0 ni, 99.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:   1048576 total,   980720 used,    67856 free,        0 buffers
KiB Swap:   131072 total,    18536 used,   112536 free.   843640 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
  885 nobody    20   0  303748  28380  20760 R 20.4  2.7   0:00.35 php-cgi
  894 nobody    20   0  302396  21136  14864 R 15.3  2.0   0:00.12 php-cgi
  865 nobody    20   0  307940  46408  34728 R  5.1  4.4   0:00.78 php-cgi
  869 nobody    20   0  307496  44924  33736 R  5.1  4.3   0:00.70 php-cgi
  870 nobody    20   0  306776  43232  32688 R  5.1  4.1   0:00.70 php-cgi
  874 nobody    20   0  305608  39896  30568 R  5.1  3.8   0:00.61 php-cgi
  889 nobody    20   0  301968  20508  14660 R  5.1  2.0   0:00.21 php-cgi
  890 nobody    20   0  303480  23932  16500 R  5.1  2.3   0:00.20 php-cgi
  897 nobody    20   0  300884  17500  12560 R  5.1  1.7   0:00.06 php-cgi
...

Une multitude de processus PHP sont en train de saturer la RAM et le CPU du serveur. Cela explique pourquoi les serveurs MySQL et Apache ne répondent plus, et pourquoi la connexion SSH est constamment interrompue. Une vérification du trafic avec tcptrack permet de confirmer qu’il s’agit d’une attaque.

Il faut d’abord installer tcptrack qui n’est pas inclus d’office avec Ubuntu 14.04 :

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

Le plus souvent, le nom de l’interface réseau est eth0 mais dans le cas d’un serveur virtuel il est fréquent de la trouver sous un autre nom :

$ ifconfig
lo        Link encap:Local Loopback
...
venet0    Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
...
venet0:0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
...

L’avantage de tcptrack est de pouvoir suivre en temps réel l’état des connexions ouvertes dans une interface minimaliste :

$ tcptrack -i venet0
191.96.249.54:39074   167.114.88.210:80    ESTABLISHED     0s    902 B/s B/s
191.96.249.54:50730   167.114.88.210:80    ESTABLISHED     1s    901 B/s B/s
191.96.249.54:16331   167.114.88.210:80    ESTABLISHED     1s    900 B/s B/s
...

La première colonne correspond à l’adresse IP d’origine, la deuxième à l’adresse IP et le port de destination (le serveur et le service attaqué).

La commande lsof permet de vérifier quel service (apache, nginx par exemple) écoute le port 80 :

$ sudo lsof -i :80 | grep LISTEN
apache2 11371 www-data    4u  IPv6 3269827235      0t0  TCP *:http (LISTEN)
...

La vérification des fichiers de logs d’Apache donne plus de détails sur l’origine des processus lancés :

$ sudo tail -100 /var/log/apache2/access.log
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)"
191.96.249.54 - [26/Aug/2016:21:59:57 -0400] "POST /xmlrpc.php HTTP/1.0" 403 471 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
191.96.249.54 - [26/Aug/2016:21:59:57 -0400] "POST /xmlrpc.php HTTP/1.0" 403 471 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
191.96.249.54 - [26/Aug/2016:21:59:57 -0400] "POST /xmlrpc.php HTTP/1.0" 403 471 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
191.96.249.54 - [26/Aug/2016:21:59:58 -0400] "POST /xmlrpc.php HTTP/1.0" 403 471 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
191.96.249.54 - [26/Aug/2016:21:59:58 -0400] "POST /xmlrpc.php HTTP/1.0" 403 471 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
191.96.249.54 - [26/Aug/2016:21:59:59 -0400] "POST /xmlrpc.php HTTP/1.0" 403 471 "-" "Mozilla/4.0 (compatible: MSIE 7.0; Windows NT 6.0)"
...

Le problème est maintenant identifié, il s’agit d’une attaque par brute force sur le fichier xmlrpc.php dans le but de trouver les identifiants de connexion à WordPress.

Le serveur n’ayant que 1G de RAM, l’attaque par brute force a été détectée en provocant les symptômes d’une attaque DoS, d’où le titre de cet article.

Solution

La manière la plus radicale d’arrêter l’attaque est de bloquer l’adresse IP avec ufw, un outil intégré à Ubuntu qui simplifie la gestion des règles de iptables

$ sudo ufw deny from 191.96.249.54 to any

Les connexions entrantes de l’attaquant ne recevront plus de réponse :

$ tcptrack -i venet0 port 80
 191.96.249.54:39074   167.114.113.230:80    SYN_SENT     25s    0 B/s
 191.96.249.54:50730   167.114.113.230:80    SYN_SENT     26s    0 B/s
...

Avant d’établir une connexion TCP, plusieurs paquets sont échangés entre deux machines (cf. three-way handshake), le statut SYN_SENT signifie que l’attaquant tente d’établir une connexion en envoyant un message SYN mais le serveur ne lui renvoie plus de message SYN-ACK. La connexion finira par s’interrompre au bout de 30 secondes.

Solutions alternatives

Il est également possible d’interdire l’accès au site à une certaine adresse IP via le fichier virtual host de Apache :

$ sudo nano /etc/apache2/sites-available/000-default.conf

À l’intérieur de la directive , il faut ajouter (syntaxe Apache 2.4) :

<RequireAll>
    Require all granted
    Require not ip 191.96.249.54
</RequireAll>

Une autre solution consiste à interdire l’accès au fichier xmlrpc.php :

<Files "xmlrpc.php">
    Require all denied
</Files>

Cependant, ces deux méthodes n’empêcheront pas l’ouverture de connexion et l’utilisation de ressources qui en découle.

Conclusion

Parce qu’il s’agit ici d’une attaque automatisée très commune, peu sophistiquée et non distribuée, le problème a pu rapidement être détecté et résolu. Dans le cas d’une attaque plus complexe, où les requêtes proviendraient de plusieurs adresses IP par exemple, il est indispensable d’automatiser la détection et le blocage de l’attaque.

Pour cela, il est possible de créer des règles personnalisées dans fail2ban afin de mieux protéger un serveur contre ce type de menace.

Le serveur utilisé pour la démonstration fonctionne avec Ubuntu 14.04.5 LTS, Apache 2.4 et UFW 0.34~rc-0ubuntu2

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
Créer des règles personnalisées dans Fail2Ban

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

Fail2ban est un logiciel fonctionnant en arrière plan et qui…

Type your search keyword, and press enter to search