Reflections

Status
Nicht offen für weitere Antworten.

Fischer

Mitglied
Ich habe eine Frage, die mich nun schon seit Stunden beschäftigt. Bei der Frage dreht es sich um Reflections.

Ich bin mir nicht sicher, ob ich Reflections bisher nicht bis ins Detail begriffen habe, oder ob Reflections ein Sicherheitsproblem schaffen, wie es für Java eigentlich untypisch ist.

Zwecks Selbststudium habe ich folgende Code erzeugt.

1.) Ein Test-Objekt mit einer privaten Variablen, die im Konstruktor initialisiert wird:
Code:
public class TestObject{

   private int secret;

   public TestObject(int secret){
      this.secret = secret;
   }

}
Nun ist davon auszugehen, dass die Variable secret (da private deklariert) von niemandem, außer dem Klassenprogrammierer von TestObject, einzusehen oder (noch schlimmer) zu verändern ist (Java-Geheimnisprinzip).

Nehmen wir an die Variable secret würde einen sensiblen Wert beinhalten. Nachdem ich (in der hypothetischen Person eines Hackers) nun den folgenden Code erzeugt habe, wurde ich für lange Zeit sehr Nachdenklich.

2.) Das Programm mit der main-Methode, welches an dieser Stelle stellvertretend für eine beliebige Klasse mit Referenz auf TestObject stehen soll:
Code:
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;

public class ReflectionTest{

   public static void main(String[] args){
      TestObject to = new TestObject(10);

      Class c = to.getClass();
      try{
         Field f = c.getDeclaredField("secret");
         f.setAccessible(true);
         System.out.println(f.getName() + "=" + f.get(to));
         f.setInt(to, 20);
         System.out.println(f.getName() + "=" + f.get(to));
      }catch(NoSuchFieldException nsfe){
         System.out.println(nsfe);
      }catch(IllegalAccessException iae){
         System.out.println(iae);
      }
   }

}
Über Reflection, die jedem Programmierer zugänglich ist, kann ich also private Variablen einer fremden Klasse ändern, ohne dass der Klassenprogrammierer ausdrücklich zugestimmt hat?

Der Java Optionsschalter –Djava.security.manager kann dies zwar verhindern (=> java.security.AccessControlException), der Klassenprogrammierer hat auf diesen Schalter jedoch wenig Einfluss, wenn das Programm auf einem Clientrechner läuft.

Habe ich etwas falsch verstanden, oder hätte Sun den expliziten Zugriff auf geschützte Variablen und Methoden (Zugriffs-Modifizierer package, protected oder private) nicht auch nur dann gestatten können, wenn der Klassenprogrammierer dem auch zustimmt (z.B. durch implementieren eines Funktionslosen Interfaces, wie dies beispielsweise auch bei Cloneable passiert ist)?

Wenn ich derzeit nichts übersehen habe, stehen dann nicht Cloneable und Reflections in einem (auf Prinzipfragen beruhendem) direkten Widerspruch zueinander?

Ich danke bereits jetzt für jede Antwort, die meine geistige Verwirrung offenbart ;-)
 

Schreihalz

Mitglied
Es ist zwar so, dass es dir wahrscheinlich nur ums prinzip geht, aber ich habe diese Sache mit private, protected und public nie als eine Sicherheitseinrichtung verstanden, die deine Daten schützen soll...
Viel mehr ist es doch dazu da, Fehler zu vermeiden und jede Klasse nur so zu nutzen, wie sie sich nach Aussen 'zeigt'.

Und wenn etwas wirklich 'secret' ist, dann ist es doch damit nicht getan, es als private zu deklarieren. Ausserdem wüsste ich auch gerne, ob man einfach so von aussen an ein Objekt im Arbeitspeicher kommen kann und es durch Reflections untersuchen kann... Aber dir gehts es wahrscheinlich nur ums prinzip und da muss ich dir recht geben, weil ichs nicht besser weiss :)
Eigentlich sind wir doch alle froh, dass es Reflections gibt :)

Und wenn wir sogar die .class Datei haben und hineinschauen möchten, dann haben wir doch schon Decompiler (weiss aber nicht wie gut die z.Z. sind)... Also ist hier wohl nichts sicher oder?
 

Fischer

Mitglied
Dem kann ich so nur bedingt zustimmen. Es ist zwar nicht immer damit getan etwas privat zu deklarieren, aber wie will man denn seine Objektdaten sinnvoll vor unbefugtem Zugriff schützen?

