How can I secure the serialized object if I send the serialized object over the network? I doubt that hackers may interrupt/hack my data.
can anyone tell in detail about how to implement this?
How can I secure the serialized object if I send the serialized object over the network? I doubt that hackers may interrupt/hack my data.
can anyone tell in detail about how to implement this?
This presentation give ideas on how effectively attackers can tamper a Java serialized stream:
https://www.owasp.org/images/e/eb/OWASP_IL_2008_Shai_Chen_PT_to_Java_Client_Server_Apps.ppt
There is also the risk of injecting unsuspected behavior and inject code in case a vulnerable class exists on the server's classpath. See this article:
[Look-ahead Java deserialization][3]
You can encrypt or hash it, but java serialization format is a poot choice for sending over network - better solution would be JSON / XML ( encrypted or signed with some cryptographic algorythm)
Look into encryption as said before, but more specifically look at hte SSL/TLS libraries for network communication in java.
http://juliusdavies.ca/commons-ssl/ssl.html
No need to try and implement secure encryption communication when there is a very powerful library built into Java.
In my opinion, you can use either use SSLSocket
or SealedObject
. However, it will make things a bit heavy for you. However, one of the option is described in this article as well. http://www.ibm.com/developerworks/library/j-5things1/
You can use the signed object and sealed object to secure the serialisation object
I add a useful resource to the thread here, Oracle's Secure Coding Guidelines for Java SE (particularly, in this case section 8 in the guidelines, "Serialization and Deserialization"):
https://www.oracle.com/java/technologies/javase/seccodeguide.html#8
A good way to secure any object in java is enforcing invariants in the constructor. For example, imagine a class Person
where you do not want to allow any instantiation of a person under age 13:
public class Person implements Serializable{
private String name;
private Integer age;
public Person(final String name, final Integer age) {
if(age < 13) {
throw new IllegalArgumentException("invalid age");
}
this.name = name;
this.age = age;
}
}
However, as you are implementing Serializable
it is possible to write code bypassing your constructor, which should be our main defense mechanism, so it is possible to break encapsulation:
@Test
void testEncapsulationSerialization() throws IOException, ClassNotFoundException {
Person a = new Person("dave", 23);
ByteArrayOutputStream boas = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(boas)) {
oos.writeObject(a);
}
byte[] bytes = boas.toByteArray();
bytes[237] = 12; // trick: we are modifying the array of bytes manually
try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes))) {
Person b = (Person) ois.readObject();
System.out.println(a);
System.out.println(b);
}
}
With this test we are able to create an object of type Person
with age of 12 (which is not allowed in our constructor).
So in this case, if you want to secure serialization you need to override in Person
class readResolve()
method to call your constructor:
private Object readResolve() throws ObjectStreamException {
return new Person(this);
}
So that we will enforce that any instantiation follow the invariants declared in our constructor.
Also if you have a parent class that implements Serialization, you may need to also override readObject()
and writeObject()
methods.
Furthermore, you should ensure immutability of your object, as the default extensibility of java works against security.
To sum up, we should avoid using Serializable
(and Clonable
) because both can break encapsulation if we do not explicitly secure them.