Besoin

  • Fonctionnel
  • Technique
    • Evolutivité (ouvertures à de nouvelles solutions de paiement par exemple)
    • Intéropérabilité entre les différents prestataires de services commerciaux (boutiques, fournisseurs, banques...)
    • Distribution : l'informatique d'aujourd'hui est dominée par le réseau et adopte un modèle coopératif, plus souple. Il implique cependant de nouvelles contraintes de sécurité distribuée.
    • Portabilité : les architectures logicielles sont aujourd'hui dynamiques, et dépendent de moins en moins d'une l'architecture matérielle. Une même architecture logicielle peut se déployer sur différentes architectures matérielles (exploitant des postes clients tels que PC, Mac ou NC, des serveurs divers ainsi que d'autres plates-formes telles que les appareils portables) et les exploiter différemment (exploitation de la puissance de traitement, exploitation des périphériques). Cette capacité implique la mobilité du code et donc de nouvelles contraintes de sécurité.
    • Simplicité : les opérations techniques, et notamment les opérations de sécurité doivent être transparentes pour l'utilisateur, et non pas constituer une contrainte à l'accès au service

Analyse

La sécurité peut être abordée sous différents angles :

  • la définition d'une architecture matérielle/réseau (firewalls, proxies, etc.). La compréhension des problématiques réseau liées à la sécurité est effectivement importante dans la mesure où elles ont un impact sur les possibilités des applications développées (un serveur proxy peut fortement limiter les possibilités d'une application par exemple, et il faut savoir comment intégrer une application dans une telle architecture).
  • l'utilisation de procédés cryptographiques
  • l'utilisation des caractéristiques de sécurité d'un langage : Cette dernière approche est relativement nouvelle, et trouve un nouvel essort grâce à Java.
  • le paramétrage de l'OS

C'est au travers d'une approche par composants qu'il convient de considérer les problématiques de sécurité, chaque composant pouvant se situer dans un des domaines cités. Chacun de ces domaines ne suffit à lui seul à proposer une véritable solution de sécurité, et plus que cela, chacun se doit de fournir une interface avec les autres.

Conception

DP Description
Session suite d'échanges entre deux objets...
Proxy objet auquel on délègue l'accès à un autre objet.
Objet gardé objet encapsulé par un autre, l'objet englobant régissant les opérations autorisées sur l'objet englobé.

De manière plus générale l'objet gardé est généralement un objet encapsulant un objet garde et un ou plusieurs objets dont l'accès est contrôlé par le garde.

Le principe d'encaspulation des objets gardés permet de transporter un objet avec ses règles d'accès. Ils permettent donc de répondre aux problématiques où l'on doit fournir l'accès à un objet sans connaître le contexte de sécurité du demandeur (celui-ci est distant et ne veut pas transmettre son contexte trop sensible par exemple). Dans ce cas, les objets gardés permettent de déléguer le test de sécurité au demandeur lui-même, en retournant l'objet demandé encapsulé avec son garde. Tout accès à l'objet demandé ne pourra se faire directement, et devra forcément être soumis à l'approbation du garde.

Objets constants Les objets constants (non mutables ou immutables) sont des objets dont l'état n'est accessible qu'en lecture seule On peut voir les objets constants comme un objet gardé n'autorisant que la lecture.
Objets opaques / transparents objet dont le contenu n'est pas accessible par celui qui le manipule (une clé par exemple).

Implémentation

La sécurité au niveau implémentation concerne :

  • les API de sécurité disponibles (cryptographie, etc.)
  • la sécurité inhérente au langage et la plate-forme Java eux-mêmes (accès mémoire, robustesse, etc.)

API

Java offre des API cryptographiques ainsi que des moyens de s'interfacer avec des composants matériels (réseau typiquement) tels que les proxies ou suites cryptographiques via des API adéquates.

