The document discusses Java serialization and its flaws. It begins by explaining common uses of serialization and how easy it is to implement. However, it notes that the built-in design has security issues, as serialization data can contain sensitive object details. It also explains that serialization is exploited in attacks and discusses how to mitigate risks from Java and alternative serialization formats.
2. Steve Poole
Developer Advocate, IBM
JVM Developer
Open Source Advocate
DevOps Practitioner (whatever that means!)
Driving Change
3. A Modern Fairy Tale:
Java Serialization
• Why we still need serialization and
where we use it.
• How the built-in design is flawed
• How it is being exploited and used
against us.
• How to work against the dark arts
rallied against us
• How even the alternative forms of
Java serialization can still be open to
attack.
8. Java Serialization is easy to use
implementsjava.io.Serializable;
You just have to opt in….
9. Java Serialization is easy to use
FileOutputStream fos=new FileOutputStream(output);
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(m);
FileInputStream fis=new FileInputStream(input);
ObjectInputStream ois=new ObjectInputStream(fis);
Thing t=(Thing) ois.readObject();
Then its easy to save and restore objs
10. If you don’t opt-in
java.io.NotSerializableException:
atjava.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
atjava.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
11. Java Serialization is a useful and
relatively easy to use technology
There might just be
some side effects
12. Example
OC1 example=newOC1();
oos.writeObject(example);
public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
13. public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
<STREAM_MAGIC>
14. public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
<STREAM_MAGIC><STREAM_VERSION>
15. public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
<STREAM_MAGIC><STREAM_VERSION><TC_OBJECT>
16. public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
<STREAM_MAGIC><STREAM_VERSION><TC_OBJECT><TC_CLASSDESC>
17. public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
<STREAM_MAGIC><STREAM_VERSION><TC_OBJECT><TC_CLASSDESC>
<UTF8-ClassName>
18. public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
<STREAM_MAGIC><STREAM_VERSION><TC_OBJECT><TC_CLASSDESC>
<UTF8-ClassName><serial-version-id>
19. public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
<STREAM_MAGIC><STREAM_VERSION><TC_OBJECT><TC_CLASSDESC>
<UTF8-ClassName><serial-version-id><flags>
20. public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
<STREAM_MAGIC><STREAM_VERSION><TC_OBJECT><TC_CLASSDESC>
<UTF8-ClassName><serial-version-id><flags><field count>
21. public class OC1 implements Serializable {
private String hello="hello";
}
0000000 ac ed 00 05 73 72 00 15 6f 63 31 2e 73 65 72 69 | ....sr..oc1.seri
0000010 61 6c 69 73 61 74 69 6f 6e 2e 4f 43 31 ab 5a a9 | alisation.OC1.Z.
0000020 59 37 9f 03 ef 02 00 01 4c 00 05 68 65 6c 6c 6f | Y7......L..hello
0000030 74 00 12 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 | t..Ljava/lang/St
0000040 72 69 6e 67 3b 78 70 74 00 05 68 65 6c 6c 6f | ring;xpt..hello
<STREAM_MAGIC><STREAM_VERSION><TC_OBJECT><TC_CLASSDESC>
<UTF8-ClassName><serial-version-id><flags><field count><field type(Object)>
26. Element Value
STREAM_MAGIC 0xacdc
STREAM_VERSION 0x0005
TC_OBJECT 0x73
TC_CLASSDESC 0x72
UTF8-ClassName oc1.serialisation.OC1
serial-version-id 0xab5aa959379f03ef
flags 0x02
field count 0x0001
field type ‘L’
UTF8-FieldName ‘hello’
Class Name ‘java.lang.String’
flags 0x787074
UTF8-String value ‘hello’
27. Element Value
STREAM_MAGIC 0xacdc
STREAM_VERSION 0x0005
TC_OBJECT 0x73
TC_CLASSDESC 0x72
UTF8-ClassName oc1.serialisation.OC1
serial-version-id 0xab5aa959379f03ef
flags 0x02
field count 0x0001
field type ‘L’
UTF8-FieldName ‘hello’
Class Name ‘java.lang.String’
flags 0x787074
UTF8-String value ‘hello’
A check that you’re talking
about the same class
28. Element Value
STREAM_MAGIC 0xacdc
STREAM_VERSION 0x0005
TC_OBJECT 0x73
TC_CLASSDESC 0x72
UTF8-ClassName oc1.serialisation.OC1
serial-version-id 0xab5aa959379f03ef
flags 0x02
field count 0x0001
field type ‘L’
UTF8-FieldName ‘hello’
Class Name ‘java.lang.String’
flags 0x787074
UTF8-String value ‘hello’
The actual contents of the
instance are self-defining
30. Element Value
STREAM_MAGIC 0xacdc
STREAM_VERSION 0x0005
TC_OBJECT 0x73
TC_CLASSDESC 0x72
UTF8-ClassName oc1.serialisation.OC1
serial-version-id 0xab5aa959379f03ef
flags 0x02
field count 0x0001
field type ‘I’
UTF8-FieldName ‘hello’
Class Name ‘java.lang.Number’
flags 0x787074
Integer value 0x0001
What happens if I do this?
32. Are we safe from
changes to the
serialization
stream then?
33. public class OC1 {
private String hello="hello";
}
Element Value
field name hello
field type L
class name java.lang.String
value hello
public class OC1 {
private Objecthello="hello";
}
Element Value
field name hello
field type L
class name java.lang.Object
value hello
34. public class OC1 {
private Objecthello="hello";
}
Element Value
field name hello
field type L
class name java.lang.Object
value hello
Element Value
field name hello
field type [
class name java.lang.Array
value 1,2,3,4
Element Value
field name hello
field type [
class name HashMap
value A=1,B=2
Element Value
field name hello
field type L
class name Any class name
value Any value
36. public class Foo {
static {
System.out.println("static initaliser called");
}
public Foo() {
System.out.println("object constructor called");
}
}
What happens we run “new Foo()”
37. public class Foo {
static {
System.out.println("static initalizer called");
}
public Foo() {
System.out.println("object constructor called");
}
}
static initalizer called
object constructor called
38. Element Value
field type ‘L’
UTF8-FieldName ‘hello’
Class Name ‘org.random.Foo’
What happens if we do this in our serialized form?
public class OC1 {
private String hello="hello";
}
39. public class Foo implements Serializable{
static {
System.out.println("static initaliser called");
}
public Foo() {
System.out.println("object constructor called");
}
}
What gets called - A,B, Both or Neither?
A
B
40. What gets called - A,B, Both or Neither?
static initaliser called
“Exception in thread "main"
java.lang.ClassCastException: cannot assign
instance of org.random.Foo to field
oc1.serialisation.OC1.hello of type
java.lang.String in instance of
oc1.serialisation.OC1”
output
exception
41. Java Deserialization can be used to execute code
even if it eventually fails
That’s still useful to the bad guys.
42. We’ve just learnt that constructors do not get
called during deserialization
public class Foo implements Serializable{
private int data[];
public Foo() {
data=new int[] {1,2,3,4};
}
public int size() {
return data.length;
}
What happens here?
43. Element Value
STREAM_MAGIC 0xacdc
STREAM_VERSION 0x0005
TC_OBJECT 0x73
TC_CLASSDESC 0x72
UTF8-ClassName oc1.serialisation.OC1
serial-version-id 0xab5aa959379f03ef
flags 0x02
field count 0x0001
field type ‘[’
UTF8-FieldName ‘data’
Element Type I
Element Count 0x04
Values 1,2,3,4
Valid stream
44. We’ve just learnt that constructors do not get
called during deserialization
public class Foo implements Serializable{
private int data[];
public Foo() {
data=new int[] {1,2,3,4};
}
public int size() {
return data.length;
}
The answer is 4?
45. What happens if I do this?
Element Value
STREAM_MAGIC 0xacdc
STREAM_VERSION 0x0005
TC_OBJECT 0x73
TC_CLASSDESC 0x72
UTF8-ClassName oc1.serialisation.OC1
serial-version-id 0xab5aa959379f03ef
flags 0x02
field type null
UTF8-FieldName ‘data’
46. We’ve just learnt that constructors do not get
called during deserialization
public class Foo implements Serializable{
private int data[];
public Foo() {
data=new int[] {1,2,3,4};
}
public int size() {
return data.length;
}
Code here never
Gets called
47. We’ve just learnt that constructors do not get
called during deserialization
public class Foo implements Serializable{
private int data[];
public Foo() {
data=new int[] {1,2,3,4};
}
public int size() {
return data.length;
}
So NPE!
48. And its not just “implements Serializable”
instances that are at risk
50. ”new SubClass()”. Deserialise SubClass
in Parentclass init
in foo class init
in Parentconstructor
in Parentclass init
in SubClass class init
in Parentconstructor
in SubClass constructor
58. Classes can ‘opt-in’ to deserialization and
take more control
public class Log implements Serializable{
private File logfile;
private transient FileOutputStream los;
private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException {
in.defaultReadObject();
los=new FileOutputStream(logfile);
}
}
59. But that can still be used against them
public class Log implements Serializable{
private File logfile;
private transient FileOutputStream los;
private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException {
in.defaultReadObject();
los=new FileOutputStream(logfile);
}
}
Element Value
field name logfile
value /etc/passwd
60. Other ways to reduce exposure
private final void readObject(ObjectInputStream in) throws
java.io.IOException
{
throw new java.io.IOException("forbidden");
}
Opt out of being deserialized (add to every class!)
61. Other ways to reduce exposure
// reject deserialisation of any class belonging to untrustedmodule,
// and of any array with more than 500 items in it
jdk.serialFilter=!untrustedmodule/.**;maxarray=500
// white-list classes from package com.myorg.trusted,
// but not necessarily from its subpackages.
jdk.serialFilter=com.myorg.trusted.*
Implement class filtering
62. Other ways to reduce exposure
Implement your own ObjectInputSteam.
63. Other ways to reduce exposure
Use modularity to reduce available classes
Attackers can only call
code available on your system
64. Other ways to reduce exposure
Create a deliberate data transfer model
public final class Packet implements Serializable{
String name;
int size;
List<ChildPacket> kids;
}
Complicated
data structures
converter
65. Other ways to reduce exposure
And maybe stop using native serialization at all
{
"name" : "foobar" ,
"size" : 1 ,
"kids" : [ { } , {} ]
}
Complicated
data structures
converter
68. The self-defining design of Java Serialization is
open to exploitation.
It’s all about running the code you already
have. Just not how you expected
Or changing your data to invalid but useful
values
How do the bad guys do this?
71. Element Value
STREAM_MAGIC 0xacdc
STREAM_VERSION 0x0005
TC_OBJECT 0x73
TC_CLASSDESC 0x72
UTF8-ClassName oc1.serialisation.OC1
serial-version-id 0xab5aa959379f03ef
flags 0x02
field count 0x0001
field type ‘[’
UTF8-FieldName ‘data’
Element Type I
Element Count MAX_INT
Values
84. Impressive amount of tools and collateral out
there – but does it really matter?
How much risk are we taking by ignoring the
problem?
85. In 2016 Cybercrime was
estimated to be worth
450 Billion Dollars
@spoole167
Cybercrime is the most profitable type of crime
In 2016 The illicit drug trade
was estimated to be worth
435 Billion Dollars
@spoole167
86. Cybercrime is the most profitable type of crime
• Guess which one has the least risk to the criminal ?
• Guess which is growing the fastest ?
• Guess which one is the hardest to prosecute ?
• Guess which one is predicted to reach 2100 Billion Dollars by 2019?
• Guess which one is predicted to reach 6000 Billion Dollars by 2021?
@spoole167
88. That’s about $600 for every
person on the planet
In the US it’s about $8000
each
@spoole167
89. Don’t agree?
“The bad guys prey on the weak, vulnerable and ignorant”
That’s you
@spoole167
90. Ever googled for:
“very trusting trust manager”
“Getting Java to accept all certs over HTTPS”
“How to Trust Any SSL Certificate”
“Disable Certificate Validation in Java”
@spoole167
91. TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
X509Certificate[] certs, String authType) {
}
public boolean isClientTrusted( X509Certificate[] cert) {
return true;
}
public boolean isServerTrusted( X509Certificate[] cert) {
return true;
}
}}
Ever written
something
like this?
@spoole167
93. We’ve all done something like that
We do it all the time
@spoole167
94. We’ve all done something like that
We do it all the time
The whole world does it
How bad can it be?
@spoole167
95. We’ve all done something like that
We do it all the time
The whole world does it
Github search “implements TrustManager” ….
@spoole167
96. We’ve found 72,609 code results
AlwaysValidTrustManager
TrustAllServersWrappingTrustManager
A very friendly, accepting trust
manager factory. Allows anything
through. all kind of certificates are
accepted and trusted.
A very trusting trust manager that
accepts anything
// Install the all-trusting trust
manager
OverTrustingTrustProvider
AllTrustingSecurityManagerPlugin.java
AcceptingTrustManagerFactory.java
AllTrustingCertHttpRequester.java
99. Today Java serialization use is widespread.
Java Persistence
API (JPA)
Remote EJB
Remote Method
Invocation (RMI)
Java
Management
Extensions (JMX)
Contexts and
Dependency
Injection (CDI)
HTTP cookies
HTML Forms
REST Services
101. Reality
• As developers we all need to wake up to our
responsibilities to design and code secure software.
• The bad guys exploit our ignorance and lack of
attention
102. Games & Drinks on Us
Please join our IBM Java devs on
Wednesday after the community
keynote for some drinks and video
games!
Coin-Op Game Room
508 4th St
7:30pm drinks
8:00pm light food, and
quarters for games
Here
There
Ibm.biz/javaparty