Esistono casi di vita reale, in cui l'utilizzo della parola chiave final in Java aumenta la sicurezza del sistema?

6

Mi sono imbattuto in questa domanda su StackOverflow: link

L'affermazione è fatta, che secondo Wikipedia:

A final class cannot be subclassed. This is done for reasons of security and efficiency.

e l'OP ha chiesto come si ottiene la sicurezza utilizzando la parola chiave final.

Ciò che mi ha sorpreso, la maggior parte delle risposte sosteneva, che la parola chiave finale aumenterebbe notevolmente la sicurezza, perché l'attaccante non sarebbe in grado di scavalcare le classi e chiamare i metodi protetti ecc. Si basano principalmente sull'articolo di Oracle Linee guida per la codifica sicura

For example, making a class final prevents a malicious subclass from adding
finalizers, cloning, and overriding random methods

Tuttavia, con la mia comprensione, se l'attaccante acquisisce la possibilità di eseguire codice Java arbitrario sul sistema di destinazione (e se si considera che abbia scavalcato le classi, è previsto che lo sia) di quanto non possa già fare tutto il codice è in grado di fare, quindi è completamente irrilevante dal punto di vista della sicurezza, se i tuoi metodi sono definitivi o meno, o anche se i campi sono privati e non esposti o no (può serializzare la tua classe e leggere ogni campo ecc.). p>

Ma dall'altra parte, è possibile trovare uno scenario simile nella vita reale, quando l'attaccante non raggiungerebbe i suoi obiettivi eseguendo codice arbitrario, e riuscirà solo (o tale attacco sarebbe considerevolmente più facile) "maliziosamente" 'annullando le tue lezioni, come descritto nell'articolo di Oracle? Ad esempio, se il server delle applicazioni è condiviso da più applicazioni Java?

    
posta Danubian Sailor 12.09.2013 - 19:31
fonte

2 risposte

7

Questa caratteristica di Java ha senso, in termini di sicurezza, nel modello di applet : un contesto in cui, in effetti, l'attaccante arriva ad eseguire il suo codice sulla tua macchina, eppure quel codice potenzialmente ostile è ancora contenuto. Questo era inizialmente pensato per i browser Web, non per i server.

Tutto il contenimento di un'applet Java viene eseguito su una base per chiamata, in un modo molto dettagliato. Esiste una complessa struttura di autorizzazioni che codifica ciò che l'applet può fare e cosa non può fare. In particolare, un'applet di base non può eseguire una serializzazione arbitraria del codice o una riflessione per ispezionare e / o modificare istanze dal proprio pacchetto o chiamare codice nativo. Anche la parola chiave final ha senso in questo contesto: poiché String è final , allora le classi standard possono assumere che quando ricevono come argomento un String , è l'oggetto genuino, non un EvilString che estende String ma agisce in modi imprevisti quando viene richiamato il suo metodo Substring() .

Si è scoperto che mantenere la sicurezza in queste condizioni era un problema difficile, più difficile di quanto inizialmente credesse Sun. Esistono centinaia, se non migliaia, di classi di librerie standard che devono essere rese "consapevoli dei permessi" e, per ognuna di esse, il codice deve fare attenzione per applicare le autorizzazioni appropriate. Era inevitabile che le persone sole, per quanto competenti esse fossero, dimenticassero alcuni casi d'angolo, portando a vulnerabilità sfruttabili. Negli ultimi anni c'è stato un flusso costante di "vulnerabilità delle applet Java" che consentono a un sito Web malvagio di assumere il controllo di qualsiasi browser Web che lo visita, purché tale browser utilizzi un plug-in Java che non è stato corretto.

Nessuna di queste influisce su Java come linguaggio di programmazione, poiché viene spesso utilizzato su server o in applicazioni desktop di grandi dimensioni; in queste situazioni, infatti, non esiste un codice ostile in esecuzione localmente.

La parola chiave final può ancora servire come documentazione applicata al compilatore (quindi non contro attackers , ma come promemoria per programmatori distratti); aiuta anche l'ottimizzazione (quando la JVM vede una chiamata a un metodo final , o a qualsiasi metodo su una classe final , allora sa che può ottimizzare la chiamata in un salto diretto nel codice del metodo, poiché c'è nessun modo in cui il metodo potrebbe essere sovrascritto.

    
risposta data 12.09.2013 - 20:14
fonte
1

C'è anche sicurezza del design :

Indicando classi e metodi come final ; il team di sviluppo sfrutta la quantità di mutazione futura nel codice sensibile *. Questo guida il team di sviluppo (che può essere distribuito) e qualsiasi futuro manutentore del codice o progetti di miglioramento su dove si sta verificando un comportamento sensibile e dovrebbe verificarsi - concentrando il rischio di progettazione in un'area più piccola.

Se ricordo bene, le classi BouncyCastle che non sono destinate al consumo pubblico di API sono bloccate in questo modo per scoraggiare comportamenti in polimorfici imprevisti e design di cripto-primitivi all'interno di BouncyCastle. Mentre final non impedisce a nessuno di modificare il codice sorgente e ricompilare come meglio crede, per qualsiasi progetto con un buon design, final offre un flag di avviso decente per i nuovi sviluppatori che la modifica del metodo potrebbe avere effetti collaterali inattesi integrità dell'infrastruttura interna. E quindi su sicurezza.

* Al grande inconveniente degli sviluppatori OOP di formazione classica che potrei aggiungere.

    
risposta data 13.09.2013 - 00:56
fonte

Leggi altre domande sui tag