Les objectifs de Java en matière de sécurité sont de :

  • Maximiser la sécurité pour le code suspect
  • Maximiser la souplesse de la configuration pour le code sûr, besoin de plus en plus répandu en raison de l'émergence d'intranets et extranets. Il existe une forte demande pour ce type de fonctionnalité (souplesse de configuration sans trop de contraintes pour l'utilisateur) à laquelle Java doit répondre. A défaut de satisfaire cette demande par un standard, Java sera fragmenté car étendu de manière par des éditeurs fournissant des solutions propriétaires, ou à défaut, son succès sera remis en cause.

Java se donne les moyens de la sécurité qu'il propose au travers de garanties de :

  • authentification : vous savez d'où vient le code
  • intégrité : on vous garantit que le code n'a pas été modifié
  • confidentialité : le transit a été crypté
  • contrôle d'accès : la sandbox ou les domaines de protection ont protégé vos ressources locales.

Afin de permettre à tout éditeur de fournir une implémentation d'un ou plusieurs de ces concepts de sécurité, à toute classe de sécurité générique (engine class) est associée une fabrique (factory) retournant les implémentations paramétrées dans la plate-forme (on retrouve là le modèle de SPI).

Tout fournisseur est effectivement susceptible de ne pas implémenter un protocole demandé par une application (il pourra fournir une implémentation de signature RSA/MD2 mais pas de RSA/MD5 par exemple). Il est donc possible d'installer dans la plate-forme plusieurs implémentations des classes de sécurité, avec un ordre de préférence. Pour un algorithme donné, la première implémentation trouvée dans cette liste de préférence sera utilisée. Il est également possible pour une application de spécifier son fournisseur de prédilection par programmation.

Les concepts implémentables par un fournisseur sont :

  • les clés publiques et privées (génération DSA ou RSA, mapping sur une clé abstraite)
  • les condensés de message (MD2, MD5, SHA)
  • les signatures (DSA + SHA, RSA + MD5...)
  • les certificats (X.509) et leurs listes de révocation (CRL)
  • la base locale d'informations sur les clés et certificats (permettant différentes implémentation du stockage, sur une carte à puce, sur un Java Ring, par exemple)
  • Paramètres d'algorithme
  • Générateur de paramètres d'algorithme
  • Générateur de nombres aléatoire
Version 1 Commentaire
Domaine Paradigme Release 1 2
Architecture Sandbox Bac à sable ou TCB (Trusted Computing Base) = Ligne Maginot : tout ou rien : une fois franchie, la guerre est perdue. Un bug, tout est perdu. Franchir la ligne maginot, attaquer là où on ne s'y attend pas, attaquer d'une manière non prévue par l'auteur du TCB : la guerre est perdue.
Permission Par nature (fonction de la provenance du code)
Cryptographie Implémentations JDK Pluggable API cryptographiques standardisées et donc pluggables et interopérables
Identité Classe java.security.Identity Interface java.security.Principal
Propriétés Non java. security. manager Gestionnaire de sécurité à utiliser par l'application
Non java. class. path Liste de répertoires ou fichiers JAR d'où charger des classes locales non privilégiées (non système)
Non java. security. policy URL du fichier de politique de sécurité à utiliser (=) ou ajouter (==) à la politique courante. Avec le JDK 1.2, il est possible de l'exprimer facilement à l'aide de l'outil graphique (AWT) %java_home%/bin/policytool.exe.

Langage et plate-forme

Java possède divers atouts pour l'élaboration d'une solution sûre. Parmi ceux-ci, beaucoup sont liés au principe de la JVM. Il s'agit de :

  • robustesse
    • l'exécution dans un processus (celui de la JVM) garantit généralement un espace d'adressage mémoire limité en lecture et en écriture, voire un jeu d'instructions limité. Il offre de plus une protection contre les plantages de la machine (une erreur fatale plante le processus, mais pas l'OS).
  • contrôle d'accès
    • le typage fort : Un objet ne peut être manipulé qu'au travers de son interface. En interdisant les conversions (transtypage ou cast) sauvage, Java garantit l'intégrité de l'état (des données) d'un objet (moyennant un développement vertueux, que des attributs privés par exemple). D'une manière générale, l'accès aux données est contrôlé par l'interface du type de ces données, à l'exception malheureuse des classes internes (inner classes du langage Java). Cette sécurité permet d'autoriser plusieurs flots d'exécutions (code + threads) à partager le même espace d'adressage, ce qui est plus performant que d'exécuter plusieurs applications dans des espaces d'adressage différents ou d'utiliser une zone d'échange commune.
    • Modificateurs d'accès (private, protected, final). Encore une fois, ceci permet à plusieurs applis de coopérer dans le même espace d'adressage de manière sécurisée. Réelles limitations, contrairement au C++.
    • Objets constants : Java offre diverses classes d'objets constants (non modifiables ou immutables) tels que les chaînes de caractères (String) ou les wrappers de types simples (Integer, Long, Float, etc.). Ceci permet de retourner un objet en lecture seule (la modification d'une chaîne retournée ne doit pas modifier la chaîne d'origine par exemple). On peut voir les objets constants comme un objet gardé n'autorisant que la lecture.
  • mémoire
    • GC local et distribué
    • pas d'arithmétique de pointeurs - Les références sur des objets Java ne peuvent être déplacées.
    • Références constantes (référence final sur un objet)
    • Tableaux à limites contrôlées - Un tableau est (presque) un objet, dont la lecture et la modification du contenu sont contrôlés afin d'éviter les accès mémoires illégaux.
  • Pas de préprocesseur -
  • Exceptions systématiquement remontées, doivent être gérées (compilateur), ou sont gérées par la JVM (stacktrace output).

