Diamo un'occhiata a cosa assomiglia ad una stringa serializzata quando serializzata su un array di byte. Ho acquisito il codice di esempio da questa guida .
Codice:
// Java code for serialization and deserialization
// of a Java object
import java.io.*;
class Demo implements java.io.Serializable
{
public String s;
// Default constructor
public Demo(String s)
{
this.s = s;
}
}
class Test
{
public static void main(String[] args)
{
Demo object = new Demo("helloWorld");
String filename = "file.ser";
// Serialization
try
{
//Saving of object in a file
FileOutputStream file = new FileOutputStream(filename);
ObjectOutputStream out = new ObjectOutputStream(file);
// Method for serialization of object
out.writeObject(object);
out.close();
file.close();
System.out.println("Object has been serialized");
}
catch(IOException ex)
{
System.out.println("IOException is caught");
}
}
}
Se guardo il file binario serializzato file.ser
vedo: (in un editor di testo che gestisce le proprietà binarie, caricando uno screenshot perché l'editor SE non gestirà correttamente i caratteri non stampabili)
Seloanalizziamo,vediamo:
- Ilnomedell'oggettoserializzato:
Demo
- Ilnomedell'oggettomembroserializzato:
java/lang/String
- Idatidiquestooggetto:
helloWorld
Riepilogo:
Sepermettiall'utentemalintenzionatodimodificareicontenutidellaString(cioè" helloWorld
", allora no, non credo sia possibile scoppiare. stai consentendo all'utente malintenzionato di modificare l'intero flusso di byte, quindi possono sostituire il nome della classe (ad esempio " java/lang/string
") con qualsiasi classe di gadget che desiderano e compromettere l'applicazione.
UPDATE per indirizzare questo commento:
isn't that where visibility comes in handy for security? e.g. if the 'injected' class is not in the package or private .. no chance of accessing it. am i right?
Direi di no. Non sono un esperto, ma la mia comprensione è che il codice di deserializzazione fa parte della JVM principale e quindi ignora completamente i modificatori di accesso come protected
, private
. Prova del concetto, considera una classe serializzabile con un membro privato:
class Demo implements java.io.Serializable
{
public String pub;
private String priv;
// No-args constructor
public Demo() {
pub = "Public data";
priv = "Private data";
}
}
Quando serializzi questo e lo mandi in rete, devi includere il membro privato, e il deserializzatore dall'altra parte deve essere in grado di ricostruirlo:
Scuotiamoilmitochelaparolachiavejavaprivate
abbiaqualcosaachefareconlasicurezza.Èunmodoperlosviluppatorechehascrittolaclassedidire"Ehi, non dovresti accedervi direttamente" allo sviluppatore che usa la classe, ma in nessun modo ti impedisce di usare java reflection per leggere / modificare membri o classi private, né impedisce che i dati in membri o classi privati vengano serializzati / deserializzati.