I had the opportunity to work with serialization in Java, so I read Chapter 12 of Effective Java 3rd Edition. Here is a summary.
A technique for encoding an object as a byte stream and vice versa. In the Java framework, it can be easily implemented by implementing the Serializable interface on the object.
For example, when User is serialized as follows, the instantiated User object can be easily deserialized by calling ```ObjectInputStream # readObject ()` ``.
public class User implements Serializable {
private static final long serialVersionUID = 199035831519635924L;
private String name;
private String cardNumber;
public User(String name, String cardNumber) {
this.name = name;
this.cardNumber = cardNumber;
}
}
Serialization is convenient, but the above example also means that the User instance can be deserialized from anywhere.
Such code is a weak point for attacks such as remote code execution (RCE) and denial of service attacks. In addition, serialization is also used in popular Java subsystems such as RMI, JMX, and JMS, as well as in third-party libraries, which tends to increase the ** attack surface **. (Methods with Java serializable types used in various places such as these libraries and products are called ** gadgets **. By combining these gadgets (gadget chain), an attacker can call native code. Will end up.)
Also, even without a gadget, you can use serialization technology to launch a DoS attack and make a "deserialize bomb". This exploits the need to calculate the hash code for the field or element when deserializing an instance, for example by creating a deeply nested HashSet instance and deserializing it. This is an attack method that requires a huge amount of calculation time.
The best bet is not to do any deserialization in the system. There is a cross-platform structured data representation (≠ serialization system) in the world, and by using these, it is possible to safely perform conversion between an object and a byte sequence by a method other than serialization. These representations support only basic data types and arrays and are much simpler than Java serialization.
The main ones are JSON and protobuf, which are ** language neutral **. -JSON → A lightweight data exchange format often used on the Web. Developed for JavaScript, it can represent data in a human-readable format in text. ・ Protobuf → Developed by Google as C ++. Binary format, more efficient.
Next, if you are developing an existing Java system and you cannot avoid using serialization, do not deserialize untrusted byte streams at all. (Do not accept RMI requests from untrusted sources) → Java's Secure Coding Guidelines state that "deserialization of untrusted data is inherently dangerous and should be avoided" and is the only one highlighted in capital letters, bold, italics, and red throughout the guidelines. ing. Secure Coding Guidelines for Java SE
If serialization is unavoidable and data safety cannot be ensured, it is also necessary to use ObjectInputFilter
introduced in Java 9.
This allows the filtering applied to the data stream to be performed before deserialization.
There are the following two types of filter methods.
Blacklist ... How to accept classes by default and reject potentially dangerous classes
Whitelist ... How to reject classes by default and accept safe classes
Blacklists cannot respond to new threats, so choose a *** whitelist *** (A tool called the Serial Whitelist Application Trainer automatically prepares the whitelist to prevent excessive memory usage and deeply structured objects, but there are also attacks such as deserialized bombs that cannot be prevented. )
[Effective Java 3rd Edition](https://www.amazon.co.jp/Effective-Java-%E7%AC%AC3%E7%89%88-Joshua-Bloch/dp/4621303252/ref=tmm_pap_swatch_0?_encoding = UTF8 & qid = & sr =)
Recommended Posts