Domanda

Di recente, il team per la sicurezza sul mio progetto rilasciato un codice di sicurezza documento di linee guida, progettato per essere utilizzato come parte del nostro codice.La prima cosa che mi ha colpito è stato un elemento che ha detto "non utilizzare classi Interne".Ho pensato che questo sembrava molto pesante e solenne dichiarazione.Classi interne sono buone, se utilizzato correttamente, giusto?, ma ho fatto un po ' di ricerche su google e trovato questo, citato qui per comodità.

Regola 5:Non Utilizzare Classi Interne

Java linguaggio di libri di dire che classi interne possono essere raggiunte solo da l'esterno classi che li racchiudono.Questo non è vero.Java byte code ha non esiste il concetto di classi interne, in modo da interno le classi sono tradotto dal compilatore in classi normali che capita di essere accessibile a qualsiasi codice stesso pacchetto.E la Regola 4 dice che non dipendono in ambito di pacchetto per la protezione.

Ma aspettate, c'è di peggio.Un interno classe ottiene l'accesso ai campi di allegando esterno della classe, anche se questi i campi sono dichiarati private.E il classe interna è tradotto in un classe separata.Al fine di consentire a questa classe separata di accesso ai campi di l'esterno classe, il compilatore in silenzio la modifica di tali campi da privato a ambito di pacchetto!E ' già abbastanza grave che la classe interna è esposto, ma è ancora peggio che il compilatore in silenzio ignorando la vostra decisione di fare alcuni campi privati.Non utilizzare classi interne, se e ' possibile.(Ironia della sorte, la nuova versione di Java 2 doPrivileged() API linee guida di utilizzo consigliamo di utilizzare una classe interna per scrivere codice privilegiato.Questo è uno motivo a noi non piace il doPrivileged() API.)

Le mie domande sono

  1. Questo comportamento ancora esiste in java 5 / 6?
  2. Questo è effettivamente un rischio per la sicurezza, dato che ogni classe, oltre l'esterno e l'interno delle classi, che ha cercato di accesso esterno classe' soci privati non compilare?
  3. Non si pongono abbastanza di un rischio per la sicurezza warant le 'linee guida' 'non usare le classi interne'?
È stato utile?

Soluzione

Questa informazione è un giro di un decennio di data.L'uso diffuso di anonymous inner class con AccessController.doPrivileged dovrebbe essere un indizio.(Se non ti piace l'API, considerare la percentuale di try-finally blocchi che vengono erroneamente mancanti nel JDK.)

Il criterio è che non esistono due classi possono condividere lo stesso pacchetto, se sono caricati da varie classe caricatori vari certificati.Per maggiore protezione, marchio di pacchetti sigillati nel manifesto dei tuoi vasi.Così, da un punto di vista della sicurezza, della Regola "4" è falsa e, quindi, anche questa regola.

In ogni caso, il lavoro fuori politiche di sicurezza è necessario capire che cosa si sta proteggendo contro.Questi tipi di politiche per la gestione mobile del codice che si muove) che può avere diversi livelli di fiducia.A meno che non si sta gestendo il codice mobile, in quanto il codice è di andare in una libreria che può essere richiesto, c'è molto poco di punto in questi tipi di precauzioni.Tuttavia, è quasi sempre una buona idea di utilizzare un robusto stile di programmazione, per esempio, la copia e la convalida di argomenti e valori di ritorno.

Altri suggerimenti

Questo comportamento ancora esiste in java 5 / 6?

Non è esattamente come descritto;Non ho mai visto un compilatore in cui questo è stato vero:

Al fine di consentire a questa classe separata, accesso ai campi della classe esterna, il compilatore silenzio di questi cambiamenti campi da privato a ambito del pacchetto!

Invece IIRC Sun Java 3/4 creata una funzione di accesso piuttosto che modificare il campo.

Sun Java 6 (javac 1.6.0_16 ) crea una statico funzione di accesso:

public class InnerExample {
    private int field = 42; 

    private class InnerClass {
        public int getField () { return field; };
    }

    private InnerClass getInner () { 
        return new InnerClass();
    }

    public static void main (String...args) {
        System.out.println(new InnerExample().getInner().getField());
    }
}


$ javap -classpath bin -private InnerExample
Compiled from "InnerExample.java"
public class InnerExample extends java.lang.Object{
    private int field;
    public InnerExample();
    private InnerExample$InnerClass getInner();
    public static void main(java.lang.String[]);
    static int access$000(InnerExample);
}


$ javap -classpath bin -c -private InnerExample
static int access$000(InnerExample);
  Code:
   0:   aload_0
   1:   getfield    #1; //Field field:I
   4:   ireturn

Questo è effettivamente un rischio per la sicurezza, dato che ogni classe, oltre l'esterno e l'interno delle classi, che ha cercato di accesso esterno classe' soci privati non com[p]ile?

Sto speculando un po ' qui, ma se si compila contro la classe non è così, ma se si aggiunge il access$000 quindi è possibile compilare il codice che utilizza la funzione di accesso.

import java.lang.reflect.*;

