2010-12-14 4 views
1

Est-il possible pour une classe d'usurper son identité? Par exemple, la classe A tente d'accéder aux méthodes de classe B. Les méthodes de la classe B utilisent getClass().getName() pour tenter de vérifier la classe A pour s'assurer que c'est bien qui. L'usurpation d'identité peut-elle avoir lieu? par exemple. Classe C imite la classe A pour obtenir le getclass().getName() Classe B utilise pour les contrôles?Usurpation d'identité basée sur la classe

Si la classe B veut implémenter getClass().getName() pour des contrôles efficaces sur la méthode exemple ci-dessous, comment l'implémenter correctement dans l'exemple de code ci-dessous?

public byte[] getStoragePrivateKey(String application) { 
    if (application.getClass().getName().equals("correctClass") { 
     // Allow access to Private Key. 
    } else { 
     // Access denied 
    } 
} 

L'exemple ci-dessus est une simulation d'un applet de plug-in dans le système tente d'accéder à une base de données de serveur clé interne dans le système.

+1

Qu'est-ce que vous essayez d'atteindre? Il y a plusieurs façons d'activer la sécurité dans Java, la plus simple étant une politique de sécurité. Je voudrais d'abord jeter un coup d'oeil ici car ils vous permettent de fournir un contrôle d'accès d'une manière robuste - http://download.oracle.com/javase/1.4.2/docs/guide/security/permissions.html –

Répondre

2

Vous pouvez le faire avec plusieurs chargeurs de classe. Chaque classe laoder peut avoir une classe avec le même nom qui est différent.

Cependant, je vous suggère d'utiliser simplement des réflexions si vous pouvez contourner cette « sécurité »

Une façon plus simple d'écrire la validation est

if (application.getClass() == CorrectClass.class) { 

Une méthode améliorée pour mettre en œuvre la validation est pour utiliser

StackTraceElement[] stes = Thread.currentThread().getStackTrace(); 
if (stes[0].getClassName().equals("correctClass") { 

Cela garantit que l'appelant provient du bon nom de classe. Il peut encore être usurpé avec des chargeurs de classe.

La classe sun.misc.Unsafe utilise quelque chose comme ce dernier pour protéger la méthode getUnsafe(). Le travail standard est à faire.

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 
theUnsafe.setAccessible(true); 
Unsafe unafe = theUnsafe.get(null); 

Si vous vous demandez pourquoi Unsafe est protégé et pourquoi vous voudrez peut-être d'avoir accès un coup d'oeil à la liste des méthodes. ;)

EDIT: Unsafe.getUnsafe() utilisé pour être protégé mais n'apparaît plus dans la dernière source. Peut-être parce que le contrôle pourrait être facilement contourné. ??

+1

Bien que vous pouvez ne charge pas les fausses classes java. *, ou généralement toute classe chargée par un chargeur de classe parent. –

+1

@Tom Hawtin, pas sans casser le contrat de licence. Mais c'est techniquement possible. J'ai écrit des articles sur les utilisations d'une chaîne de compression automatique, un Runtime qui indique où les appels à gc() sont faits, etc. Terracotta modifie la classe java. * À l'exécution, Profiler injecte du code à n'importe quelle classe pour obtenir des informations supplémentaires. Cependant, je ne crois pas qu'ils chargent plusieurs copies. –

+0

@Peter Lawrey Vous pouvez remplacer des parties de la bibliothèque Java par '-Xbootclasspath' ou similaire, mais vous ne devriez pas pouvoir utiliser les chargeurs de classe pour le retirer. –

2

Cela ne fonctionnera pas: Dans votre exemple application.getClass().getName() retournera toujours "java.lang.String", car vous obtenez le type du paramètre "application". En outre, en Java, la méthode invoquée ne peut pas trouver le type à partir duquel elle est invoquée. Vous devriez donc peut-être vérifier votre conception en implémentant un autre type de contrôle d'accès.

EDIT: laissez-moi ajouter un exemple, en fonction de votre code, sur la façon dont vous pouvez essayer de vérifier le type de l'invocateur, et comment il ne serait pas éviter les invocations d'autres sources:

//Change the String for an Object, to allow the invoker pass a 
//reference to itself 
public byte[] getStoragePrivateKey(Object application) { 
    if (application.getClass().getName().equals("correctClass") { 
     // Allow access to Private Key. 
    } else { 
     // Access denied 
    } 
} 

à partir du type de référence a, l'invocation pourrait être:

B b=new B(); 
    byte[] key=b.getStoragePrivateKey(this); 

l'appeler d'une classe C « imitateur », échouerait, car cela est un C.instance de classe:

B b=new B(); 
    byte[] key=b.getStoragePrivateKey(this); 

Mais, en évitant la validation, il est aussi simple que:

B b=new B(); 
    A a=new A(); 
    byte[] key=b.getStoragePrivateKey(a);