10. Attaques DOS

DOS est le sigle pour le terme anglais « Denial Of Service », dénie de service en français. C'est une attaque dans laquelle un utilisateur utilise une ressource partagée jusqu'au point qu'elle ne soit plus disponible pour les autres utilisateurs. Les attaques DOS compromettent donc la disponibilité d'une ressource, celle ci pouvant être le processeur, la mémoire vive ou le swap, une imprimante, l'espace disque disponible, les processus systèmes, une connexion réseau, ou plus généralement le temps d'un administrateur système. Ces attaques ont pour particularité d'être dures à tracer et à prévenir.


On différencie deux types d'attaques DOS, les attaques destructives et les attaques par surcharge. Les attaques destructives ont pour but d'endommager ou de détruire des ressources de manière à ce qu'elles ne soient plus utilisables (par exemple, provoquer la défaillance physique d'un disque dur, ou faire s'écrouler un système entier). Ce type d'attaque requiert souvent un accès à la machine, mais peut aussi intervenir par le réseau. L'autre type consiste à épuiser une ressource ou bien à faire monter la charge d'un service ou d'un système entier, de manière à en perturber ou arrêter le fonctionnement. Ce deuxième type d'attaque est beaucoup plus courant, il consiste par exemple simplement à faire en sorte qu'une partition soit remplie, et qu'il soit impossible de créer de nouveaux fichier sur celle ci, ou à bombarder un service réseau avec tellement de paquets que le service devienne injoignable ou que la bande passante disponible soit réduite à néant.


Note : Ces attaques DOS peuvent être volontaires (attaque délibérée), ou involontaires (mauvaise configuration d'un service, script mal conçu, utilisateur débutant commettant une erreur, événement non prévu mais normal).


La plupart des systèmes Gnu/Linux possèdent des mécanismes systèmes permettant de limiter l'accès à certaines ressources. PAM, décrit dans le deuxième chapitre de ce document, permet par exemple de limiter les ressources par utilisateur, par une simple configuration du fichier /etc/security/limits.conf, dont voilà un exemple :


# limits.conf
# On empêche la création de core (snapshot du système en cas de crash d'un programme), en limitant leur taille à 0
*   soft    core    0
# On limite la taille de la mémoire résidente utilisable par une session utilisateur
*   soft    rss     16384
# On limite le nombre de processus par session à 20 pour tout le monde
*   soft    nproc   20
# Sauf pour les membres du groupe mysql qui peuvent en créer 50
@mysql      soft    nproc   50
# On empêche plus de 4 session simultanées pour l'utilisateur john
john        soft    maxlogins       4


La commande « ulimit » permet également de limiter certaines ressources systèmes, mais ne marche que pour la session en cours, et est donc peut intéressante à l'échelle du système, pour modifier les valeurs par défaut, il faut aller toucher aux sources du noyau, ces valeurs se trouvant être configurées en dur.


Une des attaques les plus simples consiste à créer un processus qui va lui même « forker » (créer des processus fils), et ce en boucle. Par exemple, le code C suivant peut paralyser une machine en quelques instants :


main()
{
    while (1) fork();
}


On pourra alors utiliser le script « killall », disponible sur les bonnes distributions, capable d'envoyer le signal d'arrêt à un ensemble de processus portant le même nom (ce nom doit être passé en paramètre), ou « slay », qui va tuer tous les processus appartenant à l'utilisateur passé en paramètre. Préventivement, on peut configurer le noyau Linux pour que le nombre total de processus ne puisse en aucun cas dépasser un certain nombre.


En cas d'atteinte du nombre maximum de processus utilisateur sur la machine, il est impossible de créer de nouveaux processus, donc de lancer la commander kill, slay, ou killall. Si on a un shell d'ouvert sur la machine, il reste une chance de s'en sortir proprement, en utilisant la commande intégrée à certains shell, « exec », qui va exécuter la commande passée en paramètre sans créer de nouveau processus, mais en utilisant le processus du shell sur lequel on se trouve.


Un numéro identifiant de processus pourra aussi être utile en cas de problème, c'est « -1 », qui concerne tous les processus utilisateurs, sans les processus systèmes (donc tous les processus dont l'identifiant système est supérieur à 1). Un autre numéro particulier est 0, il désigne tous les processus dépendant du shell en cours. Pour plus d'information sur les signaux système disponibles sous Unix, voir l'annexe sur les signaux système.


En cas de surcharge CPU, provoquant une latence ne permettant quasiment rien, on pourra affecter une priorité maximale à sa session pour pouvoir être plus libre d'intervenir (cela affecte la session dans laquelle on exécute cette commande) :


# renice -19 $$


Pour l'espace disponible sur les partitions, on pourra utiliser l'utilitaire de quota, pour placer des quotas par utilisateur sur des partitions sensibles (/var, /temp, /log, /home par exemple).


On peut adapter le morceau de code C ci-dessus pour obtenir un programme dont le but serait de consummer tout l'espace mémoire disponible, jusqu'à ce qu'il n'y ai en plus pour les autres programmes.


main()
{
    while (1)
    {
        malloc(128*1024*1024); /* on alloue un bloc de 128 mégaoctets de memoire */
        fork();
    }
}


En cas d'usage maximale de la mémoire et du swap, on pourra créer un fichier de swap temporaire, pour avoir de la mémoire Swap disponible, et donc pouvoir par la suite agir pour libérer de la mémoire (attention à créer ce swap sur une partition disposant de l'un espace suffisant):


# dd if=/dev/zero of=/tmp/swaptemp bs=1048576 count=500
# mkswap /tmp/swaptemp
# swapon /tmp/swaptemp


La partition de données temporaires peut être un goulot d'étranglement important, et il existe des outils d'administrations fournis avec les distributions Gnu/Linux permettant de faire le ménage parmi les fichiers trop vieux, ce qui est généralement une bonne idée. De manière similaire, un DOS sur la partition de journaux peut faire beaucoup de dégats, il convient par conséquent de surveiller cet espace et e configurer proprement l'utilitaire logrotate, qui permet de compresser les fichiers de logs, et de les effacer après un certain temps (je vous propose de vous rapporter au manuel de cette commande pour plus d'information).


Les attaques DOS réseaux ou plutôt quelques moyens de les prévenir sont décrites dans le chapitre réseau de ce document.



9. Journalisation, audit, et surveillance
Sommaire
11. Sécurité physique