2010-06-09 12 views
17

Quindi dopo alcune ore di soluzione temporanea al momento la limitazione di Reflection è stata disattivata su Google App Engine, mi chiedevo se qualcuno potesse aiutarmi a capire perché la riflessione dell'oggetto può essere una minaccia. È perché posso controllare le variabili private di una classe o ci sono altre ragioni più profonde?Qual è il rischio per la sicurezza della riflessione dell'oggetto?

+0

è disabilitato oppure esiste un responsabile della sicurezza? – Bozho

+0

+1 domanda killer. Non chiudere questo, ma non sono soddisfatto della risposta. – rook

+0

Dai un'occhiata a [questa domanda] (http://stackoverflow.com/questions/1160924/what-risk-does-reflection-pose-medium-trust). – dbyrne

risposta

19

1 - La riflessione (come concetto) è in effetti ortogonale alla sicurezza.

c'era una grande attenzione nella progettazione di Java per renderlo una piattaforma sicura, con statica digitando, responsabile della sicurezza, l'utilizzo disciplinata class loader, e non c'è modo di avvitare puntatori/memoria . Puoi leggere l'intervista di James Gosling nel numero Masterminds of programming, il che è interessante.

Ma più è il riflettente potere più difficile è assicurarsi che le cose siano al sicuro come dovrebbero. Reflection sconfigge tipicamente la tipizzazione statica e può portare a errori di run-time.

Ma possono accadere anche cose più sottili. Ad esempio, i caricatori di classe - che possono essere considerati come riflettenti nello stack - non sono stati progettati correttamente nella prima versione di Java, con conseguente potenziale sostituzione del tipo. L'articolo Dynamic class loading in the JVM, di Gilad Bracha è approfondito su questi temi.

La riflessione non può essere disattivata del tutto; è sempre possibile riflettere sui propri campi/metodi pubblici. La riflessione su strutture private con AccessibleObject.setAccessible può tuttavia essere disabilitata, in quanto si rompe l'incapsulamento . Con l'accesso ai campi privati, è possibile l'ispezione e la modifica dei dati interni. Può portare a vari exploit dannosi , ad es.

  • strings non sono immutabili più e può essere modificato (vedi questo question)
  • si può rivelare informazioni sensibili degli oggetti che non si possiede
  • ... altri exploit ...

Infine ci sono altri meccanismi che mettono a repentaglio la sicurezza, in particolare sun.misc.Unsafe che dà accesso diretto alla memoria - i puntatori sono tornati.

2 - Ora, la domanda è se la riflessione (in pratica) porta a tanti rischi.

Ho letto il collegamento puntato da @dbyrne ma si tratta principalmente di .net. Inoltre, non so esattamente cosa sia disattivato per l'app Google. È solo il ReflectPermission o altra autorizzazione del responsabile della sicurezza? Un pericolo è chiaramente quello di ottenere l'accesso al file system e fare casino.

Il problema dell'accesso ai dati privati ​​e dell'interruzione dell'iscrizione può essere discusso nella pratica. Scrivere codice sicuro è davvero estremamente difficile, e anche senza modificare il modificatore di accesso è possibile sottoclasse classi in modo inappropriato - a meno che non siano final o, meglio ancora, sigillati - e passarli in giro. Ad esempio, prova a proteggere defensive copying.

Anche la sicurezza del tipo è comunque minacciata da errori di runtime a causa del downcast, quindi questo punto può anche essere discusso.

In un ambiente condiviso/ospitato, la sicurezza è relativa. A livello di linguaggio, ad esempio, non è possibile impedire a un modulo di modulo di consumare il 100% della CPU o di consumare tutta la memoria fino a un OutOfMemoryException. Tali preoccupazioni devono essere affrontate con altri mezzi, tipicamente a livello di sistema operativo, con la virtualizzazione e le quote.

Quindi la mia risposta personale sarebbe: la riflessione è un rischio per la sicurezza, ma non così grande nella pratica se confrontato con altri potenziali vettori di attacco.

+0

+1 per fornire un collegamento eccellente. Sono rispettosamente in disaccordo con il tuo scenario di attacco, anche se ammetto che tutto quello che abbiamo è la speculazione. – rook

