logo

 

Le Security By Design dans les développements logiciels

Le Security By Design dans les développements logiciels

Cet article a été à l’origine publié dans le magazine Programmez! n°234.

Le concept du Security by Design, dans le développement applicatif a pour but d’intégrer la sécurité dès la phase de conception en évaluant le risque et les contrôles nécessaires à mettre en place en anticipant aussi la maintenance, comme l’obsolescence de composants et de stacks logiciels ou simplement en prévoyant la fin de vie d’une application.

Par analogie à l’aéronautique, où la sécurité d’un système ou d’une organisation dépend directement des risques auxquels ils seront confrontés en vol, le développement sécurisé d’une application s’applique avec le même objectif ; l’amélioration continue des processus pour répondre aux exigences liées à son usage.

En d’autres termes, la sécurité dès la conception, dépendra :

  • Des fonctionnalités business de l’application et des données traitées, personnelles ou critiques pour l’entreprise en rejoignant le Privacy By Design.
  • De l’implication de tous les acteurs du projet, pas seulement les développeurs qui portent souvent l’unique responsabilité du code dans cet enjeu mais bien, du business en passant par les équipes transverses comme l’Architecture et les Opérations.

On parle donc ici de sécurité pilotée par le risque afin d’adapter au mieux les efforts de chacun en fonction des contraintes métier (time-to-market, engagement client, etc.), des standards d’architecture, de sécurité et opérationnels d’une entreprise.

Principes généraux

Le Security by Design, au même titre que le DevSecOps, est l’intégration du risque et des éléments de sécurité pendant la phase de conception et aussi durant l’intégralité du cycle de vie applicatif :

  • Conception : qualification du risque, adaptions des contrôles, intégration au SI et aux pipelines CI/CD
  • Vie courante : monitoring, opérations de maintenance comme la mise à jour de composants et stacks d’exécution devenus obsolètes et/ou vulnérables, mise à jour des politiques de sécurité
  • Désengagement : suppression des données comme précisé par la GDPR, des ressources techniques, des services et comptes associés

Les principaux éléments que nous allons décrire sont les suivants :

  • La définition des assets et des éléments de sécurité inhérents
  • La compréhension du risque informatique et de la menace associée
  • La classification de l’applicatif en fonction des quatre piliers de la Sécurité applicative
  • L’importance de l’Architecture fonctionnelle et technique d’entreprise
  • Les principes de base de la sécurité et des exemples

Enfin, l’aspect préventif est prédominant car les coûts de remédiation en production ne seront évidemment pas les mêmes qu’en phase de conception et/ou de développement itératif. La préparation à un incident de sécurité applicatif par exemple doit pouvoir permettre d’en réduire les impacts sur l’entreprise (image, pertes financières, …).

Clarification des ressources numériques

La première étape est de qualifier les données à protéger pour en adapter les contrôles nécessaires.

Nous abordons ici le besoin métier de protéger la donnée en fonction du risque business en termes de réputation, de vol, de fraude, de falsification, etc.

En termes de contrôles, la question se basera par exemple sur le besoin d’auditer l’application car soumise à une régulation ou simplement à une analyse de surface à l’aide d’un outil dynamique de sécurité en plus des habituels tests unitaires et d’intégration qui viendront compléter les contrôles métier applicatifs.

Cette étape permet donc de définir les ressources avec la topologie d’application, car l’effort tant humain que financier sera différent entre un site institutionnel et des applications bancaires ou embarquées d’un point de vue sécurité mais aussi en termes de développement pur.

Comprendre les attaquants

Cette réflexion est primordiale dans le Security By Design, connaitre son ennemi est une base de l’Art de la Guerre (Sun Tzu) mais également un atout pour les développeurs afin d’adapter les contrôles et être accompagnés par les équipes transverses.

Les profils d’attaquants sont nombreux, mais en voici une liste volontairement incomplète :

  • Personnel interne à l’entreprise, voire programmeurs, mécontents ou sur le départ
  • Organisations criminelles mal intentionnées
  • Cybercriminels motivés
  • Concurrence pour espionnage industriel par exemple
  • Apprentis utilisant des scripts trouvés sur Internet

Et de même pour les attaques :

  • Vol de données sensibles (personnelles, bancaires, santé)
  • Virus, chevaux de Troie sur le système
  • Fraudes
  • Usurpation d’identités
  • Atteinte à l’image

Bien qu’il soit difficile de connaitre les motivations réelles des attaquants et comme les techniques évoluent très vite, le Security By Design doit permettre de réduire le risque sur une échelle de temps convenable.

En retour d’expérience, quelques questions utiles à se poser :

  • Que pourrait-on faire en contournant la logique applicative ?
  • Quelles sont les dernières attaques que mon entreprise ait subies ?
  • Mon application peut-elle être utilisée pour récupérer des données afin d’en attaquer d’autres ?
  • Quelle sera sa durée de vie ? Et son exposition médiatique en interne ou en externe ?
  • Quels sont les composants embarqués ou d’exécution qui arriveront en fin de support d’ici les deux prochaines années ?

