Technical Article, DevOps

DevSecOps, ou comment placer la sécurité dans une approche DevOps ?

La sécurité fait partie intégrante des problématiques de conception et de maintenance d’une application logicielle. Le passage en DevOps est l’occasion de faire un shift left, c’est à dire de considérer les problématiques de sécurité au plus tôt dans le cycle de développement. Petit tour d’horizon des bonnes pratiques et des étapes à suivre  en DevSecOps.

 

L’analyse de l’impact sur le business

Un Business Impact Analysis doit idéalement être effectué au début de chaque projet. Il s’agit d’évaluer l’impact qu’aurait une compromission sur le business, et ainsi de mieux impliquer les départements concernés en chiffrant les éventuelles conséquences directes (comme la rupture de production) et indirectes (comme l’atteinte réputationnelle). C’est une étape simple et rapide qui permet de s’assurer que les équipes de sécurité, de développement et le business sont alignés sur les menaces et leurs conséquences.

Même dans une approche DevOps, cette première analyse de sécurité devrait être initiée dès le démarrage du projet. Pas besoin de maintenir une encyclopédie, un simple tableau peut suffire pour aligner les différents protagonistes.

 

Définition des scénarios d’abus

Par essence, la validation des scénarios d’utilisation traditionnels  (Use Cases) doit passer par le développement de tests unitaires. Par exemple, un point d’accès restreint aux administrateurs ne peut être considéré comme développé qu’une fois qu’on a vérifié que seuls les administrateurs sont autorisés à y accéder.

Les scénarios d’abus (Abuse Cases) vont au-delà des Use Cases habituels. Ils se focalisent sur les scénarios de malversation des fonctionnalités et sur leurs éventuelles conséquences. Il s’agit par exemple de songer à un attaquant :

  • Qui enverrait des données volumineuses ou contenant des caractères spéciaux, et donc aux possibles répercussions d’un dépassement de zone mémoire (i.e. buffer overflow) ou d’injections (e.g. SQLi, XXE, etc).
  • Qui tenterait d’accéder à des fonctionnalités ou des objets auxquels il n’est pas censé avoir droit.

Cette étape permet d’identifier efficacement bien des failles de sécurité mais requiert un investissement humain non négligeable, car chaque scénario de malversation devra faire l’objet d’exigences de sécurité spécifiques et de tests d’approbation.

Dans une approche DevOps, où les fonctionnalités de l’application peuvent être amenées à changer rapidement au fur et à mesure de l’identification des besoins des utilisateurs, ces scénarios sont réajustés durant le développement, en même temps que la formalisation des scénarios d’utilisation nominaux. Au même titre que les Use Cases traditionnels, les Abuses Cases donneront par la suite naissance à des tests automatisés.

 

Les exigences de sécurité

Il s’agit de définir les Security Requirements (en termes de confidentialité, d’intégrité, de disponibilité, d’authentification, d’autorisation et d’auditabilité) pour l’application cible au sens large, puis de descendre peu à peu au niveau de ses fonctions, en abordant par exemple la couche d’authentification ou le chiffrement des données sur le back-end.

En DevOps, une des règles d’or est de limiter autant que possible le formalisme inutile. Ces exigences de sécurité peuvent donc prendre la forme d’un simple document texte élaboré en concertation avec un consultant sécurité, et partagé par exemple sur le dépôt du projet.  On pourra l’actualiser au fur et à mesure de l’évolution de l’architecture.

 

L’analyse de risques architecturale

L’Architectural Risk Analysis permet d’évaluer le niveau de sécurité de la solution en analysant son design, et en corrélant ses faiblesses aux impacts business identifiés. Cela consiste à décomposer les processus, les flux de données, les zones de stockage et les limites de confiance, et à les confronter aux scénarios d’attaques usuels afin d’évaluer leur probabilité d’occurrence.