Notes

  • Il n'y a pas de sécurité absolue. Aucun système n'est inviolable. La mise en place d'une politique de sécurité vise simplement à offrir un niveau de sécurité financièrement acceptable par rapport au coût de l'absence de sécurité.
  • le corrolaire est donc que le coût de la mise en place d'une politique de sécurité ne doit pas dépasser le coût induit par la violation de cette sécurité (vol ou dégradation de service ou d'informations, manque à gagner...). Mettre en place une politique de sécurité consiste toujours en définitive à définir quel niveau de risque est acceptable pour un système donné. Plus vous avez à perdre, plus vous êtes prêt à payer pour le préserver. La sécurité implémentée dans la plate-forme Java se doit donc d'être souple, et non rigide, afin de pouvoir s'adapter aux contraintes de chacun. Elle ne doit pas (comme dans ses premières versions), imposer par défaut une sécurité trop importante qui ne révélera inutile, voire dommageable (en performance notamment) dans certains cas de figure. Cependant, elle doit être capable d'offrir un niveau de sécurité important lorsque cela est nécessaire.
  • Trop de sécurité nuit à la sécurité : plus les contraintes seront grandes pour les utilisateurs, plus les utilisateurs seront incités à contourner cette infrastructure. Java doit donc pouvoir offrir un grand niveau de sécurité tout en s'efforçant de minimiser les contraintes pour l'utilisateur. Maximiser la transparence des opérations de sécurité passe par l'utilisation de procotoles relativement transparents (comme SOCKS, le SSO), et par la possibilité de distinguer les rôles des différents utilisateurs du système : administrateur (capable de définir la politique de sécurité d'un poste, à distance par exemple) ou utilisateur simple de la plate-forme Java.
  • Plus un algorithme est connu, plus il est sûr : il est illusoire de penser qu'une bonne implémentation d'un algorithme de sécurité est une implémentation confidentielle. Au contraire, tout bon algorithme de sécurité (et tout bon système en général) est un algorithme connu de tous, dont chacun peut déceler les failles et les corriger. Nombre d'implémentations d'algorithmes sont disponibles en OSS.
  • Un modèle de sécurité efficace est un modèle en couches. La responsabilité de la sécurité doit être l'affaire de différentes composantes, et non d'une seule (le modèle de sandbox de Java 1.1 est donc un mauvait modèle, corrigé dans Java 2). Chaque composante à son rôle dans la politique de sécurité, et l'ensemble du système développe une synergie (1+1=3) plus efficace. Chaque couche doit remplir son rôle et ne pas croire aveuglément la couche supérieure (ce n'est pas parce la porte de ma maison est fermée à clé que je laisse la nourriture sur la table de la cuisine).

