BLOG

L'attaque que vous ne pouvez pas arrêter dans votre application

Miniature de Lori MacVittie
Lori MacVittie
Publié le 09 novembre 2015

Une grande variété d’attaques basées sur HTTP peuvent (et doivent) être empêchées dans votre application. Le Top 10 de l’OWASP est un excellent exemple de techniques d’attaque qui sont à la fois détectables et évitables à partir de n’importe quelle application. Une multitude d’outils, notamment des analyses statiques et dynamiques ainsi que des tests de pénétration, peuvent garantir que ces vulnérabilités ne passent pas en production. À condition, bien sûr, que ces tests de sécurité soient déplacés vers la gauche du processus CI/CD plutôt que d'être laissés comme l'étape finale avant de basculer le commutateur (ou les bits, en quelque sorte) qui le rend accessible aux utilisateurs. 

Même si vous avez éliminé toutes les vulnérabilités potentielles trouvées dans le développement, les applications sont toujours en danger. C’est parce que certaines attaques ne peuvent pas – et par ne peuvent pas, je veux vraiment dire ne peuvent pas – être détectées par l’application. En fait, au moment où l’attaque atteint l’application, il est déjà trop tard.

carburant vide

Bien sûr, je parle des attaques DDoS au niveau de la couche applicative (HTTP). Vous savez, les vampires qui exploitent le protocole HTTP lui-même pour aspirer jusqu'à la dernière goutte de calcul et de mémoire disponible d'une application afin de la rendre inutile pour les utilisateurs légitimes.

Il existe essentiellement deux types d'attaques DDOS HTTP : les attaques rapides et les attaques lentes, les attaques par inondation et les attaques par drainage.

L'attaque du déluge

Une attaque HTTP DDoS par inondation tire parti du fait que les applications doivent accepter les requêtes HTTP et y répondre. C’est un peu leur rôle, n’est-ce pas ? Elles le font donc. Et ce, peu importe la vitesse d’arrivée des requêtes. Même si les requêtes arrivent si vite que le serveur épuise ses ressources en minutes — voire en secondes — il essaie de répondre. Chaque application (et en réalité chaque appareil, service, système, etc.) a une limite maximale au nombre de connexions TCP qu’elle peut maintenir ouvertes simultanément avant de ne plus pouvoir en accepter. Lorsqu’elle atteint cette limite, elle ignore simplement toutes les requêtes suivantes. Vous rencontrez cela avec le message simple « Tentative de connexion… » lorsque votre navigateur ou application attend que le délai d’attente prévu par le système soit écoulé, puis déplore de ne pas pouvoir établir la connexion.

Ce type d’attaque survient tellement rapidement (d’où l’image de la « crue éclair ») que les systèmes n’arrivent pas à s’adapter à la demande. Même l’auto-scaling ne suffit pas ici, car il faut plus de temps pour préparer et lancer une nouvelle instance de l’application que l’attaque n’en prend pour épuiser toutes les ressources des instances existantes.

L'attaque du drain

L’attaque inverse, appelée attaque par drainage, atteint le même objectif en forçant l’application à maintenir une connexion ouverte plus longtemps que nécessaire. Elle y parvient en simulant une connexion bas débit ; elle libère quelques gouttes de données par seconde au lieu de transmettre à la vitesse réelle que l’application peut recevoir. Cela prolonge la durée des connexions, et en multipliant ces connexions, vous vous retrouvez dans la même situation qu’avec une attaque par inondation : l’épuisement des ressources.

Aucune de ces attaques n’est détectable depuis une application. Pourquoi le seraient-ils ? Pour l'application, ces requêtes sont toutes légitimes ; ce sont toutes des requêtes HTTP bien formées pour des données auxquelles elle répond probablement des milliers de fois par jour. Il n’y a aucun indicateur dans les en-têtes HTTP ou la charge utile qui indique la nature néfaste des requêtes. L’application est complètement et totalement aveugle aux intentions malveillantes derrière ces requêtes car elle n’a aucune visibilité sur le réseau ou sur l’environnement plus large – en particulier la table de session du serveur qui conserve la liste principale de toutes les connexions ouvertes. Je vous épargnerai les détails techniques et les conférences sur les threads, les processus et la volatilité des données dans les environnements multithreads et je m'en tiendrai simplement au « manque de visibilité sur le traitement des autres requêtes ».

Il suffit de dire que l’application elle-même n’a aucun moyen de déterminer si une requête donnée fait partie ou non d’une attaque plus vaste (inondation) ou si son comportement est incompatible avec ses capacités connues (drainage).

Le proxy à la rescousse

ail_vampire

Ce qui a une visibilité sur les deux est le proxy situé en amont (devant) l'application. C'est parce que le proxy effectue probablement un équilibrage de charge et doit donc prêter attention au nombre de requêtes actuellement en cours de traitement ainsi qu'à celles qui arrivent, car il doit les envoyer à l'une des applications du cluster (ou du pool, si vous préférez).

Il doit aussi savoir où envoyer la réponse, ce qui signifie connaître le client et sa connexion réseau (seule l’adresse IP du client est en général transmise à l’application, rien d’autre). Contrairement à l’application, il bénéficie d’une visibilité suffisante pour détecter et bloquer les attaques par saturation et par vidage avant qu’elles ne plongent leurs dents vampiriques dans les ressources de l’application.

C’est pourquoi les services basés sur un proxy comme un WAF (Web Application Firewall) ou même un équilibreur de charge avancé sont des acteurs essentiels dans les stratégies de sécurité des applications d’aujourd’hui. Parce qu’ils ont la visibilité et les moyens de détecter le comportement anormal indicateur d’une attaque – et de le repousser comme l’ail et un vampire.

Et parce que ces services traditionnellement « réseau » doivent nécessairement faire partie de l’architecture de l’application, il semble logique qu’une approche DevOps ait tendance à étendre ses ailes et à inclure davantage les services qui gravitent naturellement vers l’application en premier lieu , comme la sécurité et l’évolutivité des applications (équilibrage de charge).

Les applications ne peuvent pas arrêter toutes les attaques, en particulier celles qui nécessitent un niveau de visibilité qui ne leur est tout simplement pas accessible. Cependant, travailler de concert avec des services adaptés aux applications, tels que la sécurité des applications Web et l'équilibrage de charge, peut fournir les moyens par lesquels un ensemble plus complet d'attaques peut être détecté et repoussé afin de garantir moins de pannes et de violations.