Pour information, de nombreuses formations permettent d’appréhender les bases du « ethical hacking » afin de pouvoir intuiter les vecteurs d’attaques et les exploitations potentielles, mais surtout apprendre à tester ses propres développements.

Piliers de la sécurité applicatives

Ils sont au nombre de quatre :

  • Confidentialité : N’autoriser que l’accès aux données auxquelles l’utilisateur a droit
  • Intégrité : S’assurer que les données ne soient pas falsifiées ou manipulées par des utilisateurs non autorisés
  • Disponibilité : Permettre l’accès aux systèmes et aux données pour les utilisateurs autorisés en fonction de leurs besoins
  • Traçabilité : S’assure que les journaux d’audit et de monitoring sont bien implémentés et protégés surtout pour les éléments stratégiques

Ces piliers serviront ensuite à la construction de contrôles robustes correspondant aux principes de sécurité ci-après et adaptés aux fonctions applicatives et leurs criticités.

Également, ils permettent un premier niveau de classification d’une application auquel peut s’ajouter par exemple l’exposition de l’application sur Internet comme critère.

Architecture applicative sécurisée

La conception actuelle d’applications doit désormais, en plus du besoin initial en termes de fonctions et d’intégration au SI, prendre en compte le risque et ainsi adapter le projet.

L’aspect dimensionnement au cas d’utilisation nominal ne suffit plus et les cas extrêmes d’attaques doivent être pris en compte (Brute force, bots, injections, déni de service, etc.) au démarrage du projet.

Une architecture de sécurité d’une application pourrait se décompenser en :

  • Une couche logicielle où la confidentialité, l’intégrité et l’accès aux données aux bons utilisateurs est maitrisée par différents contrôles
  • Une infrastructure permettant des contrôles spécifiques à l’application et non un ensemble de produits ne couvrant pas le risque business sous-jacent mais uniquement le périmétrique
  • Un aspect gouvernance, où l’application réutilise des patterns d’architecture comme le découplage, les API, les stacks techniques connues et maitrisées dans leur exploitation etc.

Il est possible par exemple de s’aider de méthodologies Open Source qui permettent de

  • Modéliser la menace selon les exploitations potentielles : STRIDE
  • Quantifier le risque d’une vulnérabilité : DREAD

Plus d’informations sur STRIDE/ DREAD : https://wiki.openstack.org/wiki/Security/OSSA-Metrics

Par conséquent, le concept de Security by Design doit permettre d’analyser la sécurité de chaque fonction pendant la phase de conception une fois le modèle métier établi.

En termes d’exemple de fonctions, le schéma ci-dessous permet d’appréhender les différents besoins de sécurité d’une application trois tiers :

Chaque fonction, orientée sécurité dans ce schéma devrait une susciter une question liée au risque métier.

Par ailleurs, la fonction est aussi bien une fonction métier qu’une fonction purement technique, ce qui doit permettre de les appréhender de la même manière.

Point important, les pratiques mises en place pour atténuer le risque doivent être également décrites et de facto l’architecture applicative sécurisée devra évoluer durant le cycle de vie complet de l’application jusqu’à son abandon.

Principes de Sécurité

Ces principes sont la base du développement sécurisé et permettent de comprendre facilement les exploitations potentielles et surtout vulgariser des bonnes pratiques dans toujours le but de réduire le risque global.

Minimiser la surface d’attaque

Chaque fonction est par définition un risque de sécurité en plus pour l’application dans son ensemble, donc l’exposition d’une fonction, d’un service ou d’une donnée doit être réalisée au juste nécessaire pour remplir son besoin initial.

Par exemple :

  • Une fonction de recherche authentifiée peut être un risque d’injection SQL ou de Cross Site Scripting donc elle se doit d’être validée côté serveur afin de réduire ces risques.
  • L’interface d’administration doit-elle être accessible depuis Internet ? Si oui, est-il possible de mettre en place un filtrage IP ou une authentification forte ?
  • Les ports ouverts sur ma machine sont-ils tous utiles au bon fonctionnement applicatif ? Si non pourquoi ne pas les fermer pour éviter tout risque.

Établir des valeurs sécurisées par défaut

Chaque fonction doit apporter la meilleure expérience utilisateur possible pour un besoin dans un contexte de sécurité standard. Ce contexte doit être défini soit par l’entreprise de manière globale, soit par le métier, l’équipe de développement pourra en proposer à défaut mais ne devra pas en porter la responsabilité.

Par exemple, la fonction de modification de mot de passe se base sur une politique de caractères, une durée de vie, etc. Dans certains cas, le business peut demander à modifier cela pour ces utilisateurs, néanmoins cela devra être validé et par conséquent portera la responsabilité du risque introduit.

Le principe du moindre privilège

Chaque utilisateur doit posséder les droits nécessaires pour réaliser ses processus métier dans l’application et ce de manière minimale. Cela s’applique aussi bien à l’accès aux données et qu’aux ressources applicatives et matérielles.

La granularité des droits et l’utilisation de Frameworks peuvent permettre de faciliter la gestion et l’implémentation de ce principe.