public class InnerThief {
    public static void main (String...args) throws Exception {
        for (Method me : InnerExample.class.getDeclaredMethods()){
            System.out.println(me);
            System.out.printf("%08x\n",me.getModifiers());
        }

        System.out.println(InnerExample.access$000(new InnerExample()));
    }
}

La cosa interessante è che la sintesi di una funzione di accesso ha modificatore di bandiere 00001008 per cui, se si aggiunge un pacchetto a livello di metodo statico non ha bandiere 00000008.Non c'e ' nulla la seconda edizione della JVM spec per il valore del flag, ma sembra impedire il metodo di essere visto da javac.

Così sembra che c'è qualche funzione di sicurezza c'è, ma non riesco a trovare alcuna documentazione su di esso.

(quindi questo post in CW, nel caso in cui qualcuno sa che cosa 0x1000 significa in un file di classe)

  1. Sì, questo problema esiste ancora.
  2. È un rischio per la sicurezza perché il ladro classe può essere predisposto con qualcosa di diverso dalla standard javac.
  3. Dipende di quanto paranoico sei :) Se non si consente l'alieno classi per l'esecuzione in JVM, non vedo il problema.E se si, si hanno grossi problemi (sandbox e tutti)
  4. So che hai avuto solo 3 domande, ma come altre persone qui, penso che questa sia una stupida limitazione.

Questo comportamento ancora esiste in java 5 / 6?

È possibile utilizzare il javap strumento per determinare che cosa il vostro file binari di esporre e come.

package demo;
public class SyntheticAccessors {
  private boolean encapsulatedThing;

  class Inner {
    void doSomething() {
      encapsulatedThing = true;
    }
  }
}

Il codice di cui sopra (compilato con Sun Java 6 javac) crea questi metodi SyntheticAccessors.class:

Compiled from "SyntheticAccessors.java"
public class demo.SyntheticAccessors extends java.lang.Object{
    public demo.SyntheticAccessors();
    static void access$0(demo.SyntheticAccessors, boolean);
}

Nota il nuovo access$0 metodo.

Si dovrebbe considerare che tipo di sicurezza che la vostra applicazione è di fornire.Un'applicazione con un'architettura sicura di non correre in questi denominato problemi.

Se c'è qualcosa di un utente non è permesso di fare con il vostro codice, è necessario separare questa funzionalità ed è eseguito su di un server (in cui l'utente non ha accesso ai file di classe).

Ricordate che è sempre possibile decompilare i file di classe java.E non si basano su "security by obscurity".Anche codice offuscato può essere analizzato, compreso e modificato.

Codice dannoso possibile utilizzare java reflection per ottenere qualsiasi pezzo di informazione nella JVM, a meno che il responsabile della sicurezza che vieta questo, questo include la modifica campi privati, pubblici e molto di più.

La mia opinione personale è che le ragioni per non, sono sopraffatti da tutte le altre possibilità, quindi, se ne avete bisogno, ha senso, ed è leggibile, è possibile utilizzare classi interne.

L'idea di questo tipo di sicurezza nel codice è piuttosto sciocco.Se si desidera che il codice di livello di protezione, utilizzare un offuscamento strumento.Come @skaffman detto nei commenti sopra, "Codice visibilità non è mai stata una caratteristica di sicurezza.Anche soci privati possono essere accessibili tramite reflection.".

Se si sta distribuendo il codice compilato e non offuscamento, quindi utilizzando una classe interna è la tua ultima preoccupazione se si sono preoccupati che le persone armeggiare con i tuoi privati.

Se si ospitano il codice, quindi perché siete preoccupati per qualcuno rovistando interno delle classi?

Se hai intenzione di collegamento di alcune 3rd party codice di cui non ti fidi e non può controllare in fase di esecuzione, sandbox di esso.

Come ho detto sopra, se questo è davvero una politica presso la vostra azienda, si prega di segnalare tempestivamente la vostra azienda a thedailywtf.com

"Questo è in realtà un rischio per la sicurezza, dato che ogni classe, oltre l'esterno e l'interno delle classi, che ha cercato di accesso esterno classe' soci privati non compilare?"

Anche se non compilare in circostanze normali, si può ancora generare il vostro proprio bytecode.Ma questo non è un motivo per evitare di classi interne.Tutto quello che dovete fare è assumere tutte le vostre classi interne sono pubbliche.

Se si vuole veramente essere in grado di eseguire codice non attendibile, imparare come impostare il tuo sandbox e i livelli di sicurezza utilizzando L'Architettura Di Sicurezza Di Java, non è molto difficile.Ma soprattutto, si dovrebbe evitare l'esecuzione di codice casuale in un ambiente sicuro.

sciocchezze!seguire la stessa logica, non scrivere metodi pubblici, perché hanno accesso a campi privati, gush!

Nota che gli inconvenienti elencati di non tenere per static classi interne non hanno accesso implicito a loro che racchiude classe (o di un oggetto davvero.)

Quindi, se questa regola sta per aiutare nella vostra azienda, potrebbe essere una buona idea per ottenere statico classi interne excempted in quanto offrono un modo per incapsulamento che è utile in molti casi.

@Tom, citando il Specifica del linguaggio Java, "Membro classi possono essere statico, nel qual caso essi sono nessun accesso per le variabili di istanza della circostante classe"

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top