+0

Grazie per la spiegazione dettagliata. Questa domanda deriva infatti dalla mia altra domanda: http://stackoverflow.com/questions/3002714/gson-on-google-app-engine-throws-a-security-exception. La risposta fornita dice il contrario, ma non riesco ancora a capire perché GSON fa le cose come stanno facendo. Ho finito per scrivere il mio piccolo metodo toJSON ma questo approccio non è semplicemente accettabile per oggetti di grandi dimensioni. Questo mi porta alla mia ultima domanda: se non la riflessione, c'è un altro modo in cui posso fare quello che stavo cercando di fare? qualche idea? – Legend

+0

@Legend Apparentemente GSON tenta di utilizzare 'AccessibleObject.setAccessible' quando non è consentito. Non ho familiarità con GSON e perché è necessario modificare il modificatore di accesso. Immagino che dovresti dare un'occhiata al codice di GSON se vuoi capirlo. Forse potresti creare la tua versione di GSON che usa il reflection ma non usa 'AccessibleObject.setAccessible' e assicurati di passare oggetti per la serializzazione in cui tutti i campi/metodi sono pubblici. – ewernli

2

Un'applicazione può utilizzare le API di riflessione Java per accedere e aggiornare campi ed eseguire metodi vietati dalle normali regole di accesso/visibilità Java. Con un po 'di ingegno, questo è sufficiente per:

  • le informazioni di accesso che dovrebbe essere nascosto,
  • sovvertire la sandbox di sicurezza di Java in modo da poter interferire con altre cose in esecuzione nella JVM, accedere ai file su la macchina locale e così via.

In determinate circostanze, potrebbe persino consentire l'iniezione di codice nativo dannoso.

+0

Interessante, potresti fornire maggiori dettagli? Forse un link. – rook

0

Una mia teoria è che Google sta cercando di nascondere qualcosa. Disabilitando Reflection Google potrebbe nascondere nomi di variabili, chiamate di funzioni e persino un'API completa. Se Google nasconde qualcosa come un'API, allora la certezza non te lo dirà.

So per certo che Reflection svolge un ruolo molto importante nei test di sicurezza. Ad esempio è possibile generare automaticamente test Fuzz usando la riflessione. AxMan utilizza TypeLib per identificare tutte le classi e le relative chiamate di metodo che costituiscono un oggetto COM. Usando queste informazioni, AxMan istanzia ogni classe e chiama ogni metodo con permutazioni di stringhe lunghe e numeri grandi. Test simili sono condotti da SOAP Fuzzers utilizzando il file WSDL per la riflessione.

2

Prima di tutto, se non hai installato un SecurityManager allora non sei sicuro comunque.

In secondo luogo, la riflessione non apre fori significativi a meno che lo setAccessible() sia abilitato e che sia esso stesso soggetto a un controllo di sicurezza (governato dallo setAccessChecksreflection permission). Senza quello, mentre si potrebbe essere in grado di sapere che il campo o il metodo privato esiste (sebbene ciò richieda lo stesso accessDeclaredMembers) non si può fare molto con quella conoscenza. La soluzione migliore per attaccare potrebbe essere quella di lavorare con oggetti serializzati, ma questa è tutta una cerchia di cera.

Si noti inoltre che la scrittura di un gestore sicurezza sicuro e di un programma di caricamento classi non è banale. Meglio lasciarli agli altri se non aspiri a mega-guru-dom (o, più probabilmente, a livelli imbarazzanti di fallimento).

1

GAE è un ambiente di hosting condiviso e ospita file WAR di più utenti. È molto probabile che più file WAR siano ospitati nella stessa JVM, perché generare un processo per WAR è semplicemente ridicolo. Quindi, l'unico modo per sandbox ogni file war è tramite un classloader personalizzato per ogni file WAR.

Ora, supponiamo che sia stata consentita la riflessione. Si could then walk the classloader hierarchy e si enumerano classi/metodi da file WAR appartenenti a utenti diversi. Ovviamente, questa è una grande preoccupazione.

Problemi correlati