Par exemple, lorsque l’on créé un compte dans le cloud Amazon, il n’a aucun droit d’accès à aucun service permettant ainsi de les attribuer au strict nécessaire par la suite.

Le principe de défense en profondeur

Un contrôle peut parfois suffire pour une fonction, néanmoins le point est le durcissement en rajoutant des contrôles selon différents vecteurs potentiels d’attaque. L’objectif est donc de réduire les risques de manière globale et de limiter l’exploitation de vulnérabilités graves ou critiques au maximum.

En développement sécurisé, cela peut se décrire par exemple par la « Ne jamais faire confiance aux entrées utilisateur » et ainsi avoir plusieurs niveaux de validations dans chaque fonction.

Un autre exemple, est de faire valider l’autorisation d’un utilisateur à une fonction à chaque appel, de tracer les accès et actions en fonction du risque tout en étant capable de bloquer temporairement ou non les appels successifs en cas de problème ou de suspicion d’attaque.

Échouer en toute sécurité

Dans les fonctions transactionnelles, la gestion des erreurs est primordiale afin de ne pas fournir de la connaissance à l’attaquant sur la sécurité en place ou les workflows de l’application.

Par exemple, si une personne malveillante essaie d’accéder à une fonction de manière non nominale, il peut obtenir des codes d’erreurs lui permettant de comprendre la logique de l’application ou pire des stacks d’exceptions lui permettant d’identifier les technologies utilisées et ainsi continuer à peaufiner son attaque future.

Ne faites pas confiance aux services

L’utilisation de services externes est devenue légitimement une pratique courante et requiert une attention particulière.

Les partenaires proposant ces services peuvent avoir des politiques de sécurité très différentes et des niveaux de maturité en termes de développement et de sécurité bien différents.

La confiance d’un partenaire ne doit jamais être implicite et chaque service doit être traité indépendamment. Un contrat de service est déjà un bon point de départ mais n’assure pas que les données partenaire ne soient pas corrompues un jour. Également, ce contrat doit permettre d’expliciter ses exigences d’interconnexions et pouvoir permettre des analyses conjointes en cas d’incidents de sécurité.

Par exemple, il est recommandé de prévoir une validation des données avant de les afficher. Demander à avoir un jeton renouvelable sur une durée décente pour utiliser un service distant est aussi une bonne pratique. Cela permettra de s’assurer qu’en cas de vol de ce jeton, le fenêtre d’action de l’attaquant soit la plus limitée possible.

Séparation des tâches

Elle a pour but d’éviter les fraudes et les contournements de processus en interne et se base sur la notion de confiance sur la validation de la bonne réalisation d’une tâche dans un contexte bien précis.

Par exemple, un développeur ayant des droits d’administrateur sur la plateforme de développement ne devrait pas les avoir en production et ainsi pouvoir visualiser des données hors de son périmètre d’activités initial.

Évitez la sécurité par l’obscurité

Bien qu’étant un contrôle de sécurité, l’obscurité repose sur la non-divulgation d’informations liées à la structure, au fonctionnement et l’implémentation d’un process informatique.

L’exemple type est l’obfuscation du code qui est censé bloquer toute rétro-ingénierie. Le contre-exemple venant de fait, sont les projets Open Source comme Apache, Linux, GPG entre autres où la sécurité est améliorée par la communauté bien que les sources soient publiques.

En cryptologie, tout repose sur le secret de la clé, mais si l’algorithme utilisé est obsolète car l’application est très ancienne par exemple, l’attaquant pourra retrouver la clé initiale via des outils dédiés de brute force et des dictionnaires et ainsi contourner l’obscurité définie pour sécuriser. Des outils d’analyse de cryptographie comme Cryptosense permettent d’auditer les applications et d’évaluer le risque induit et surtout comment remédier.

Gardez la sécurité simple

De la même façon que pour la maintenabilité du code, la sécurité introduite dans l’application doit rester simple tout en assurant sa fonction et permettre son évolutivité dans le temps.

Utiliser directement une librairie standard du marché pour réaliser un protocole OAuth par exemple, plutôt que de redévelopper sa propre implémentation.

Avoir une architecture logicielle simple permet de conserver une bonne isolation en les différents services et faciliter la gestion des différents contrôles d’accès.

Résoudre les problèmes de sécurité correctement

Si un problème de sécurité est identifié, sa remédiation doit être préalablement testée pour éviter des régressions fonctionnelles.

Elle devra aussi être appliquée de manière globale sur l’ensemble des services et/ou applications impactées pour que la correction soit effective.

Par exemple, si un service Web est corrigé côté serveur sur sa partie autorisation, les clients devront tous mettre à jour leur implémentation afin de pouvoir clôturer le service vulnérable dans les délais les meilleurs.

En conclusion

Implémenter le Security by Design nécessite de la logique, des connaissances sur le risque et les attaquants. La qualité et la sécurité du code sont un gage de confiance envers les utilisateurs finaux mais nécessitent une compréhension et une appréhension du risque qu’un développeur peut apporter dans une démarche d’amélioration continue.

 

Référence :

https://www.owasp.org/index.php/Security_by_Design_Principles