Limitations

  • Aucune approche de sécurité (architecture, cryptographie, langage, OS) n'est suffisante en elle-même. Chaque spécialiste de ces domaines ne considère trop souvent les problématiques de sécurité qu'au travers de son domaine.
  • l'aspect distribué des applications - L'utilisation du réseau augmente les risques d'attaquent par chevaux de Troie (Trojan horse) et par personne interposée (man in the middle).
  • les aspects dynamiques et d'extensibilité (édition de liens dynamique comme les capacités croissantes d'extension dynamique de la plate-forme) augmentent les risques d'attaquent par chevaux de Troie (Trojan horse) et par personne interposée (man in the middle).
  • le modèle de bac à sable (sandbox) ou TCB (Trusted Computing Base) est un modèle "tout ou rien" n'offrant qu'un garde unique (gatekeeper). Des approches plus sûres exploitent plusieurs gardes indépendants, où la faille d'un garde ne remet pas en cause la sécurité du système dans son ensemble. Ce modèle a été remis en cause depuis Java 2 [J2SE 1.2] avec les permissions.
  • l'option visant à fournir une sécurité par le langage et/ou la plate-forme implique que cette sécurité disparaît dès que l'on quitte ce langage et/ou cette plate-forme. Or une application Java doit pouvoir offrir une sécurité à des systèmes non Java, récents ou anciens. La solution d'encapsulation n'est pas toujours suffisante.
  • le modèle objet masque l'implémentation derrière une interface, autorisant ainsi le remplacement d'une implémentation par une autre sans que le client n'en soit conscient. Un code hostile peut ainsi être accédé à distance ou téléchargé. De la même manière, l'utilisation de noms symboliques (services d'annuaires tels que DNS ou autres) permet de remplacer une implémentation par une autre et donc de redéfinir des services de confiance.
  • la redondance de divers mécanismes de sécurité implémentés dans la plate-forme Java alors qu'ils sont parfois offerts par les couches sous-jacentes (OS, matériel, réseau, cryptographie des communications). Ceci peut nuire à la performance.
  • des implémentations incorrectes, propriétaires ou incomplètes de la plate-forme Java (dans certains anciens navigateurs Web par exemple) contenant des bugs connus ou inconnus représentant des failles de sécurité ou représentant des solutions propriétaires de sécurité moins interopérables et moins éprouvées que des standards. Cependant aujourd'hui des extensions standards verticales existent pour le cryptage (JCE).
  • le manque de standards de sécurité aboutis, implémentés et largement diffusés (dans les navigateurs notamment), manque comblé par des implémentations propriétaires (par Netscape, Microsoft). Ces implémentations propriétaires de la plate-forme Java sont aujourd'hui contournables grâce au Plugin Java
  • avant Java 1.2 :
    • la complexité de la mise en oeuvre de mécanismes de sécurité dans Java 1.1 (dérivation de SecurityManagers et de ClassLoaders). Ceci est résolu depuis Java 2 [J2SE 1.2] par l'implémentation de politiques de sécurité est simplifiée (plus besoin de dériver des SecurityManagers ou ClassLoaders).
    • l'immaturité de la plate-forme Java dans le domaine de la sécurité en Java 1.1 : API limitée aux signatures et condensés de messages (pas de certificats), absence de permissions fines pour du code téléchargé (logique "tout ou rien" de la sandbox 1.1). Ce manque a été comblé à nouveau par des implémentations propriétaires (Netscape Capabilities API par exemple). Cependant Java 2 [J2SE 1.2] a introduit la JCA, définissant une véritable architecture de sécurité supportant des protocoles importants du monde de la sécurité (certificats X.509, etc.).
  • limitations du langage Java.

Glossaire

JEPI

Acronyme pour Joint Electronic Payment Initiative.

Le protocole JEPI défini en 1997 a l'avantage d'être indépendant du protocole de paiement (il le négocie). Cependant, il ne spécifie pas d'interface permettant à l'utilisateur d'exploiter de nouveaux protocoles de paiement.

La première implémentation de JEPI est celle de CommerceNet, en Java, mais n'exploite pas la possibilité de Java de télécharger des nouveaux gestionnaires de protocoles (JAF ?) et du code (applications) en général.

MOSS

Standard de sécurisation du courrier électronique conçu pour dépasser les limites de PEM en supportant les messages MIME.

Parce que MOSS est plus un framework qu'une spécification, et parce qu'il dispose de nombreuses implémentations différentes, deux correspondants MOSS peuvent avoir des difficultés à communiquer. On pourra donc lui préférer S/MIME, clairement défini.

RIPEMD-160

Acronyme pour RIPE Message Digest, algorithme de hâchage permettant de générer des condensés de messages.

RIPEMD-160 ou SHA sont considérés comme plus sûr que MD5, dans la mesure ou MD5 a été cassé (pour des messages courts cependant). RSA elle-même ne recommande plus l'utilisation de MD5.

RNG

Acronyme pour Random Number Generation, algorithme sécurisé de génération de nombres aléatoires (non périodiques), utilisés pour la génération de clés.

Java 2 ne fournit qu'une implémentation de nombres pseudo-aléatoires (PRNG).

PRNG

Acronyme pour Pseudo Random Number Generation, algorithme sécurisé de génération de nombres pseudo-aléatoires (pérodiques), utilisé pour la génération de clés.

Java 2 inclut une implémentation de PRNG, via le générateur java.security.SecureRandom.

SET

Acronyme pour Secure Electronic Transactions.

Protocole de commerce électronique situé au-dessus de SSL, permettant les authentifications des clients porteurs de cartes de crédit, des commerçants et des fournisseurs, l'intégrité et la confidentialité des informations de paiement (du client vers le commerçant) et de commande (du commerçant vers le fournisseur).

Comme SSL, SET exploite les certificats X509.

SKIP

Acronyme pour Secure Key Internet Protocol.

S/WAN

Acronyme pour Secure Wide Area Network.

Permet d'intégrer de la sécurité pour les WAN au sein de réseaux privées virtuels.

TIPEM

Acronyme pour Toolkit for Interoperable Privacy Ehanced Mail, librarie de RSA permettant de développer des produits intégrant S/MIME dans les applications de courrier électronique.

Le modèle de sécurité ActiveX

Comme pour les plugins, le modèle de sécurité ActiveX :

  • prétend limiter les possilité du code natif des ActiveX. Or un ActiveX peut construire des pointeurs, etc.
  • autorise tout par défaut (non signé). Java n'autorise rien par défaut.
  • repose entièrement sur le jugement de l'utilisateur. Lorsqu'une fenêtre s'affiche en indiquant que Verisign garantit que Joe Schmoe est bien l'auteur du programme téléchargé, on ne peut prendre de décision raisonnable si l'on ne sais pas qui est Joe Schmoe.
  • fonctionne en mode tout ou rien : si vous acceptez, le programme pourra faire tout ce qu'il veut sur votre machine (définir un sécuritymanager en Java 1.1 ou utiliser java2 permet de spécifier les actions autorisées). Si vous refusez, il ne peut théoriquement rien faire. Mais il s'agit de code natif, donc il peut tout faire (ou presque). Il exite également une option permettant de *tout* accepter systématiqueemnt en provenance d'une identité donnée.
  • les plugins/activeX ne sont pas téléchargés à chaque fois et restent sur votre poste

Evolution de OLE.

-> OLE inventé pour rendre Office plus flexible

--> Patch way of life

Sécurité Windows : non multi-utilsiateur non multisession, non network... etc, C history ; patch way not designed for all this stuff.

La sécurité est dans l'OS Windows et non dans les composants (sécurité au niveau du langage comme Java).

Voir