On peut par exemple utiliser la méthodologie STRIDE (pour identifier les menaces) conjointement avec DREA(D) (pour estimer leur niveau de risque), ou utiliser un framework plus poussé comme OCTAVE Allegro. Il s’agit d’une étape assez laborieuse mais primordiale, car plus de la moitié des problèmes de sécurité sont aujourd’hui la résultante de problèmes d’architecture.

En DevOps, l’architecture peut évoluer drastiquement au gré de la formalisation des besoins. À ce titre, cette analyse peut être faite sous forme d’ateliers réguliers avec un consultant en sécurité. Ces ateliers peuvent influencer les choix d’architecture, et faire évoluer les exigences de sécurité.

 

Les tests de sécurité automatisés

Il est maintenant possible de formaliser les différents tests de sécurité automatisés, qui seront généralement implémentés par l’équipe qualité. Ils permettront d’éprouver les fonctionnalités en émulant le comportement d’un attaquant sur la base des spécifications fonctionnelles, des exigences de sécurité, et des scénarios d’abus.

C’est à partir de ce stade que les différentes équipes de développement pourront réellement écrire du code sans pour autant risquer d’introduire des vulnérabilités majeures pour l’entreprise.

 

La revue de code automatisée

Cette étape de Static Code Analysis est vitale. Elle permet de minimiser l’introduction de vulnérabilités au niveau du code. Si les ressources financières et/ou humaines ne permettent d’implémenter qu’une seule des bonnes pratiques recommandées, alors c’est par celle-ci qu’il faut commencer.

Néanmoins la configuration des outils est généralement complexe et il peut s’avérer difficile de réduire les faux-positifs, et donc de conserver la confiance des développeurs. Par ailleurs ce processus requiert des connaissances très poussées en termes de développement, et nécessite donc une réelle collaboration entre les développeurs et l’équipe sécurité.

 

Les tests d’intrusion applicatifs

Contrairement à un test d’intrusion traditionnel, qui consiste généralement à tenter de s’introduire dans le système depuis l’extérieur, ces simulations d’attaque ne ciblent que l’application concernée. On place ici l’application au cœur de l’analyse en s’appuyant sur le travail effectué en amont, comme l’analyse de risques architecturale.

Il s’agit d’un processus manuel réalisé indépendamment de l’équipe produit. Il est effectué par l’équipe sécurité ou un mandataire externe, généralement à chaque changement majeur.

 

Sécurisation de l’environnement

Il convient à ce stade de penser à la sécurité en termes opérationnels, et notamment au déploiement et au maintien de l’application.

Cela passe par exemple par :

  • L’identification des composants tiers et leur maintien à jour.
  • L’analyse périodique des vulnérabilités :
    • Des systèmes d’exploitation (e.g. avec MBSA ou Nessus).
    • Des conteneurs (e.g. avec Docker EE ou Tenable.io).
    • Des services additionnels comme Tomcat ou MySQL  (e.g. avec OpenVAS, LanGuard ou Nessus).
  • La vérification de conformité des configurations applicatives, comme SSH ou Tomcat, en adhérent à certains standards de sécurité comme ceux du NIST ou du CIS  (e.g. avec OpenSCAP).
  • Un cloisonnement des environnements entre applications, afin de limiter les effets d’une intrusion. Ce cloisonnement peut prendre la forme de machines virtuelles ou de conteneurs différents répartis sur des VLANs ou des réseaux segmentés.
  • Une bonne configuration des pare-feux réseaux et applicatifs de manière à garantir suffisamment de flexibilité au moment du déploiement tout en limitant l’impact d’une intrusion sur l’une des machines de l’infrastructure.
  • La limitation du choix des composants, notamment des OS et des images.  Il s’agit d’une réelle amélioration de la sécurité, mais au prix d’une charge de travail importante pour l’équipe sécurité et d’une perte de productivité conséquente.
  • La gestion des ressources externes, notamment en termes de suivi des dépendances et de contrôle d’intégralité des librairies tierces.
  • Effectuer périodiquement des tests d’intrusion traditionnels. Ils permettent d’obtenir une vue d’ensemble du niveau de sécurité et prennent notamment en considération la topologie réseau, les protocoles de communication et les dispositifs de filtrage comme les firewalls et les WAF (Web Application Firewall).

 

