Serialization Proxy Pattern :
Need of the pattern : In java serialization mechanism , It is actual Object of the class that gets serialized . This increases the security risk. Any attacker can construct an real object from that serialized state of object and invoke the method.
Do we want to get our object exposed so openly. Obviously No. Won't it be good that instead of real object a proxy of real object is serialized. This proxy will represent the state of real object that was earlier intended to be serialized. Now through this proxy attacker can not hit on real object and object safety is appropriately imposed.
Now how does all that happen technically in our actual code :
Let's consider we have a class Student that we had been traditionally serializing . Student class two variables
name and class.
public class Student implements Serializable {
private String name;
private String class;
Student(){
}
Student(String name, String class0{
this.name=name;
this.class=class;
}
}
So if you serialize an object of this class actual object of of the class will be serialized and exposed.
Lets try to create a proxy of this object .
To create a proxy let's create a private static inner class in Student class. Let the name of class be StudentProxy.
StudentProxy class will have single argumentconstructor . This constructor will only assign data from actual object to proxy object
private static class StudentProxy implements Serializable {
private String name;
private String class;
StudentProxy (Student student){
this.name = student.name;
this.class=student.class
}
}
Please note StudentProxy class need to have the same intrinsic state as original. So it has declared all variables that were there in Student class and were desired to be serialized.
Now , how will you create the StudentProxyObject ?
StudentProxy is private class in Student class. We need to provide a method to create the proxy. In Student class we write a method writeReplace.
private Object writereplace(){
return new StudentProxy(this);
}
This methos is simply invoking the constructor and creating the StudentProxy instead of Student itself.
Now we are serializing the proxy But attacker might try to fabricate this to Actual Student object and might succeed to attack the code. How do we save that?
Simply we need to insulate that by adding readObject method to Student class which basically will be invoked if attacker tries to reconstruct the object. In readObject method we need to restrict object creation .
private void readObject(ObjectInputStream stream) throws InvalidObjectException{
throw new InvalidObjectException("Go via proxy");
}
So here attacker has got no option to attack object directly and If he tries to attack on proxy it will fail to attack the real object as it has no public access to proxy . So we have safeguarded our serialization and deserialization mechanism .
Finally in our StudentProxy class we need to provide readResolve method. This method will create the object at deserialization time using Student constructor. So if serialized object got maligned it would not get though ,this method will create same only using same constructor , nothing extra will be added to deserialized object.
private Object readResolve(){
return new Student(name, class)
}
That's how we complete the proxy pattern implementation .
Need to consider the fact that this proxy based security does not come free of cost but it adds to overall performance degradation to certain extent. So one need to be judicious to use proxy pattern only when it is really required .
Please share your comments /questions to discuss it further .
Need of the pattern : In java serialization mechanism , It is actual Object of the class that gets serialized . This increases the security risk. Any attacker can construct an real object from that serialized state of object and invoke the method.
Do we want to get our object exposed so openly. Obviously No. Won't it be good that instead of real object a proxy of real object is serialized. This proxy will represent the state of real object that was earlier intended to be serialized. Now through this proxy attacker can not hit on real object and object safety is appropriately imposed.
Now how does all that happen technically in our actual code :
Let's consider we have a class Student that we had been traditionally serializing . Student class two variables
name and class.
public class Student implements Serializable {
private String name;
private String class;
Student(){
}
Student(String name, String class0{
this.name=name;
this.class=class;
}
}
So if you serialize an object of this class actual object of of the class will be serialized and exposed.
Lets try to create a proxy of this object .
To create a proxy let's create a private static inner class in Student class. Let the name of class be StudentProxy.
StudentProxy class will have single argumentconstructor . This constructor will only assign data from actual object to proxy object
private static class StudentProxy implements Serializable {
private String name;
private String class;
StudentProxy (Student student){
this.name = student.name;
this.class=student.class
}
}
Please note StudentProxy class need to have the same intrinsic state as original. So it has declared all variables that were there in Student class and were desired to be serialized.
Now , how will you create the StudentProxyObject ?
StudentProxy is private class in Student class. We need to provide a method to create the proxy. In Student class we write a method writeReplace.
private Object writereplace(){
return new StudentProxy(this);
}
This methos is simply invoking the constructor and creating the StudentProxy instead of Student itself.
Now we are serializing the proxy But attacker might try to fabricate this to Actual Student object and might succeed to attack the code. How do we save that?
Simply we need to insulate that by adding readObject method to Student class which basically will be invoked if attacker tries to reconstruct the object. In readObject method we need to restrict object creation .
private void readObject(ObjectInputStream stream) throws InvalidObjectException{
throw new InvalidObjectException("Go via proxy");
}
So here attacker has got no option to attack object directly and If he tries to attack on proxy it will fail to attack the real object as it has no public access to proxy . So we have safeguarded our serialization and deserialization mechanism .
Finally in our StudentProxy class we need to provide readResolve method. This method will create the object at deserialization time using Student constructor. So if serialized object got maligned it would not get though ,this method will create same only using same constructor , nothing extra will be added to deserialized object.
private Object readResolve(){
return new Student(name, class)
}
That's how we complete the proxy pattern implementation .
Need to consider the fact that this proxy based security does not come free of cost but it adds to overall performance degradation to certain extent. So one need to be judicious to use proxy pattern only when it is really required .
Please share your comments /questions to discuss it further .
aahhh, great article. Crisp, Clear and to the point.
ReplyDeleteKeep up the good work Manoj.
Cheers.