Sécurité des services web – 1ère partie

le 04/12/2008 par Xavier Vaccari
Tags: Software Engineering

Cet article est la première partie d'une série de posts concernant la sécurité des services web.

Nous allons présenter dans cette première partie un aperçu de la norme WS-Security pour les services SOAP et les différentes possibilités pour sécuriser des services web.

Les architectures SOA se sont généralisées petit à petit au sein des entreprises pour construire des systèmes capables d'offrir des fonctionnalités partagées via des services.

Ces services peuvent être internes et ne concerner qu'une organisation ou être ouverts sur l'extérieur dans le cadre d'échanges B2B.

Dès lors que l'on propose de la valeur ajoutée ou transporte des données dites sensibles, ces services sont alors confrontés à des buts contradictoires :

  • Exposer de l'information et la rendre facilement accessible à un tiers (personne ou système)
  • Sécuriser l'information pour la rendre uniquement consommable par des personnes ou des systèmes habilités à la voir et à l'utiliser.

La sécurité est au cœur des préoccupations des entreprises pour garantir la cohérence et la pérennité des systèmes. Pour ce faire, la sécurité doit être prise en compte dès la conception des services web et ceci à tous les niveaux :

  • Conception, spécification
  • Architecture
  • Développement
  • Déploiement
  • Exécution & exploitation

Au-delà du tout sécuritaire, une approche pragmatique de la sécurité pilotée par les risques est préférable. Rappelons les fonctions de sécurité disponibles qui pourront s'appliquer à des services:

  • Authentification : le mécanisme qui permet de vérifier l'identité d'une personne/d'un système
  • Habilitation : le droit d'accéder ou non à une fonctionnalité, à une donnée
  • Intégrité (ou signature) : la non modification d'une donnée échangée
  • Imputabilité : traçabilité des actions d'un individu sur un système
  • Confidentialité (ou chiffrement) : la non lisibilité de la donnée par un tiers ne partageant pas un secret

Les stacks de sécurité des web services (WS-Security & co) sont à priori complexes et chers à mettre en œuvre. Toutefois, on peut trouver des exemples concrets où ces solutions ont un réel intérêt (signature des messages par exemple).

Nous allons présenter dans cet article un aperçu de la norme WS-Security pour les services SOAP et les différentes possibilités pour sécuriser des services web.

WS-Security

WS-Security est un standard pour sécuriser des services web SOAP uniquement. Ce dernier aborde les aspects classiques comme l'authentification, l'habilitation mais également des besoins plus rares comme le chiffrement, la signature. Cette norme s'applique uniquement au niveau des messages échangés et n'a aucun impact sur le protocole et le transport choisis. Il repose sur l'ajout d'éléments dans les headers/en-têtes SOAP. Ce standard appelé aussi WSS (Web Services Security) tente de normaliser les échanges sécurisés de messages et de garantir l'interopérabilité entre systèmes.

Des Profiles sont disponibles pour couvrir l'ensemble des problématiques liées à la sécurité (authentification, chiffrement et signature). Le consortium OASIS vise la standardisation des spécifications WS-* pour permettre une meilleure interopérabilité entre les technologies.

Authentification

L'authentification s'appuie sur la notion de token c'est à dire des headers SOAP capables de véhiculer les credentials (typiquement un login et un mot de passe) jusqu'au service cible. Le niveau de confidentialité de ces données échangées peut également être choisi (hash de password, chiffrement des données,.).

Les principaux tokens disponibles sont :

  • User Name Token : échange de couples login/mot de passe
  • SAML Token : échange de données d'authentification au format XML SAML
  • X509 Token : échange de données d'authentification par certificat (authentification forte)

D'autres tokens permettent de l'authentification via des systèmes tiers comme Kerberos.

Voici un exemple de header avec un token user name non chiffré :

