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. n1La 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. n2Java
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 chiffrement (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 œuvre 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.
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.
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 sait 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 existe é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