Er det muligt at bryde ud af en binær Java-serialiseret streng?
Lad os se på, hvordan en serialiseret streng faktisk ser ud, når den serialiseres til en byte-array. Jeg tog prøvekode fra denne guide.
Kode:
// 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");
}
}
}
Hvis jeg ser på den serialiserede binære fil file.ser
Jeg ser:(i en teksteditor håndterer denne egenskab binær, uploader et skærmbillede, fordi SE-editoren ikke håndterer de ikke-udskrivbare tegn korrekt)
Hvis vi opdeler det, ser vi:
- Navnet på det serialiserede objekt:
Demo
- Navnet på det serialiserede medlemsobjekt:
java/lang/String
- Dataene for dette objekt:
helloWorld
Oversigt:
Hvis du kun tillader angriberen at ændre indholdet af strengen (dvs. "helloWorld
", så nej, jeg tror ikke, det er muligt at bryde ud. Men hvis du tillader angriberen at ændre hele bytestrømmen, så kan de erstatte klassenavnet (dvs. "java/lang/string
") med den gadget-klasse, de ønsker, og kompromitterer din applikation.
OPDATERING for at løse denne kommentar:
er det ikke her synlighed kommer til nytte for sikkerheden? for eksempel. hvis den 'injicerede' klasse ikke er i pakken eller privat .. ingen chance for at få adgang til den. har jeg ret?
Jeg ville sige nej. Jeg er ikke ekspert, men min forståelse er, at deserialiseringskoden er en del af kerne-JVM og derfor fuldstændig ignorerer adgangsmodifikatorer som protected
, private
. Proof of concept, overvej en serialiserbar klasse med et privat medlem:
class Demo implements java.io.Serializable
{
public String pub;
private String priv;
// No-args constructor
public Demo() {
pub = "Public data";
priv = "Private data";
}
}
Når du serialiserer dette og sender det over netværket, skal du inkludere det private medlem, og deserializeren i den anden ende skal være i stand til at rekonstruere det:
Lad os ryste myten om, at java-søgeordet private
har noget med sikkerhed at gøre. Det er en måde for udvikleren, der skrev klassen, at sige "Hey, du skal ikke få adgang til dette direkte" til udvikleren, der bruger klassen, men forhindrer dig på ingen måde i at bruge java-refleksion til at læse/ændre private medlemmer eller klasser. forhindrer det data i private medlemmer eller klasser i at blive serialiseret / deserialiseret.