<s11 :Envelope xmlns:S11="..." xmlns:wsse="..." xmlns:wsu= "..." >
</s11><s11 :Header >
...
<wsse :Security>
</wsse><wsse :UsernameToken>
</wsse><wsse :Username>NNK</wsse>
<wsse :Password Type="...#PasswordDigest">
weYI3nXd8LjMNVksCKFV8t3rgHh3Rw==</wsse>
<wsse :Nonce>WScqanjCEAC4mQoBE07sAQ==</wsse>
< wsu:Created>2003-07-16T01:24:32Z< /wsu:Created>


...
</s11>
...

Chiffrement

Le chiffrement peut se faire via différents algorithmes, symétriques ou asymétriques. La norme WS-Security permet l'envoi de métadonnées du client de web service au web service cible (end-point) afin de décrire la méthode de chiffrement utilisée et permettre des échanges de clé si besoin.

Les messages sont constitués de plusieurs parties (header, message), chacune pouvant être chiffrée ou non selon la configuration choisie.

Voici un exemple de chiffrement du corps du message avec un certificat X509 :

<s11 :Envelope xmlns:S11="..." xmlns:wsse="..." xmlns:wsu="..." xmlns:ds="..." xmlns:xenc="...">
</s11><s11 :Header>
<wsse :Security>
<xenc :ReferenceList>
<xenc :DataReference URI="#bodyID"/>
</xenc>
</wsse>
</s11>
<s11 :Body>
<xenc :EncryptedData Id="bodyID">
<ds :KeyInfo>
</ds><ds :KeyName>CN=Hiroshi Maruyama, C=JP</ds>

</xenc><xenc :CipherData>
</xenc><xenc :CipherValue>...//le message chiffré// </xenc>


</s11>

Ainsi, plutôt que d'utiliser une couche de transport gérant la confidentialité des données, on chiffre tout ou partie du message.

Signature

L'objectif de la signature est de garantir l'origine du message en échangeant un jeton chiffré avec un secret partagé (clé symétrique ou asymétrique). Elle se se fait via des certificats X509 et peut être appliquée sur des messages en clair ou chiffrés selon la configuration choisie.

Comme pour le chiffrement, il est possible de signer à la fois le corps des messages mais également leurs en-têtes.

Voici un exemple de header WS-Security avec une signature du corps du message à base de certificat X509 :

<s11 :Envelope xmlns:S11="..." xmlns:wsse="..." xmlns:wsu="..." xmlns:ds="..." xmlns:xenc="...">
</s11><s11 :Header>
<wsse :Security>
<xenc :ReferenceList>
<xenc :DataReference URI="#bodyID"/>
</xenc>
</wsse>
</s11>
<s11 :Body>
<xenc :EncryptedData Id="bodyID">
<ds :KeyInfo>
</ds><ds :KeyName>CN=Hiroshi Maruyama, C=JP</ds>

</xenc><xenc :CipherData>
</xenc><xenc :CipherValue>...//le message chiffré// </xenc>


</s11>

WS-Security : une norme de plus en plus accessible

La norme WS-Security est vaste mais la complexité inhérente à la norme est de plus en plus masquée et devient même dans certains cas complètement externe aux développements applicatifs.

En Java par exemple, l'adoption de nouveaux frameworks et leur intégration avec Spring a favorisé la mise en place de WS-Security par simple déclaration au niveau de la configuration Spring. Un service SOAP peut donc intégrer un chiffrement ou une signature par simple ajout d'un bloc XML.

Des constructeurs d'appliances comme IBM vont également dans ce sens en proposant des boitiers dédiés à la sécurité des web services. Ces derniers sont capables de modifier à la volée des messages SOAP pour leur appliquer des fonctions de sécurité.

Où placer la sécurité ? Jusqu'où aller ?

Les fonctionnalités d'un système n'étant pas exposées aux mêmes risques et cela de façon uniforme, l'approche sécuritaire pilotée par les risques permet d'ajuster le niveau de combinaison et donc d'ajuster les coûts et délais induits lors de la mise en œuvre/exploitation.

Généralement, la plupart des services web implémentés dans les entreprises n'embarquent pas de brique sécurité à proprement parler et les organisations ont plutôt tendance à s'appuyer, dans la plupart des cas, sur les procédures et matériels existants pour la gérer au niveau de l'infrastructure. Cette démarche a l'avantage de ne pas ou peu impacter les développements applicatifs.

