Sécurité
en Java 2
Université de Nice - Sophia Antipolis
Version TA 4.5.1 – 28/10/05
Richard Grin
Présentation
R. Grin Java : sécurité page 2
La sécurité en informatique
Authentifier les utilisateurs ou les programmes
avec des signatures
Contrôler les autorisations d’accès aux
ressources (système et utilisateur) d’une entité
authentifiée ; par exemple, empêcher des
lectures, suppressions ou des modifications non
autorisées sur des fichiers
Assurer par le cryptage la confidentialité des
transmissions ou des données stockées
R. Grin Java : sécurité page 3
Le soucis de la sécurité
Dès sa conception, Java a attaché beaucoup
d’importance à la sécurité
Les classes Java peuvent être chargées
dynamiquement depuis des machines non
sûres et il faut un moyen de contrôler les
actions exécutées par ces classes
En particulier, l’exécution des applets
récupérées sur le Web présente un grand
risque
R. Grin Java : sécurité page 4
Interdire pour protéger
Pour effectuer la protection des ressources,
Java interdit aux classes Java non sûres
(essentiellement celles qui viennent d'une autre
machine) d'effectuer des opérations
potentiellement dangereuses :
n obtenir des informations sur l'utilisateur ou
la machine locale
n écrire sur le disque local
n se connecter sur une tierce machine non
connue de l'utilisateur
n ...
R. Grin Java : sécurité page 5
Le bac à sable des applets
Par défaut les applets s'exécutent dans un
« bac à sable » duquel elles ne peuvent sortir
et qui leur interdit toute action dangereuse
Mais les contraintes imposées par le bac à
sable sont trop strictes pour certaines applets
qui souhaitent obtenir des informations
locales ou écrire des données sur les disques
locaux
Java 2 permet d’assouplir cette politique de
sécurité
R. Grin Java : sécurité page 6
Sujet du cours
Les exemples suivants montrent les
restrictions imposées par le bac à sable
Il faudra contourner ces restrictions si on veut
faire fonctionner les applications
Mais il ne faut pas pour cela ouvrir la porte
aux utilisateurs mal intentionnés
C’est le sujet de la 1ère partie de ce cours :
comment permettre juste ce qu'il faut pour
qu'une application ou applet (et pas les
autres) puisse effectuer des opérations qui lui
sont interdites normalement
R. Grin Java : sécurité page 7
Un exemple
Application qui pose des QCM et gère les
résultats
Pour cela, l'utilisateur se connecte à une
adresse Web et récupère une page qui
contient une applet qui affiche les questions
Pour obtenir l'identité de la personne qui
répond, l'applet contient l'instruction
[Link]("[Link]");
Le bac à sable dans lequel s'exécutent les
applets interdit la lecture de la propriété
système « [Link] »
R. Grin Java : sécurité page 8
Un autre exemple
Cette même application range les résultats
des étudiants dans une base de données
Le SGBD est placé sur une autre machine
que le serveur Web
L'applet se voit refuser l'accès à ce SGBD car
le bac à sable interdit les connexions réseaux
sur une autre machine que celle du serveur
Web d’où vient l’applet
R. Grin Java : sécurité page 9
Encore un autre exemple
Une applet souhaite écrire sur le disque de
l’utilisateur un fichier qui contient des
données qui seront utiles à l’utilisateur la
prochaine fois qu’il se connectera
La politique de sécurité liée au bac à sable
refuse à l’applet l’écriture d’un fichier sur le
disque local de l’utilisateur
En fait une applet ne peut que lire des fichiers
qui sont placés dans le répertoire d’où elle
vient ou dessous (et placés dans le même jar
si elle est dans un jar)
R. Grin Java : sécurité page 10
Il n’y pas que les applets…
Des restrictions comme celles imposées par
le bac à sable des applets se retrouvent aussi
n pour les applications qui chargent des
classes dynamiquement depuis une autre
machine (RMI en particulier)
n pour les applications qui décident, pour
une raison quelconque, d’installer un
gestionnaire de sécurité
n lorsque l’utilisateur l’a décidé en lançant
l’application
R. Grin Java : sécurité page 11
Plan
La sécurité dans le langage Java
Plugin Java pour les applets
Police de sécurité
Signature de code
Les outils Sun pour la signature
JAAS
R. Grin Java : sécurité page 12
La sécurité dans le langage Java
R. Grin Java : sécurité page 13
Les moyens pour la sécurité
Dans le langage Java et la JVM
Les API standard
Les API et les outils pour la sécurité
R. Grin Java : sécurité page 14
La sécurité dans le langage
Vérifications à la compilation :
n Java est fortement typé
n Pas d'arithmétique des pointeurs
n Les variables non initialisées sont
inutilisables
n Protection des variables d'état
(private,…)
n Possibilité de déclarer final les variables,
méthodes et classes
R. Grin Java : sécurité page 15
La sécurité dans le langage
Vérifications à l'exécution :
n Contrôle des débordements dans les
tableaux
n Contrôle des casts
n Vérification des classes au chargement
R. Grin Java : sécurité page 16
La sécurité dans les API
Les API liés à la sécurité permettent de
n délimiter ce qui est autorisé pour chaque
programme Java, selon
— le lieu d'où les classes ont été chargées
— l'utilisateur qui les a signées
— l'utilisateur qui l'exécute (étudié plus
loin lors de l’étude de JAAS ; pas pris en
compte pour cette partie)
n protéger la confidentialité des informations
par le cryptage
R. Grin Java : sécurité page 17
Écrire des programmes sûrs
Favoriser l'encapsulation : les variables doivent
être private, sauf raison contraire
Éviter autant que possible les variables
protected
Éviter de passer des références vers des
variables sensibles en sortie ou en entrée des
méthodes ; cloner (ou copier) les valeurs avant
de les passer
Déclarer final les méthodes ou les classes
dont le fonctionnement ne doit pas être modifié
R. Grin Java : sécurité page 18
Sécurité et JDBC
Si une requête SQL exécutée par JDBC
comporte une partie constituée d’une chaîne
de caractères entrée par un utilisateur il faut
se prémunir contre une injection de code
SQL
Ce procédé de piratage n’est pas lié à JDBC
mais peut être utilisé dès qu’une requête SQL
est construite à partir d’une partie donnée par
l’utilisateur
R. Grin Java : sécurité page 19
Exemple d’injection de code SQL
Un programme demande le nom et le mot de
passe d’un utilisateur et les range dans 2
variables nom et mdp
Il vérifie le nom et le mot de passe d’un
utilisateur en vérifiant que la requête suivante
renvoie bien une ligne
"select * from utilisateur"
+ " where nom = '" + nom
+ "' and mdp = '" + mdp + "'"
Quel est le problème ?
R. Grin Java : sécurité page 20
Le problème
Un pirate sait qu’un des utilisateurs autorisés
s’appelle Dupond
Il saisit « Dupond' -- » pour le nom et « a »
pour le mot de passe
La requête devient :
select * from utilisateur
where nom = 'Dupond' -- and mdp = 'a'
Mais « -- » indique un commentaire avec le
SGBD utilisé ; donc la requête exécutée sera :
select * from utilisateur
where nom = 'Dupond'
R. Grin Java : sécurité page 21
Les parades
Toujours vérifier la saisie d’un utilisateur
avant de s’en servir pour construire une
requête SQL
Pour l’exemple, il aurait suffit d’interdire le
caractère « ' »
Avec JDBC, il sera plus sûr d’utiliser une
PreparedStatement et les méthodes
setXXX plutôt que de concaténer des
String et d’utiliser Statement ; par
exemple l’utilisation de setDate va obliger à
vérifier le format de la date
R. Grin Java : sécurité page 22
Vérificateur de bytecode
Il fait partie de la JVM
Son rôle est d'examiner le bytecode des
classes au moment de leur transformation en
objet Class par le chargeur de classe
Il vérifie que la structure des classes
chargées par la JVM sont correctes
En plus des avantages pour la sécurité, il
évite ainsi à la JVM d’effectuer certaines
vérification à l’exécution (par exemple, les
dépassements de capacité de la pile), ce qui
améliore les performances
R. Grin Java : sécurité page 23
Les 4 passes de la vérification
Vérification de la structure du fichier
Vérifications qui ne dépendent pas du code
particulier des méthodes
Vérification du code de chaque méthode
Vérifications sur le code des méthodes, qui
sont repoussées pour des raisons d’efficacité
jusqu’au moment où le code est exécuté pour
la première fois
R. Grin Java : sécurité page 24
Passes 1 et 2
Structure du fichier :
n nombre « magique » correct au début du fichier
(0xCAFEBABE)
n pool des constantes a une structure correcte
Vérifications qui ne dépendent pas du code
particulier des méthodes :
n pas de classe fille d’une classe final
n pas de méthode final redéfinie
n toute classe a bien une classe mère (sauf Object)
n références vers le pool des constantes sont valables
R. Grin Java : sécurité page 25
Passe 3 (1)
Jusqu’à maintenant les vérifications ne prenaient
en compte que la classe vérifiée
Les passes 3 et 4 prennent en compte les
classes utilisées par la classe vérifiée
La passe 3 nécessite une analyse du
cheminement d’exécution ; elle est la vérification
la plus complexe
R. Grin Java : sécurité page 26
Passe 3 (2)
La répartition des tâches entre les passes 3 et 4
n’est pas complètement spécifiée et peut
dépendre des JVM
Le principe général est qu’on essaie de
repousser dans la passe 4 les vérifications qui
nécessiteraient le chargement de nouvelles
classes
Par exemple, si le profil de f est « B f() », « B b
= f(); » peut être vérifié par la passe 3 sans
charger la classe B, mais « A b = f(); » va
nécessiter le chargement des classes A et B pour
s’assurer que B est une classe fille de A
R. Grin Java : sécurité page 27
Passe 3 (3)
Vérifications effectuées :
n variables locales pas utilisées sans être
initialisées
n les méthodes sont appelées avec des
paramètres corrects (nombre et type) et
retournent les bons types
n les accès aux membres (public, protected,…)
sont autorisées
n les affectations sont effectuées avec les bons
types
R. Grin Java : sécurité page 28
Passe 4
Les vérifications effectuées sont celles de la
passe 3 qui nécessitent le chargement de
classes
La JVM peut alors remplacer les instructions qui
ont déclenché la vérification par d’autres
instructions spéciales de telle sorte qu’aucune
vérification ne sera plus déclenchée par la suite
R. Grin Java : sécurité page 29
Classes vérifiées par le
vérificateur de bytecode
Les classes de l'API standard (et des
extensions) ne sont pas vérifiées
Depuis la version 1.2, les classes venant du
classpath sont vérifiées
R. Grin Java : sécurité page 30
Protection par le chargeur de classes
Les chargeurs de classes sont les piliers de
la gestion de la sécurité en Java 2
Lors du chargement des classes ils mettent
en place tout le contexte qui sera utilisé par
les gestionnaires de sécurité pour délimiter
ce qui sera autorisé pendant l'exécution
En particulier, ils associent les classes
chargées à un domaine de protection (voir
suite du cours)
Les chargeurs de classes sont étudiés en détails
dans un autre cours
R. Grin Java : sécurité page 31
Espaces de noms liés
aux chargeurs de classes
Un chargeur de classes définit un espace de
nom : 2 classes de même nom chargées par 2
chargeurs de classes différents sont
considérées comme différentes
Les navigateurs créent un chargeur de classes
différent pour chaque codebase
Ainsi, par exemple, 2 applets venant de 2 URL
différents ont des chargeurs de classes
différents et ne partagent pas les mêmes
classes distantes (même si elles ont le même nom)
R. Grin Java : sécurité page 32
La sécurité dans les
différentes versions
La politique de sécurité de Java a évolué au
cours des différentes versions : JDK 1.0, JDK
1.1 et Java 2
Chaque nouvelle version a ajouté de la
souplesse aux possibilités offertes aux
utilisateurs, développeurs et administrateurs
R. Grin Java : sécurité page 33
Les versions de la politique de
sécurité de Java 1 Bac à sable des applets
JDK 1.0 JDK 1.1
Tout ou (presque) rien Tout (aussi pour le code signé)
(Images du tutoriel en ligne de Sun) ou (presque) rien
R. Grin Java : sécurité page 34
La politique de sécurité de Java 2
Plusieurs domaines de sécurité Les domaines de sécurité
avec plus ou moins d’autorisations sont déterminés par les
(de tout jusqu’à presque rien) chargeurs de classe
R. Grin Java : sécurité page 35
Introduction à la
politique de sécurité
de Java 2
R. Grin Java : sécurité page 36
Contrôle des applications
Par défaut les applications locales, c’est-à-
dire, lancées par une classe placée dans le
classpath ne sont pas contrôlées
Toutes les autres sont contrôlées
automatiquement par un gestionnaire de
sécurité
On peut aussi faire contrôler les applications
locales si on le souhaite
R. Grin Java : sécurité page 37
Principe général
de la sécurité en Java 2
Les droits d'un code ne sont pas écrits en dur
dans le code
Ils sont définis par une politique/police de
sécurité enregistrée à part dans des fichiers
R. Grin Java : sécurité page 38
Exemple de fichier
de police de sécurité
keystore ".keystore";
grant signedBy "toto" {
permission [Link]
"${[Link]}${/}-", "read";
};
grant codeBase
"[Link] {
permission [Link]
"[Link]", "read";
};
N’oubliez pas les « ; » !
R. Grin Java : sécurité page 39
Domaine de sécurité
Quand elle est chargée dans la JVM, une
classe se voit associer un domaine de
sécurité
Un domaine de sécurité ajoute des
permissions à une classe (en plus de ce que
permet le bac à sable)
C’est une sorte de bac à sable élargi et
assoupli
R. Grin Java : sécurité page 40
Ce qui détermine
un domaine de sécurité
Un domaine de sécurité est déterminé par
n l’origine de la classe : d'où vient-elle, qui l'a
signée
n la politique de sécurité au moment où la
classe est chargée par le chargeur de
classes
La politique de sécurité peut être modifiée en
cours d’exécution, mais ça ne change pas les
permissions associées aux classes déjà
chargées
R. Grin Java : sécurité page 41
Exemple
L’utilisateur qui a lancé l’exécution a ceci
dans son fichier de police de sécurité :
grant signedBy "toto" {
permission [Link]
"${[Link]}${/}-", "read";
};
Alors, si une classe signée par toto est
chargée en mémoire, le domaine de sécurité
qui lui est associé contiendra la permission
de lire les fichiers placés dans toute
l’arborescence du répertoire HOME de
l’utilisateur
R. Grin Java : sécurité page 42
Toutes les API sont concernées
Toute action potentiellement dangereuse
effectuée par une méthode des API Java est
contrôlée par le gestionnaire de sécurité
Les paquetages [Link] et [Link] sont
particulièrement concernés, mais aussi les
autres paquetages comme [Link],
[Link] ou [Link]
R. Grin Java : sécurité page 43
API et outils
spécifiquement destinés à la sécurité
Paquetage [Link] et ses sous-
paquetages : classes pour les permissions,
les signatures, les polices de sécurité,...
Outils pour la sécurité fournis avec le SDK :
jarsigner, keytool, policytool
R. Grin Java : sécurité page 44
Les acteurs de la
politique de sécurité
R. Grin Java : sécurité page 45
Acteurs de la politique de sécurité
n Politique de sécurité
n Domaines de sécurité
n Gestionnaire de sécurité et contrôleur d'accès
n Contexte d'appel
La politique de sécurité détermine le domaine de
sécurité d'une classe au moment de son
chargement
Si une méthode veut exécuter une action
potentiellement dangereuse, le gestionnaire de
sécurité charge le contrôleur d'accès de vérifier
qu'elle en a le droit dans le contexte de l'appel
R. Grin Java : sécurité page 46
Politique de sécurité
Par défaut elle est déterminée par la lecture d'un
fichier de propriétés au démarrage de la JVM
Elle est utilisée au moment du chargement des
classes pour créer des domaines de sécurité
La vérification des droits d'une classe n'utilise
ensuite plus que ces domaines de sécurité
Représentée par la classe Policy
La méthode refresh() permet de relire le fichier de
police de sécurité (pour l’attribution des domaines des
nouvelles classes chargées)
R. Grin Java : sécurité page 47
Domaine de sécurité
Une classe appartient à un et un seul domaine
déterminé par la politique de sécurité au
moment de son chargement et par son « code
source », c’est-à-dire l’origine du code
Un domaine de protection est composé d’un
codesource, d’une collection de permissions,
d’un classloader et d’un tableau de
« principals » (servent à identifier un utilisateur)
Représenté par la classe ProtectionDomain
R. Grin Java : sécurité page 48
Notion de CodeSource
En Java 2, l'origine du code d'une classe est
constituée
n de l'URL d'où a été chargée la classe
n du signataire de la classe, avec les
certificats qui ont été utilisés pour vérifier la
signature
Représenté par la classe CodeSource
R. Grin Java : sécurité page 49
Domaine système
Le domaine « système » est formé des classes
chargées par la chargeur de classe primordial
(celui qui charge les classes au démarrage de Java)
Les classes du domaine système ne sont pas
contrôlées
Actuellement, toutes les classes du JDK sont
placées dans le domaine système
Les applets ou les applications appartiennent à
d'autres domaines déterminés par leur
« codeSource »
R. Grin Java : sécurité page 50
Gestionnaire de sécurité
Il contrôle l'accès aux ressources protégées
Représenté par la classe
[Link] ou par une classe
descendante
En fait, le SecurityManager délègue le travail
au contrôleur d'accès (nouvelle classe
AccessControler de Java 2)
R. Grin Java : sécurité page 51
Choix du gestionnaire de sécurité
Ordinairement, il est installé par le contexte
d'exécution (par exemple, par le navigateur Internet ou
par une option de la commande java)
Par défaut, les application locales, c’est-à-dire
celles qui sont lancées par une classe principale
venant du classpath, ne sont pas contrôlées par
un gestionnaire de sécurité
Aucun contrôle d’accès n’est donc effectué pour
les applications locales, même pour les classes
distantes chargées par l’application, par
exemple, en utilisant un URLClassLoader
R. Grin Java : sécurité page 52
Choix du gestionnaire de sécurité
sur la ligne de commande
On peut installer un gestionnaire de sécurité au
lancement d'une application :
n gestionnaire par défaut (bac à sable, instance
de [Link]) :
java -[Link] … Classe
n gestionnaire particulier :
java -[Link]=MonSecurityManager
… Classe
R. Grin Java : sécurité page 53
Choix du gestionnaire de sécurité
dans un programme
Installer un gestionnaire de sécurité (pour RMI
sur cet exemple) :
[Link](
new RMISecurityManager())
Cet appel nécessite le droit
[Link]("setSecurityManager")
Récupérer le gestionnaire de sécurité :
[Link]()
R. Grin Java : sécurité page 54
Déboguer les problèmes
liés aux permissions
Pour les applications, la propriété
[Link] offre plusieurs
options pour faire afficher les problèmes liées
aux permissions ; ces options s’affichent par :
java –[Link]=help
Pour les applets, il faut faire afficher la
console Java du navigateur ou du plugin Java
de Sun
R. Grin Java : sécurité page 55
Contrôleur d'accès
C'est lui qui décide si un accès à une ressource
système est autorisé
Il tient compte
n du contexte d'appel de la méthode qui veut
accéder à la ressource système
n du domaine de sécurité de toutes les classes
qui sont dans le contexte d'appel
Il est représenté par la classe
AccessController qui ne contient que des
méthodes static (checkPermission en
particulier)
R. Grin Java : sécurité page 56
Contexte d'appel
Il est utilisé pour vérifier les droits d'une
méthode
Il est formé des classes dont les méthodes
sont dans les piles d'exécution des différents
threads qui ont conduit à l'appel de la
méthode
Pour qu'un méthode ait un droit, il faut que
tous les domaines des classes du contexte
d'appel aient ce droit
Représenté par la classe
AccessControlContext
R. Grin Java : sécurité page 57
Extrait de FileOutputStream
public FileOutputStream(String name,
boolean append)
throws FileNotFoundException {
SecurityManager
security = [Link]();
if (security != null) {
[Link](name);
}
fd = new FileDescriptor();
if (append) { openAppend(name); }
else { open(name); }
}
R. Grin Java : sécurité page 58
Extrait de SecurityManager
public void checkWrite(String file) {
checkPermission(
new FilePermission(file, "write"));
}
public void checkPermission(Permission perm) {
[Link](perm);
}
Appel à la classe
AccessControler
R. Grin Java : sécurité page 59
AccessControlException
Si un appel est rejeté par le contrôleur d'accès,
une AccessControlException (paquetage
[Link]) est levée
Cette classe d'exception hérite de la classe
[Link] qui elle-
même hérite de RuntimeException
Il n'est donc pas obligatoire de déclarer cette
exception dans la définition des méthodes
R. Grin Java : sécurité page 60
Algorithme pour le contrôle d'accès
Les domaines A, B et C doivent
check Access avoir la permission « write »
Permission() Controller sinon, lancement d'une
AccessControlException
write() FileWriter
mc() classe C domaine C permissions
mb() classe B domaine B permissions
ma() classe A domaine A permissions
Pile d'exécution Contexte d'appel
R. Grin Java : sécurité page 61
Code privilégié
Du code peut recevoir des droits privilégiés s'il est
exécuté par la méthode static
doPrivileged() de la classe
AccessController
Cette méthode prend en paramètre une instance
d’une classe qui implémente l’interface
PrivilegedAction
Cette interface ne comprend qu’une méthode
« Object run() »
La méthode doPrivileged exécute cette
méthode run() et renvoie l’objet renvoyé par
run()
R. Grin Java : sécurité page 62
Autorisations du code privilégié
Les autorisations d'accès du code privilégié
(exécuté par doPrivileged) sont déterminées
uniquement par les droits
n du code privilégié
n des méthodes appelées par ce code
Il y a donc moins de vérifications à faire : les
limitations liées aux méthodes qui ont appelé ce
code n'interviennent pas
Soyez donc très prudent avec ce que vous
permettez dans du code privilégié !!
R. Grin Java : sécurité page 63
Exceptions et code privilégié
La méthode run() ne doit pas renvoyer
d’exception
Sinon, on doit utiliser l’interface
PrivilegedExceptionAction dont la
méthode run() renvoie une Exception
R. Grin Java : sécurité page 64
Permissions pour exécuter
du code privilégié
Aucune permission spéciale n’est requise
pour exécuter du code privilégié
Ça n’est pas nécessaire car le code privilégié
ne permet pas d’exécuter du code qui n’est
pas autorisé normalement par la classe
R. Grin Java : sécurité page 65
Exemple de code privilégié
Code extrait du constructeur de la classe
[Link] :
lineSeparator =
(String)[Link](
new [Link](
"[Link]"));
La variable lineSeparator est utilisée par le code
de la méthode println() ; doPrivileged assure
que [Link] pourra être lue quelle que
soit la politique de sécurité et les méthodes qui ont
appelé ce code
R. Grin Java : sécurité page 66
Autre exemple de code privilégié :
le problème à résoudre
On a un fichier sensible password dans lequel il
faut absolument respecter un format spécial
Comment permettre l’écriture dans ce fichier
sans permettre l’écriture de lignes qui ne
respectent pas ce format ?
R. Grin Java : sécurité page 67
Une solution
Écrire une classe spéciale, seule autorisée à
écrire dans le fichier (utiliser son codebase dans le
fichier de police), comportant une méthode
ecrire qui effectue les écritures dans le fichier
password en mode privilégié
Les autres classes devront déléguer à cette
classe les écritures dans le fichier
Elles pourront ainsi enregistrer dans le fichier,
mais sans risquer de casser le format du fichier
Sans le mode privilégié, elles n’auraient pas eu
le droit d’écrire dans le fichier
R. Grin Java : sécurité page 68
Exemple de code privilégié
static void ecrire(final String s) throws IOException {
if (pas bon format)
throw new IOException("Mauvais format");
try {
[Link](
new PrivilegedExceptionAction() {
. . .
public Object run() throws IOException {
Ecriture de s dans le fichier password
}
});
} catch(PrivilegedException e) { Renvoie
throw [Link]();
l’exception
}
}
levée par run()
R. Grin Java : sécurité page 69
Threads et héritage du contexte
pour le contrôle d'accès
Quand un nouveau thread est créé, le
contexte pour le contrôle d'accès est hérité
par ce thread
L'héritage se fait au moment de la création et pas du
lancement du thread
R. Grin Java : sécurité page 70
Les fichiers de
police de sécurité
R. Grin Java : sécurité page 71
Configuration de la sécurité
Les grandes lignes pour la sécurité sont
configurées par le fichier de propriétés
<[Link]>/lib/security/[Link]
où <[Link]> est le répertoire où est
installé le programme jre (Java Runtime
Environment), en général le sous-répertoire
jre du répertoire où a été installé le SDK
R. Grin Java : sécurité page 72
Fichiers de police (.policy)
Ces fichiers sont utilisés pour définir les droits
des classes Java
Leur emplacement est donné par les propriétés
[Link].n (n=1, 2,…) du fichier de
propriétés [Link]
La convention est de donner l'extension
.policy aux fichiers de police
R. Grin Java : sécurité page 73
Emplacement par défaut des
fichiers de police (.policy)
Polices « système » et « utilisateur » :
[Link].1=
file:${[Link]}/lib/security/[Link]
[Link].2=
file:${[Link]}/.[Link]
S'il n'existe pas de fichiers de polices, la politique
de sécurité correspond aux restrictions du bac à
sable des applets (presque rien n'est autorisé)
Valeur de la propriété [Link]
R. Grin Java : sécurité page 74
Ajouter un fichier de police
Remplace les fichiers de
Nom d'un fichier
police par défaut si « == »
2 moyens pour ajouter un fichier :
n option -[Link]=maPolice
des commandes java ou appletviewer
n ajouter une propriété [Link].n dans un
fichier de propriété ; par exemple,
[Link].3=file:${[Link]}/mapolice
La 1ère solution est la meilleure pendant les tests
Remarque : ne pas oublier l’option
–[Link]
R. Grin Java : sécurité page 75
Contenu des fichiers de police
Un fichier de police de sécurité contient des entrées
du type grant (signedBy et codeBase sont
optionnels) :
grant signedBy "signataires", codeBase "url"
{
permission1; Ne pas oublier les « ; »
permission2; en particulier celui-ci !!
};
Il peut aussi contenir une entrée keystore :
keystore "emplacement", "type";
jks par défaut (format de Sun)
R. Grin Java : sécurité page 76
Exemple de fichier
de police de sécurité
// Un commentaire
keystore ".keystore";
grant signedBy "toto" {
permission [Link]
"${[Link]}${/}-", "read";
};
grant codeBase "[Link] {
permission [Link]
"[Link]", "read";
};
R. Grin Java : sécurité page 77
Entrée grant
Une entrée grant commence par grant suivi
optionnellement d'un signedBy et/ou d'un
codeBase (dans un ordre quelconque) : Signé par tous
grant (relation et, pas ou)
grant signedBy "signataire[,signataire2,…]"
grant codeBase "unURL"
grant signedBy "signataire" codeBase "uneURL"
Permission donnée au code qui vient de cet URL
(permission donnée à tous si pas de signedBy)
R. Grin Java : sécurité page 78
URL pour le codeBase
Différentes significations selon la fin de l'URL :
n "/" désigne toutes les classes (pas les JAR)
situées dans le répertoire placé avant le "/"
n "/*" désigne toutes les classes (y compris les
classes dans les fichiers JAR) situées dans le
répertoire
n "/-" désigne toutes les classes (y compris les
classes dans les fichiers JAR) situées dans
l'arborescence du répertoire
Si le codeBase désigne un répertoire, les classes se
trouvent dessous avec les chemins correspondant à
leur paquetage
R. Grin Java : sécurité page 79
Format des URL
Le séparateur est « / » dans tous les systèmes
(même sous Windows ou MacOS) : la notion d'URL est
« universelle » et ne doit pas dépendre d'un système
particulier
L’URL d’un fichier local commence par
« file: »
Exemples d’URL sous Windows :
R. Grin Java : sécurité page 80
Entrée permission
Le format standard est
permission classePermission "but", "action";
n classePermission indique le type de permission
que l'on donne (nom d'une classe de permission)
n but indique sur quel objet on donne la permission
n action indique quel type d'action on autorise sur
le but
Certaines permissions peuvent ne pas avoir d’action, ni
même de but
Une permission peut comporter une clause signedBy
"noms…" (classePermission doit être signée)
R. Grin Java : sécurité page 81
Quelques classes de permissions
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
[Link]
R. Grin Java : sécurité page 82
Exemples de permissions
Les classes placées à la racine du serveur Web de
machine ont la permission de lire les fichiers de
/tmp et le droit de lire les valeurs de toutes les
propriétés comme [Link] ou [Link]
grant codeBase "[Link] {
permission [Link] "/tmp/*",
"read";
permission [Link]
"user.*", "read";
};
R. Grin Java : sécurité page 83
Exemples de permissions (2)
Toutes les classes peuvent se connecter partout par
socket et peuvent lire tous les fichiers du répertoire
indiqué
grant {
permission [Link] "*",
"connect";
permission [Link]
"C:\\users\\truc\\*", "read";
};
Doubler les "\"
sous Windows
R. Grin Java : sécurité page 84
Exemples de permissions (3)
Permission de lire les fichiers du répertoire HOME de
l'utilisateur
Cet exemple utilise la valeur de la propriété système
[Link] (${[Link]}), et ${/} qui
désigne le séparateur utilisé dans les noms de
fichiers (qui dépend du système d'exploitation)
grant {
permission [Link]
"${[Link]}", "read";
permission [Link]
"${[Link]}${/}*", "read";
};
R. Grin Java : sécurité page 85
Exemples de permissions (4)
Certaines permissions n'ont pas d'action :
permission [Link]
"getClassLoader";
Ou même pas de but comme la permission
AllPermission
R. Grin Java : sécurité page 86
Exemples de permissions (5)
Si on veut tester du code indépendamment des
problèmes d’autorisation, on peut donner
momentanément toutes les permissions
grant {
permission [Link];
};
Très dangereux ! Ne jamais utiliser un tel fichier
de police en production ni même quand
l’ordinateur est connecté à Internet
À n’utiliser qu’avec l’option –D de java ; sinon,
limiter au moins la portée par un codebase
R. Grin Java : sécurité page 87
Exemples de permissions (6)
Si on veut donner l’autorisation d’accéder aux
membres non public d’une classe avec la
réflexivité, on peut donner la permission suivante :
permission
[Link]
"suppressAccessChecks";
C’est évidemment très dangereux et doit être
réservé à des classes très particulières comme les
débuggeurs ou les outils interactifs pour construire
des applications
R. Grin Java : sécurité page 88
BasicPermission
Les derniers exemples de permissions,
comme les PropertyPermission sont des
classes filles de BasicPermission
Elles permettent de donner un nom de but
hiérarchique de type [Link], qui peut
comporter un « * » à la place d’un des noms
Par exemple,
permission [Link]
"user.*"
donne des permissions sur les propriétés
[Link], [Link], [Link],…
R. Grin Java : sécurité page 89
FilePermission
Le but peut être de plusieurs types :
n fichier ou répertoire
n repertoire/* (ou *) : fichiers ou répertoires situés
juste sous repertoire
n repertoire/- (ou -) : fichiers ou répertoires situés
dans l'arborescence de repertoire
n <<ALL FILES>>
Attention, repertoire/* et repertoire/- ne
donnent pas la permission sur le répertoire lui-
même !
Pour Windows, remplacer « / » par « \\ » ou par
« ${/}
R. Grin Java : sécurité page 90
FilePermission
L'action peut être read, write, delete, execute,
mais pas "read,write" (2 entrées sont nécessaires)
R. Grin Java : sécurité page 91
Exemples de FilePermission
grant {
permission [Link] "/tmp/*
"read;
};
grant codeBase "[Link]
signedBy "paul" {
permission [Link]
"C:\\users\\bibi\\*", "write";
};
R. Grin Java : sécurité page 92
Permissions pour le Web
Dès qu’une connexion avec une machine
distante a lieu, il est vraisemblable que des
sockets sont utilisés et on devra ajouter des
permissions [Link]
Par exemple, pour charger un fichier depuis la
machine [Link], en passant par un
serveur HTTP, on devra ajouter la permission
suivante :
permission "[Link]",
"connect,accept,resolve";
R. Grin Java : sécurité page 93
Messages d'erreur liés à la sécurité
Exception occurred during event dispatching:
[Link]: access denied
([Link] C:\ read)
at
[Link](...)
at [Link](...)
at [Link](...)
at [Link](...)
at [Link](...)
Il manque cette permission
dans les fichiers de police de sécurité
R. Grin Java : sécurité page 94
Trouver les permissions
qui manquent
Pour faire afficher les noms des permissions
nécessaires à l’exécution, on peut lancer une
application avec
java –[Link]=access,failure
R. Grin Java : sécurité page 95
Faire afficher les permissions
accordées à une classe
ProtectionDomain domain =
[Link]().getProtectionDomain();
PermissionCollection pcoll =
[Link]().getPermissions(domain);
Enumeration enum = [Link]();
while ([Link]()) {
Permission p =
(Permission)[Link]();
}
R. Grin Java : sécurité page 96
Repérer la bonne JVM
Si malgré tous vos efforts, l’applet ou
l’application refuse de tenir compte de vos
fichiers de permissions, vous vous trompez
peut-être de JVM
Il est en effet possible d’avoir plusieurs JVM
sur une machine, en particulier quand on
utilise un navigateur Web qui a sa propre
JVM, ou qui utilise le plugin Java de Sun,
avec sa propre JVM
R. Grin Java : sécurité page 97
Entrée keystore
keystore "urlFichier" [, "type"];
Cette entrée est obligatoire dès qu'une entrée
grant fait référence à une signature
Elle doit alors être unique
Elle peut être n'importe où dans le fichier de police
emplacement est un URL absolu, ou relatif à
l'emplacement du fichier de police de sécurité
type définit le format de stockage et de cryptage
des informations contenues dans le fichier
n "jks" est un type défini par Sun ; c'est le type par défaut
R. Grin Java : sécurité page 98
Cryptographie
R. Grin Java : sécurité page 99
Concepts pour la cryptographie
R. Grin Java : sécurité page 100
Échanger des messages confidentiels
On veut
n confidentialité : seul le destinataire peut lire le
message
n authentification de l’expéditeur
n intégrité du contenu du message : un tiers ne
peut modifier le message sans que ça se voit
n non-répudiation : l’expéditeur ne peut nier
avoir envoyer le message et le destinataire ne
peut nier l’avoir reçu
R. Grin Java : sécurité page 101
Cryptographie
Science et techniques pour chiffrer des
informations
Les algorithmes reposent sur la notion de clé
Une clé est une information utilisée pour
chiffrer ou déchiffrer une information
2 types principaux d’algorithmes de
chiffrement/déchiffrement :
n à clé cachée (ou symétrique)
n à clé publique (ou asymétrique)
R. Grin Java : sécurité page 102
Dans ce cours nous n'étudierons pas les
algorithmes de chiffrement, ni le chiffrement
des messages
Nous verrons comment
n signer des documents
n fournir des certificats pour assurer
—l'authentification de l'auteur d'un message
—l'intégrité du message
—la non-répudiation de l'auteur du message
R. Grin Java : sécurité page 103
Cryptographie à clé cachée
C’est la plus ancienne technique de
cryptographie
Une même clé permet de chiffrer et de
déchiffrer les messages
Cette clé doit être partagée par l’expéditeur et
le destinataire
R. Grin Java : sécurité page 104
Problèmes de la cryptographie
à clé cachée
Comment s’échanger la clé ?
Si un tiers peut intercepter la clé pendant
l’échange, il peut lire tous les messages
R. Grin Java : sécurité page 105
Comparaison clé cachée -
clé publique
La cryptographie à clé publique n’a pas le
problème de la transmission de la clé
Les possibilités sont plus riches avec la
cryptographie à clé publique
Mais le chiffrement/déchiffrement est souvent
plus rapide avec une clé cachée
R. Grin Java : sécurité page 106
Cryptographie à clé publique
Chaque acteur (expéditeur ou destinataire) a
2 clés différentes :
n une clé publique connue de tous
n une clé privée connue seulement par
l’acteur
Un message chiffré avec une des 2 clés est
décryptée avec l'autre clé
Permet d’éviter le problème d’échange de clé
symétrique et offre de nouvelles possibilités
R. Grin Java : sécurité page 107
Principe essentiel de la
cryptographie à clé publique
Les 2 clés sont générées par des algorithmes
qui s’appuient sur des théories mathématiques
(arithmétique des grands nombres premiers) qui leur
assurent la propriété suivante :
n il est facile de chiffrer un message avec la clé
publique
n il est extrêmement difficile de déchiffrer le
message si on ne connaît pas la clé privée
R. Grin Java : sécurité page 108
Infrastructure à clé publique
L’utilisation des clés publiques-privées
impose la gestion et mise à disposition des
clés publiques, la certification des identités
associées à ces clés
Des tiers effectuent ces tâches : autorités
d’enregistrement et de certification
Pour travailler à grande échelle avec les clés
publiques il est donc nécessaire d’installer
une infrastructure à clé publique (ICP en
abrégé, PKI en anglais)
R. Grin Java : sécurité page 109
Utilisation de la cryptographie
à clé publique
Nous allons étudier comment elle permet
n la confidentialité
n l’authentification
n la non-répudiation
n l’intégrité
R. Grin Java : sécurité page 110
Chiffrement avec clé publique
Envoi d’un message chiffré :
1. l’expéditeur chiffre son message avec la clé
publique du destinataire (elle est connue de
tous)
2. le destinataire déchiffre avec sa clé privée,
restée chez lui bien en sécurité
On assure ainsi la confidentialité et
l’authentification du destinataire
Pour l’intégrité, l’authentification et la non-
répudiation de l’expéditeur, il faut ajouter
une signature
R. Grin Java : sécurité page 111
Signatures digitales
R. Grin Java : sécurité page 112
Signature
Une signature numérique à clé publique
permet :
n authentification de l’expéditeur
n intégrité : vérifier que ces données n'ont
pas été modifiées depuis que le document
a été signé
n non répudiation : le signataire ne peut pas
nier avoir signé le document
R. Grin Java : sécurité page 113
Cryptage
Un message peut être crypté avec une clé
publique ; ce message pourra être décrypté par
la clé privée correspondante
Ce sens sert à transmettre des messages
secrets
Un message peut être crypté avec une clé
privée ; ce message pourra être décrypté par la
clé publique correspondante
Ce sens sert pour les signatures digitales
R. Grin Java : sécurité page 114
Propriétés des signatures
à clés asymétriques
Elle permet d'affirmer que le signataire du
message a bien une certaine clé publique
Elle ne peut être imitée si on ne connaît pas la
clé privée du signataire
R. Grin Java : sécurité page 115
Résumé
Un résumé (message digest en anglais) est
une information de taille fixe calculée à partir
du contenu du message par une fonction de
hachage
La taille du résumé est bien plus petite que la
taille du message
R. Grin Java : sécurité page 116
Fonctions de hachage
Une fonction de hachage h : T → C associe à
tout texte T un condensé (empreinte, résumé)
C de longueur fixe de ce texte
Une bonne fonction de hachage h a les
propriétés suivantes :
n il est facile de calculer C
n il est très difficile (sinon impossible) de calculer T
à partir de C
n il est très difficile de trouver T' tel que h(T) = h(T')
n h est « presque injective » ; si T1 ≠ T2, il est
« presque sûr » que h(T1) ≠ h(T2)
R. Grin Java : sécurité page 117
Fonctions de hachage
Les fonctions les plus couramment utilisées :
n MD5 (128 bits)
n SHA
n SHS (160 bits)
R. Grin Java : sécurité page 118
Comment signer
Une signature est composée en chiffrant un
résumé du message avec la clé privée du
signataire
Le destinataire va décrypter le résumé avec la
clé publique du signataire
Si le résultat du décryptage correspond bien au
résumé du message reçu, ça signifie que
n le signataire est bien le bon (celui qui a cette clé
publique)
n le message n’a pas été modifié depuis le calcul de la
signature
R. Grin Java : sécurité page 119
Envoi par E de données signées
Hachage Données
Signature
Résumé
Identité
Transmis au
Clé destinataire
Cryptage
privée
de E
R. Grin Java : sécurité page 120
Réception par R des données
Données Hachage Résumé
Comparaison
Signature
Décryptage Résumé
Identité
Reçu par le
destinataire Clé publique
Clé
Mais ça ne marche que si Lit clé publique
celui qui reçoit a déjà la clé expéditeur de E
publique de l'expéditeur
R. Grin Java : sécurité page 121
Certificats
R. Grin Java : sécurité page 122
Association clés-identités
Celui qui reçoit un message signé doit
posséder la clé publique du signataire et avoir
un moyen d’associer cette clé publique à
l’identité du signataire (base de donnée ou autre)
Imaginez le travail pour
n recevoir et gérer les milliers de clés
publiques des clients et des partenaires
n s’assurer que ces clés publiques
appartiennent bien à ces correspondants
R. Grin Java : sécurité page 123
Certificats
Comment ça se passe en réalité :
Le plus souvent, celui qui reçoit le message
n'a pas la clé de l'expéditeur
La clé publique du signataire est transmise
avec le message, dans un certificat qui
associe cette clé avec l’identité du signataire
R. Grin Java : sécurité page 124
Utilisation des certificats
Comment avoir confiance en ce certificat ?
Ce certificat est signé par une autorité publique
de certification (comme Verisign) qui a une clé
publique bien connues de tous (ou il existe des
moyens sûrs et faciles de l’obtenir)
On se retrouve alors dans le cas où on connaît
la clé de l'expéditeur des données (la donnée
est le certificat) ; on peut donc s'assurer que le
certificat contient des données exactes
On a donc la clé publique de l'expéditeur, et on
peut donc vérifier la signature des données
R. Grin Java : sécurité page 125
Ce que contient un certificat
L’autorité fournit un certificat signé par elle, qui
contient
n des informations sur le possesseur du
certificat : nom, adresse, etc.
n la clé publique de ce possesseur
n des informations liées au certificat : dates de
validation, numéro de série, etc.
R. Grin Java : sécurité page 126
Ce qui est envoyé
Un certificat
est un message MESSAGE
signé.
Si on connaît
la clé publique Signature
de l'autorité,
et si on a CERTIFICAT
confiance en
Clé publique de E
cette autorité,
on peut être sûr Informations sur possesseur
des informations
Signature de l’autorité
qu'il contient.
Informations sur le certificat
R. Grin Java : sécurité page 127
Stockage des clés
Toute application Java peut avoir un lieu de
stockage des clés publiques
Cette base de données contient des clés
publiques et des chaînes de certificats qui
authentifient les clés publiques
Elle peut aussi contenir des clés privées locales
(celles de l'utilisateur de l'application) avec leurs
chaînes de certificats
Des mots de passe peuvent être associés au
lieu de stockage et à chacune des clés
R. Grin Java : sécurité page 128
Entrepôt des certificats par défaut
Par défaut les certificats sont entreposés
dans le fichier [Link]/lib/security/cacerts
([Link] est le répertoire jre d’installation
de java)
Pour lister les certificats : keytool -list
On peut indiquer un autre fichier entrepôt :
keytool –list –file entrepot
R. Grin Java : sécurité page 129
Envoi de données signées
Hachage Données
Signature
Résumé
Certificat
Clé
privée de E Cryptage Transmis au
destinataire
certificat
R. Grin Java : sécurité page 130
Réception des données
Données Hachage Résumé
Signature Comparaison
Certificat Décryptage Résumé
Reçu par le
destinataire Clé publique
de E vérifiée
Clé
Extraction publique
clé autorité
R. Grin Java : sécurité page 131
La chaîne de vérification
Le vérificateur du certificat doit déjà connaître la
clé publique de l'autorité de certification
(appelons-la CA1)
Sinon, le vérificateur doit avoir un certificat, émis
par une autorité de certification CA2 dont il
connaît la clé publique, et qui authentifie la clé
publique de CA1
On peut ainsi avoir une chaîne de certificats
signés par CA1, CA2, CA3, ...
Cette chaîne confirme l'identité du signataire si
un des certificats a été signé par une autorité
déjà connue par le vérificateur
R. Grin Java : sécurité page 132
Comment obtenir un certificat
1. Génération d’une paire de clés publique-privée
2. Fournir à l’autorité qui délivre le certificat
n la clé publique
n des documents qui certifient l’identité
3. L’autorité fournit un certificat signé par elle, qui
permet d'associer la clé publique et l'identité
Pour les cas de diffusion restreinte, on peut se contenter
d'un certificat auto-signé que l'on distribue aux
utilisateurs
R. Grin Java : sécurité page 133
Types de certificats
Les autorités universellement connues ne sont
pas les seules à délivrer des certificats
Un organisme peut aussi utiliser en interne sa
propre autorité de certification
Un certificat peut aussi être auto-signé, c'est-à-
dire signé par la personne qui est authentifiée
par le certificat (convient si le destinataire connaît la
clé publique de celui qui a signé)
R. Grin Java : sécurité page 134
Plugin Java pour
les navigateurs Web
R. Grin Java : sécurité page 135
Qu’est-ce que c’est ?
Sun fournit un plugin Java pour les
navigateurs Web qui permet aux applets de
s’exécuter indépendamment de la version de
la machine virtuelle Java installée dans le
navigateur
Des informations sur le plugin en
[Link]
FAQ :
[Link]
in/developer_guide/faq/[Link]
R. Grin Java : sécurité page 136
Installation du plugin
Ce plugin s’installe sur la machine d’un client
Web en même temps que le JRE Java
S’il n’est pas installé, l’applet peut demander
son installation
L’installation est longue mais elle ne se fait
qu’une fois ; les applets suivantes pourront
utiliser le plugin installé par la première applet
R. Grin Java : sécurité page 137
Pratique de la signature avec les
outils fournis par Sun
R. Grin Java : sécurité page 138
Outils pour la sécurité
policytool facilite la saisie d'une police de
sécurité (évite les fautes de syntaxe que l’on peut
faire si on modifie « à la main » les fichiers de police)
jarsigner permet de signer un fichier JAR ou
de vérifier sa signature
keytool permet de gérer des clés et des
certificats
R. Grin Java : sécurité page 139
Algorithmes utilisés dans les API
Fonction de hachage par défaut : SHA1
Chiffrement par défaut pour les signatures :
DSA, ce qui donne l'algorithme de signature
de nom interne SHA1withDSA
Autres possibilités : MD2withRSA, MD5withRSA,
SHA1withRSA
Certificats selon la norme X.509
R. Grin Java : sécurité page 140
Nous allons donner 2 exemples concrets :
n signer du code qui sera exécuté par un
autre (une applet)
n signer un document que l'on envoie à un
autre
R. Grin Java : sécurité page 141
Créer les clés
Création des clés privée et publique de toto, et
d'un certificat auto signé valable 90 jours (rangés
dans le fichier .keystore) :
> keytool -genkey -alias toto -keystore .keystore
Enter keystore password: abc123
créé s'il n'existe
What is your first and last name? pas ; par défaut
[Unknown]: Pierre Toto $HOME/.keystore
What is the name of your organizational unit?
[Unknown]: Dept informatique
What is the name of your organization?
[Unknown]: UNSA
What is the name of your City or Locality?
[Unknown]: Nice
. . .
R. Grin Java : sécurité page 142
Obtenir un certificat
Obtenir un certificat (ou une chaîne de
certificats) pour certifier la clé publique de toto,
émis par une autorité publique connue ; pour
cela on envoie la clé publique et les documents
demandés par l'autorité pour identifier toto
Remplacer le certificat auto-signé de toto par ce
nouveau certificat (rangé dans le fichier reponseCA),
dans le fichier .keystore de toto :
> keytool -import -alias toto
-keystore .keystore -file reponseCA
Cette étape n'est pas obligatoire, on peut se contenter
du certificat auto-signé
R. Grin Java : sécurité page 143
Exporter un certificat
Exporter le certificat :
> keytool -export -alias toto
–keystore .keystore -file [Link]
Ce certificat pourra être importé dans la base de
données des clés de celui qui fera confiance à
toto
R. Grin Java : sécurité page 144
Signer un fichier jar
Créer le fichier [Link]
> jar cvf [Link] [Link]
toto signe le fichier [Link] qui ajoute son
certificat au contenu du fichier [Link]
> jarsigner -keystore .keystore
-signedjar [Link] [Link] toto
R. Grin Java : sécurité page 145
Exemple de fichier [Link]
d'un fichier jar signé
Manifest-Version: 1.0
Created-By: 1.3.0 (Sun Microsystems Inc.)
Name: [Link]
SHA1-Digest: mOaQUgZhHj1ksr53hHk/FAGLdWE=
Name: rep/[Link]
SHA1-Digest: xrQEm9gZhHj1ksr53hHkYV4XIt0=
résumé du fichier
R. Grin Java : sécurité rep/[Link] page 146
Etapes à la réception des messages
L'utilisateur qui recevra de toto le fichier signé
va vérifier que c'est bien toto qui a signé
1. il vérifie d'abord que le certificat de toto qu'on lui a
envoyé contient des informations qui
correspondent aux informations qu'il a reçu par
d'autres voies fiables
2. il doit tout d'abord importer le certificat de toto
dans sa base de clés
2. il peut ensuite utiliser cette base de clé en
donnant son emplacement dans le fichier de
police de sécurité (entrée "keystore")
R. Grin Java : sécurité page 147
Importer un certificat
Vérifier le certificat en comparant les
informations imprimées par keytool avec des
informations fiables obtenues par ailleurs :
keytool -printcert -file [Link]
Importer le certificat de toto utilisateur en qui
on peut avoir confiance :
keytool -import -alias toto
-file [Link] -keystore .keystore
R. Grin Java : sécurité page 148
Certificats révoqués
Java ne vérifie pas auprès de l’autorité de
certification si le certificat a été révoqué (en
cas, par exemple, de vol ou de certificat
attribué par erreur)
Pour les cas où une sécurité renforcée est
nécessaire, il faudra ajouter du code pour
effectuer cette vérification
R. Grin Java : sécurité page 149
Signature et plugin Java
Depuis la version JDK 1.3, une applet signée
et certifiée peut avoir tous les droits si
l’utilisateur déclare avoir confiance dans cette
applet signée (le navigateur lui pose la
question)
Cette fonctionnalité a été ajoutée pour
faciliter l’exécution des applets sans
installation de fichiers de police de sécurité
spéciaux chez les clients Web
R. Grin Java : sécurité page 150
Signature et plugin Java
Mais cette possibilité peut être jugée
dangereuse
Le fichier de police de sécurité du client peut
comporter une ligne
permission [Link]
"usePolicy";
pour indiquer que seule la police de sécurité
doit être examinée, et que même une applet
signée devra s’y tenir
R. Grin Java : sécurité page 151
Signature et plugin Java
Le plugin Java a changé de politique de sécurité
à chaque version du jre, ce qui ne favorise pas
la portabilité
Les fonctionnalités ont été ajoutées pour faciliter
le déploiement des applets
n avec le jre 1.2, seuls les fichiers de police de sécurité
sont pris en compte
n avec le jre 1.3, il n’est pas tenu compte de ces fichiers
de police si l’applet est signée avec un certificat
obtenu par une autorité connue de certification, et si
l’utilisateur affirme avoir confiance en ce certificat
n avec le jre 1.4, ça marche aussi avec les certificats
auto-signés
R. Grin Java : sécurité page 152
Compléments
R. Grin Java : sécurité page 153
Protéger les paquetages
Par défaut, les paquetages ne sont pas protégés
Un programmeur peut ajouter une classe dans
n’importe quel paquetage et avoir ainsi accès à
tous les membres des classes du paquetage qui
ont un accès réservé au paquetage
On peut empêcher l’ajout de nouvelles classes
dans les paquetages par divers moyens :
n par les mécanismes de protection liés aux fichiers de
polices de sécurité
n par les fichiers jar "scellés"
R. Grin Java : sécurité page 154
Protéger des paquetages avec les
fichiers de sécurité
On peut empêcher
n le chargement direct d’une classe d’un paquetage
n l’ajout de nouvelles classes dans un paquetage
Pour commencer, il faut ajouter des entrées dans le
fichier de sécurité (.security)
Ces entrées sont des listes de noms séparés par des « , » ;
tout paquetage dont le nom commence ainsi est protégé
Pour empêcher le chargement direct :
[Link]=[Link],[Link]
Pour empêcher l’ajout de nouvelles classes :
[Link]= [Link],[Link]
R. Grin Java : sécurité page 155
Permissions pour les paquetages
Si on a protéger un paquetage on peut autoriser
l’action interdite en ajoutant des entrées dans les
fichiers de police de sécurité (.policy)
L’autorisation suivante permettra un accès direct aux
classes du paquetage [Link]
RuntimePermission
"[Link]"
De même, il faudra ajouter une autorisation
« RuntimePermission "defineClassInPackage.." »
pour permettre l’ajout d’une classe dans un
paquetage
R. Grin Java : sécurité page 156
Exemple
grant codeBase "http:[Link]/-" {
[Link]
"[Link]";
};
R. Grin Java : sécurité page 157
Prise en compte
des protections des paquetages
La protection des paquetage n’est pas
vraiment prise en compte par les chargeurs
de classes de la version 1.3
La protection d’accès n’est prise en compte
que par la classe URLClassLoader, et
encore, seulement si l’instance du chargeur
de classes a été obtenue par la méthode
static newInstance() et pas par new
La protection pour l’ajout d’une classe dans
un paquetage n’est prise en compte par
aucun chargeur de classes
R. Grin Java : sécurité page 158
Fichiers jar scellés
L'entrée "Sealed: true" dans la section
principale du fichier MANIFEST d'un fichier
jar empêche l'ajout de classes des
paquetages de ce fichier, venant d'une autre
source que ce fichier jar
On peut aussi ne protéger que certains
paquetages du fichier jar en donnant des
entrées du type
Name: fr/unice/p1
Sealed: true
R. Grin Java : sécurité page 159
Protéger des objets
On peut protéger un objet particulier
GuardedObject permet de faire garder un
objet par un autre objet qui est d'une classe
qui implémente l'interface Guard :
GuardedObject go = new GuardedObject(
new ClasseProtegee(…),
new GardeObjet(…));
La classe
implémente
l’interface Guard
R. Grin Java : sécurité page 160
Interface Guard
Elle contient la seule méthode checkGuard()
qui doit lancer une SecurityException si
l'accès à l'objet est interdit
Cette interface est implémentée par les classes
filles de la classe [Link]
Dans ce cas, checkGuard() fait un appel à
[Link](this);
R. Grin Java : sécurité page 161
Exemple
Si on garde un objet avec une instance de
FilePermission, l'accès à l'objet sera
autorisé dans les mêmes conditions que
l'accès à un certain fichier
Avec le code suivant, objet ne pourra être
récupéré que par le code qui aura
l’autorisation de lire le fichier /rep1/fichier :
GuardedObject go =
new GuardedObject(
objet,
new FilePermission("/rep1/fichier",
"read"));
R. Grin Java : sécurité page 162
Récupération de l’objet
Quand on veut récupérer l'objet protégé, on
appelle la méthode getObject() de la
classe GuardedObject
getObject() fait un appel automatique à la
méthode checkGuard() qui lancera une
SecurityException pour signaler que
l'accès à l'objet est interdit
R. Grin Java : sécurité page 163
JAAS
(Java Authentification and
Authorization Service)
R. Grin Java : sécurité page 164
Présentation
Le mécanisme des autorisations de Java 2
est centré sur le code : les permissions sont
données ou non selon l’origine du code (d’où
vient-il, qui l’a signé)
JAAS est centré sur l’utilisateur : il va
permettre de donner des permissions en se
basant sur l’utilisateur qui exécute le code
Les utilisateurs doivent s’authentifier et
certaines parties du code ne pourront être
exécutées que par les utilisateurs autorisés
R. Grin Java : sécurité page 165
Concepts de base de JAAS
Sujet (subject) : représente une entité
authentifiée ; utilisateur, administrateur,
service Web, processus,…
Identité (principal) : une des identités d’un
sujet ; un sujet peut en avoir plusieurs, sur le
modèle d’un utilisateur qui peut avoir
plusieurs noms pour des services différents,
un numéro de sécurité sociale, une adresse
mail, etc.
Pièce d’identité (credential) : justificatif pour
une identité ; peut être un objet quelconque
R. Grin Java : sécurité page 166
Paquetages et quelques classes
Depuis la version 1.4, JAAS est inclus dans le
J2SE
[Link] contient la classe
Subject
[Link] contient la
classe LoginContext
[Link] contient
l’interface LoginModule
R. Grin Java : sécurité page 167
Paquetages et quelques classes
[Link] contient
les interfaces Callback et CallbackHandler,
et quelques classes qui implémentent
Callback
R. Grin Java : sécurité page 168
2 parties dans JAAS
L’authentification de l’utilisateur (souvent
avec un système de mot de passe)
Les autorisations, liées à l’utilisateur qui s’est
authentifié, qui s’ajoutent au système des
autorisations de Java 2 déjà étudié
R. Grin Java : sécurité page 169
Exemple minimal de code
LoginContext lc = new LoginContext("Appli1");
try {
[Link]();
}
catch(LoginException e) {
// Le login n’a pas marché
. . .
}
Subject sujet = [Link]();
[Link](sujet, new ActionProtegee());
R. Grin Java : sécurité page 170
Authentification
Elle est effectuée par une instance de la
classe LoginContext
Quand on crée cette instance, on lui passe
un nom qui va permettre à JAAS de savoir
comment se fera l’authentification de
l’utilisateur
Ce nom correspond à une entrée dans un
fichier de configuration
R. Grin Java : sécurité page 171
Emplacement du
fichier de configuration
Il peut être donné par
n la propriété Java
[Link]
n une ou plusieurs entrées dans le fichier
[Link] :
[Link].1=file:${[Link]}/
lib/security/[Link]
R. Grin Java : sécurité page 172
Fichier de configuration
Il contient des entrées qui indiquent quels
modules de login devront être utilisés :
entree1 {
ClasseModule1 flag options;
ClasseModule2 flag options;
. . .
}
entree2 {
. . .
}
R. Grin Java : sécurité page 173
Exemple de fichier de configuration
Appli1 {
[Link] Required
driver="[Link]"
url="jdbc:mysql://[Link]/jaas?user=adm"
debug="true";
}
Appli2 {
[Link] Required
fichier="rep/motdepasse";
}
R. Grin Java : sécurité page 174
Système de plugin
Le LoginContext utilise des plugins, appelés
modules de login, qui permettent d’authentifier
l’utilisateur suivant différents modes
R. Grin Java : sécurité page 175
Modules de login
Le paquetage [Link]
contient des modules JAAS pour authentifier
avec :
n nom et mot de passe Unix
(UnixLoginModule), ou NT (NTLoginModule)
n un service JNDI (JndiLoginModule)
n le protocole Kerberos (Kbr5LoginModule)
n une clé enregistrée dans un fichier KeyStore
(KeyStoreLoginModule)
R. Grin Java : sécurité page 176
Modules de login
On peut aussi écrire ses propres modules de
login, ou les acheter ; par exemple des modules
pour authentifier avec
n un nom et mot de passe enregistrés dans une
base de données, ou un fichier
R. Grin Java : sécurité page 177
Autorisations
Une fois que l’utilisateur s’est authentifié, on
peut récupérer une instance de Subject par
[Link]()
Ensuite, on peut limiter certaines actions à des
utilisateurs particuliers
L’exécution de ces actions devra être lancée par
la méthode static doAs de la classe
Subject ; par exemple :
ActionSpeciale action =
new ActionSpeciale();
[Link](subject, action);
R. Grin Java : sécurité page 178
Interface PrivilegedAction
Les actions passées à la méthode doAs doivent
appartenir à une classe qui implémente l’interface
PrivilegedAction
Cette interface contient la méthode run() qui
contient l’action à exécuter
La méthode doAs renvoie un Object, renvoyé
par la méthode run()
Comme avec la méthode doPrivileged étudiée
avant, si une action peut lancer des exceptions,
elle doit implémenter
PrivilegedExceptionAction
R. Grin Java : sécurité page 179
Mode privilégié
Une méthode doAsPrivileged permet de
lancer l’action dans un autre contexte
d’exécution (en mode privilégié si on lui
passe null comme contexte)
Attention à ne pas ouvrir des portes aux
pirates !
R. Grin Java : sécurité page 180
Permissions indispensables
Les classes qui créent des LoginContext
ou appellent la méthode doAsPrivileged
doivent avoir certaines autorisations :
permission
[Link]
"createLoginContext"
permission
[Link]
"doAsPrivileged"
R. Grin Java : sécurité page 181
Autorisations
Il faut ajouter des informations relatives à JAAS
dans les fichiers de police de sécurité
La syntaxe est :
grant codebase …, signed by …,
Principal classePrincipal utilisateur
{
permission . . .;
permission . . .;
}
R. Grin Java : sécurité page 182
Exemple d’autorisation
grant codebase "[Link] . . "
Principal [Link].Principal1 "pierre" {
permission [Link]
"[Link]", "read";
. . .
}
R. Grin Java : sécurité page 183
Callbacks et callbackHandlers
Le plus souvent le développeur utilisera les
classes de callbacks fournies avec l’API (ou
avec un module de login JAAS)
Ils sont dans le paquetage
[Link] : NameCallback,
PasswordCallback, TextOutputCallback,
ChoiceCallback,…
Il peut cependant avoir à écrire ses propres
callback
R. Grin Java : sécurité page 184
CallbackHandlers
Le plus souvent le développeur aura à écrire
un callbackHandler pour indiquer comment
demander des informations à l’utilisateur à
l’aide des callbacks
Il n’y en a pas dans l’API de base mais on en
trouve 2 qui demandent un nom et un mot de
passe dans le paquetage
[Link] :
DialogCallbackHandler (utilise une fenêtre de
dialogue Swing), TextCallbackHandler
(demande dans une console)
R. Grin Java : sécurité page 185
Les callbacks
Pour accroître la portabilité des applications,
la méthode login échange des informations
avec l’utilisateur à authentifier, par
l’intermédiaire d’un callbackHandler
En changeant ainsi de handler, on pourra,
par exemple, demander le nom et le mot de
passe d’un utilisateur en mode texte dans
une console, ou dans une fenêtre Swing, ou
par tout autre moyen, sans changer le code
de la méthode login
R. Grin Java : sécurité page 186
Utilité des callbacks
Les échanges avec l’utilisateur sont
déterminés par un tableau de callbacks qui
vont être passés au handler
Un callback n’a pas d’action directe avec
l’utilisateur ; il sert seulement à passer les
informations échangées entre l’application et
l’utilisateur
C’est le handler qui va, en s’aidant des
callbacks, afficher des informations à
l’utilisateur et lui demander des informations
R. Grin Java : sécurité page 187
Utilisation des callback (1)
La méthode login crée des callback, par
exemple, 2 callbacks NameCallback et
PasswordCallback
Elle lance alors un handler en lui passant les
callbacks dans un tableau
Le handler connaît les interactions qu’il doit faire
avec l’utilisateur, associées à chaque type de
callback
Il peut interroger un callback (méthodes getXXX)
s’il veut des précisions ; pour obtenir, par
exemple, un texte à afficher à l’utilisateur
R. Grin Java : sécurité page 188
Utilisation des callback (2)
Le handler met dans les callback les
informations recueillies auprès de l’utilisateur
(méthodes setXXX)
La méthode login récupère ces informations
avec les méthodes getXXX de la classe du
callback
R. Grin Java : sécurité page 189
Exemple de callback
NameCallback implémente l’interface « marqueur »
Callback (obligatoire)
Il a les 2 constructeurs (utilisés au début de la
méthode login) :
n NameCallback(String prompt)
n NameCallback(String prompt, String nomParDefaut)
Il a les méthodes suivantes :
n getPrompt()
n getName()
n setName(String nom)
n getDefaultName()
R. Grin Java : sécurité page 190
Écrire un CallbackHandler
Il doit implémenter l’interface
CallbackHandler, c’est-à-dire implémenter la
méthode void handle(Callback[])
Un exemple est donné dans le tutorial
distribué avec le J2SE
(docs/guide/security/jaas/tutorials)
R. Grin Java : sécurité page 191
JCA/JCE
R. Grin Java : sécurité page 192
Les 2 APIs
L’API pour la cryptographie est partagée en 2
parties à cause des restrictions d’exportation
dans certains pays en dehors des États-Unis
JCA (Java Cryptography Architecture) est
livrée avec le SDK ; elle contient le
paquetage [Link] ; elle est
exportable
JCE (Java Cryptography Extension) est une
extension ; elle contient le paquetage
[Link] ; elle n’est pas exportable
dans tous les pays
R. Grin Java : sécurité page 193
Annexes
R. Grin Java : sécurité page 194
Fichier .security par défaut
[Link].1=[Link]
[Link].2=[Link]
[Link]=[Link]
[Link].1=file:${[Link]}/lib/security/java
.policy
[Link].2=file:${[Link]}/.[Link]
[Link]=true
[Link]=true
[Link]=false
[Link]=jks
[Link]=[Link]
ase
[Link]=sun.
R. Grin Java : sécurité page 195
Fichier .policy par défaut
grant codeBase "file:${[Link]}/lib/ext/*" {
permission [Link];
};
grant {
permission [Link]
"stopThread";
permission [Link]
"localhost:1024-", "listen";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
R. Grin Java : sécurité page 196
Fichier .policy par défaut (suite)
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
R. Grin Java : sécurité page 197
Fichier .policy par défaut (suite 2)
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
R. Grin Java : sécurité page 198
Fichier .policy par défaut (fin)
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
permission [Link]
"[Link]", "read";
};
R. Grin Java : sécurité page 199
Principaux algorithmes
de chiffrement
DES (Data Encryption Standard), à clés
symétriques
RSA (Rivest, Shamir, Adleman), à clés
asymétriques
RC4, RC5 (Rivest), à clés symétriques
AES (Advanced Encryption Standard), tout
récent, à clés asymétriques
R. Grin Java : sécurité page 200