Logging et monitoring

Le logging et le monitoring des événements sont vitaux en DevOps comme en sécurité. Il doivent permettre de détecter au plus tôt les intrusions et actions anormales, mais également de corriger les effets d’une attaque. La journalisation est primordiale et il convient de considérer les informations relatives à l’utilisation des données (comme le nombre et la taille des transactions) en plus des événements usuels.

L’utilisation d’un agrégateur de logs (comme WEF) et d’un outil de monitoring (comme Splunk ou la stack ELK) est vivement recommandée pour obtenir une vue d’ensemble de l’état du parc applicatif.

 

Sensibilisation, éducation et formation

Parallèlement à toutes ces bonnes pratiques qui interviennent séquentiellement durant le cycle de développement, il est importer de sensibiliser les équipes par le biais de l’AET (Awareness, Education and Training). La formation aux principes de base du Secure Coding reste en effet un excellent moyen de prévention, notamment via le Developer Guide et le Top 10 de l’OWASP.

Une attention particulière devrait être donnée à la validation des entrées, à l’encodage des sorties, à l’authentification, à l’autorisation, à la gestion des sessions, aux contrôles d’accès, aux bonnes pratiques cryptographiques, à la gestion des erreurs et à la journalisation des événements. Il est également judicieux de prendre le temps d’aborder les problématiques de la désérialisation et de la compromission de librairies tierces, lesquelles sont aujourd’hui devenues un risque non négligeable pour les développements internes, et donc d’aborder les thématiques de Sub Resources Integrity et de gestion des dépendances.

 

Conclusion

Implémenter l’ensemble de ces bonnes pratiques n’est pas simple et nécessite du temps ainsi que des ressources spécialisées. Il n’est donc pas rare de devoir faire des choix, ne serait-ce qu’en terme de priorisation. Il est dans ce cas vivement recommandé de commencer par implémenter les processus qui permettront de supprimer un maximum de vulnérabilités.

En termes de sécurité applicative, les mesures les plus efficaces sont à prioriser dans cet ordre  :

  • De procéder à tests unitaires au niveau de l’équipe de développement, afin d’obtenir un premier niveau de vérification que les différentes fonctionnalités ne sont bien accessibles que dans le contexte initialement prévu [par exemple en testant l’accès à une API après suppression du token associé].
  • L’analyse automatisée du code source (avec une solution comme Checkmarx ou Fortify).
  • L’analyse itérative des risques relatifs à l’architecture.
  • Des tests d’intrusion applicatifs, en mettant l’application au coeur de l’analyse.
  • Des tests automatisés de sécurité au niveau de l’équipe qualité.
  • L’extension des Uses Cases conventionnels aux Abuses Cases.

Au niveau de la sécurité opérationnelle, il convient de suivre les bonnes pratiques du NIST et de prioriser également les mesures les plus efficaces dans cet ordre :

  • Filtrer les flux à l’aide de pare-feux réseaux et applicatifs. Il est important de ne pas exposer inutilement de services qui pourraient être utilisés à mauvais escient (comme les ports TCP 2375 et 2376 qui permettent d’accéder aux APIs de gestion de Docker).
  • Implémenter des scans automatisés de vulnérabilité.
  • Remonter les journaux d’événements sur un serveur centralisé.
  • Maintenir à jour l’inventaire du matériel et des applications, en veillant particulièrement à savoir en tout temps ce qui est exposé sur Internet.

 

SmartWave est à même de délivrer des solutions qui répondent à tous ces besoins et dispense des formations d’une journée sur le développement sécurisé. Nous proposons également des prestations de conseil périodiques afin d’accompagner nos clients dans leurs projets sécurité. Contactez-nous !