La mise en place de tout ou partie des 5 fonctions citées précédemment doit être étudiée selon le besoin de chaque contexte. Il sera ainsi possible de trouver le meilleur compromis pour mitiger les risques en combinant ces fonctions. Voici quelques exemples de combinaisons possibles :

  • Contrôle d'accès aux services : utiliser un réseau sécurisé par des firewalls pour limiter la consommation de services à telle ou telle machine.
  • Confidentialité des données échangées over HTTP : HTTPS pour le transport des données
  • Confidentialité et intégrité pour des messages XML over HTTP: HTTPS pour le transport, signature personnalisée ajoutée dans le message XML
  • Confidentialité et intégrité pour des messages SOAP : HTTPS pour le transport, signature du message avec WS-Security
  • .

Le déploiement de la sécurité autour des services web va être principalement guidé par les contraintes de mise en œuvre (légale ou réglementaire de non répudiation, de confidentialité des données), le besoin en terme de confidentialité des données et la topologie des équipes infra, sécurité et projet au sein de l'entreprise :

  • Le niveau de maitrise par les équipes de développement des frameworks et outils (IDE, stack SOAP ou REST, intégration sur les serveurs de développement),
  • Le niveau de maitrise par les équipes de production des briques d'infrastructure et éventuellement des frameworks utilisés sur les projets (firewalls, reverse-proxy, appliance XML, PKI/Certificats.),
  • La facilité de communication entre ces équipes est donc nécessaire pour mettre en production des services sécurisés et fluidifier les échanges,
  • Les besoins d'interopérabilité entre les systèmes exposant ou consommant des services sécurisés.

Voici quelques exemples de combinaisons que nos architectes retrouvent souvent chez des clients.

Utiliser la sécurité des infrastructures

  • Réseaux séparés ou de confiance (firewalls)
  • (optionnel) VPN pour la confidentialité sur l'extranet/internet
  • (optionnel) Authentification éventuellement déléguée à un VPN

Dans ce cas, la sécurisation repose intégralement sur les briques réseau. Elle n'impacte pas les équipes de développement ce qui rend la sécurité complètement transverse à l'application. Ce cas d'utilisation s'applique dans des échanges B2B avec des partenaires (réseau VPN dédié entre le producteur et le consommateur de services) ou dans les intranets.

S'appuyer sur les protocoles standards

  • HTTP pour le protocole
  • SSL pour la confidentialité
  • Basic Auth pour l'authentification (user, mot de passe) (granularité au niveau de l'application)

Ces briques sont communes et maitrisées par l'ensemble des technologies utilisées dans les entreprises (Java, .Net, C/C++, Progiciels, .). Le pattern repose entièrement sur le protocole (HTTP+SSL) et permet d'assurer à la fois l'authentification et la confidentialité (les messages transite en clair dans un tuyau crypté HTTPS).

Cette typologie est la plus répandue aujourd'hui. On peut l'utiliser à la fois pour des échanges internes à l'entreprise pour des services sensibles que pour relations B2B classiques utilisant l'Internet (ex: banque qui fait de l'assurance vie en marque blanche). Ce mode de sécurisation est flexible puisque l'accueil de nouveaux clients ne nécessite aucune modification de configuration existante (pas de réseau à créer contrairement à la précédente).

S'appuyer sur les couches applicatives et des normes telles que WS-Security

  • HTTP (synchrone) ou JMS (asynchrone) pour le protocole
  • Authentification par Username Token en WS-Security
  • Chiffrement des messages via WS-Security

Cette solution est plus complexe à mettre en œuvre puisqu'elle impacte les couches applicatives et nécessite que les messages soient échangés en SOAP.

En revanche, l'application de la sécurité au niveau du message permet sa circulation sur un transport non sécurisé (http sur Internet par exemple) et une interopérabilité accrue.

Cette solution est intéressante dans le cas de services très ouverts sur Internet qui doivent garantir un fort niveau de confidentialité/intégrité du message.

La suite de cette série d'articles illustrera quelques uns de ces cas d'application.

Références