Stellen wir uns doch mal vor ein Klassenprogrammierer will eine Klasse schreiben, von der es zur Laufzeit nur ein Objekt geben darf. Bisher bin ich davon ausgegangen es wäre damit getan, ein Singleton mit privatem Konstruktor und öffentlicher get-Methode (um eine Referenz auf das eine Objekt zu bekommen) zu implementieren. Um zu verhindern, dass dieses „Sicherheitsprinzip“ später durch Vererbung und Type-Casting ausgehebelt werden kann deklariere ich die Objektklasse zusätzlich als final. Nun kann es nach meiner bisherigen Vorstellung maximal dieses eine Objekt geben. Da (sinnvollerweise) bewusst auf das implementieren der Schnittstelle Cloneable verzichtet wurde kann auch niemand eine Kopie anfertigen.

Reflections hebeln dieses Sicherheitsprinzip jedoch vollständig aus, da ich ja sogar an den privaten Konstruktor rankomme. Meiner Meinung nach hätte Sun den Zugriff auf geschützte Variablen und Methoden per Reflection, genauso umsetzen müssen wie bei Cloneable.

Gegen Decompieler kann man übrigens ja wenigstens noch anprogrammieren.
 

AlArenal

Top Contributor
Verwechselt da jemand Sicherheit mit Sichtbarkeit?

Es geht bei den Deklarationsparametern doch nicht um ein irgendwie geartetes Sicherheitskonzept, sondern mehr um eine Steuerung ähnlich einem Workflow, um eine Schnittstellendefinition.

Deiner Argmentation nach wäre sonst ein Adressoperator in C ein Hackertool, das sofort aus der Sprachdefninition entfernt gehört. Ich verstehe nicht wie du auf den Trichter kommst die Sichtbarkeitssteuerung sei als Sicherheitskonzept gedacht.

Es geht nicht um die Verhinderung von unauthorisierten Zugriffen ("Programmierer XYZ darf das nicht"), sondern um die Sicherstellung der korrekten Funktionalität seitens des Klassen-Designers. Wenn du z.B. meinst von außen mit irgendwelchen Hackentricks private Methoden von Instanzen meiner Klassen aufrufen zu müssen, musst du dich nicht wundern, wenn das Programm nicht mehr nach der Spezifikation arbeitet und schlimmstenfalls zu Datenverlust fehelrhaften Daten, Absturz, .. führt.

Dann beschwer dich aber nicht bei den Machern von Java oder mir, sondern frag dich selbst warum du meinst da drin rumpfriemeln zu müssen. Es ist nicht die Waffe die tötet, sondern der, der die Waffe bedient.
 

AlArenal

Top Contributor
P.S.:

Ich weiß auch nicht was das nun mit Reverse Engineering zu tun haben soll. Wie willst du denn mittels Reflection aus deinem selbstgefertigten Java-Hacking-Tool an Daten in meiner laufenden Java-Anwendung kommen?
 

Fischer

Mitglied
"Es geht nicht um die Verhinderung von unauthorisierten Zugriffen ("Programmierer XYZ darf das nicht"), sondern um die Sicherstellung der korrekten Funktionalität seitens des Klassen-Designers. Wenn du z.B. meinst von außen mit irgendwelchen Hackentricks private Methoden von Instanzen meiner Klassen aufrufen zu müssen, musst du dich nicht wundern, wenn das Programm nicht mehr nach der Spezifikation arbeitet und schlimmstenfalls zu Datenverlust fehelrhaften Daten, Absturz, .. führt."

Hmm. Ich muß zugeben, da ist was dran. :oops:

An die Daten der laufenden Anwendung könnte ich prinzipiel nur dann kommen wenn ich zuvor eine Class-Datei austauschen würde. Dann könnte ich aber auch gleich die Datei austauschen, die die kritischen Daten beinhaltet, was dann auch nichts mehr mit Reflections zu tun hat. Aha. :applaus:

Nun ging es mir aber von vornherein auch gar nicht darum, irgendwas zu hacken, sondern etwas nicht hackbar zu machen. Welche Möglichkeiten habe ich denn da (vorausgesetzt meine Java-Applikation läuft auf einem Clientrechner)?
Wie kann ich den Austausch und das Decompilieren von class-Dateien verhindern?
 

AlArenal

Top Contributor
Gar nicht. Du musst die class-Dateien übertragen, sonst können sie nicht ausgeführt werden und wenn du sie überträgtst, kann man sie clientseitig auf abfangen.

Die Dekompilation kannst du auch nicht verhindern. Zwar gibt es Obfuscatoren, aber die machen den Code nur schwerer lesbar. Da gibt es keine perfekte Methode, denn der Kram muss ja auch wieder in der VM verwendet werden können.

Absolute Sicherheit ist ein Trugschluss, ein Ziel das immer nur näherungsweise erreicht werden kann.
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben