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 DDoS HTTP basée sur l'inondation utilise le fait que les applications sont censées accepter les requêtes HTTP et y répondre. C'est un peu leur truc, n'est-ce pas ? C'est ce qu'ils font. Et ils le font quelle que soit la rapidité avec laquelle ces demandes arrivent. Même si les requêtes arrivent à un rythme qui épuise les ressources disponibles pour ce serveur en quelques minutes – ou secondes –, il essaie de répondre. Voyez, chaque application (en fait chaque appareil, service, système, etc…) a une limite supérieure au nombre de connexions TCP qu’elle peut maintenir ouvertes à tout moment avant de ne plus pouvoir en ouvrir. Lorsque cette limite supérieure est atteinte, toutes les demandes ultérieures sont simplement ignorées. Les utilisateurs en font l'expérience avec le statut anodin « Tentative de connexion… » pendant que leur navigateur ou leur application attend que le délai spécifié par le système soit écoulé, puis s'excuse de ne pas pouvoir se connecter.

Ce type d’attaque peut survenir si rapidement (d’où l’analogie d’une « inondation éclair ») qu’elle dépasse la capacité des systèmes à évoluer pour répondre à la demande. Même la mise à l’échelle automatique ne peut pas aider dans ce scénario, car le temps nécessaire pour provisionner et lancer une nouvelle instance de l’application est supérieur au temps nécessaire à l’attaque pour priver les instances existantes de toutes leurs ressources.

L'attaque du drain

L’inverse – une attaque de drainage – accomplit la même tâche mais le fait en forçant l’application à maintenir une connexion ouverte plus longtemps que nécessaire. Il y parvient en prétendant être connecté à un réseau commuté, en faisant sortir quelques gouttes de données de l’application par seconde plutôt qu’en suivant la vitesse à laquelle il est réellement capable de les recevoir. Cela signifie que les connexions durent plus longtemps, et si vous faites cela avec suffisamment de connexions, vous vous retrouvez essentiellement dans la même situation que l'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 également savoir où envoyer la réponse, afin de connaître le client et sa connexion réseau (seule l'adresse IP du client est généralement envoyée à l'application, rien de plus ). Contrairement à l'application, il dispose de la visibilité nécessaire pour détecter les attaques par inondation et par drainage – et les arrêter avant qu'elles ne puissent enfoncer 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.