JAVA serialization, deserialization, and vulnerability remediation

Source: Internet
Author: User

JAVA serialization, deserialization, and vulnerability remediation

Last week, cyber security staff suffered a further setback in front of the black market. Joomla exposed high-risk 0-day vulnerabilities, which can be triggered without user login. The Joomla vulnerability has been circulating in various underground black industry chains for a period of time before the official release of upgrades and patches. I am afraid many websites have been attacked by hackers. The entry point of this malicious code is the user proxy string, which is widely advertised by every browser: Let the browser know the technical structure of the user to provide the best or most suitable version for the site.
Obviously, this string is stored in the Joomla database, but it is not cleaned to detect malicious code. Attackers can exploit the special app and script tension to easily compile a custom string and attach malicious code by broadcasting fake user proxy strings, this security risk is stored in php sessions through serialization.
For more information about PHP-related remote code execution vulnerability analysis, see vBulletin5 Remote Code Execution Vulnerability Analysis.
What is JAVA serialization and deserialization?
In many existing applications, some objects need to be serialized to leave the memory space and enter the physical hard disk for long-term storage. The most common is the Session object in the Web server. Object serialization generally has two purposes: to permanently Save the object's byte sequence to the hard disk, usually stored in a specified file; or to transfer the object's byte sequence on the network.
The process of restoring a byte sequence to an object is called object deserialization. When two processes perform remote communication, they can send various types of data to each other, and no matter what type of data, it will be transmitted on the network in the form of a binary sequence. The sender needs to convert the Java object into a byte sequence before it can be transmitted over the network. The receiver needs to restore the byte sequence to a Java object.

In fact, in different computer languages, data structures, objects, and binary strings are represented in different ways. For a fully object-oriented language like Java, all the operations performed by programmers are objects, from class instantiation.
JAVA serialization and deserialization instances
The concept closest to the data structure in Java is POJO (Plain Old Java Object) or Javabean. Let's take this example to describe how to implement serialization and deserialization.
Public static void main (String [] args) throws Exception {
SerializeObject (); // serialize an Object
Object o = DeserializeObject (); // Reverse Sequence Object
System. out. println (MessageFormat. format ("name = {0}, age = {1 },
Sex = {2} ", o. getName (), o. getSex (), o. getAge (), o. getholobby ()));
}
 
/**
* MethodName: SerializeObject
* Description: serialize an Object.
* @ Author Haom
* @ Throws FileNotFoundException
* @ Throws IOException
*/
Private static void SerializeObject () throws FileNotFoundException,
IOException {
Object object = new Object ();
Object. setName ("haom ");
Object. setSex ("Female ");
Object. setAge (18 );
Object. setholobby ("Taekwondo ");
// For the ObjectOutputStream Object output stream, the objectobject is stored in the object.txt file of the mdisk to complete the serialization of the Object.
ObjectOutputStream oo = new ObjectOutputStream (new
FileOutputStream (new File ("M:/object.txt ")));
Oo. writeObject (object );
System. out. println ("Object Serialization success! ");
Oo. close ();
}
 
/**
* MethodName: DeserializeObject
* Description: Reverse Sequence Object
* @ Author Haom
* @ Throws Exception
* @ Throws IOException
*/
Private static Object DeserializeObject () throws Exception,
IOException {
ObjectInputStream ois = new ObjectInputStream (new FileInputStream (
New File ("M:/object.txt ")));
Object object = (Object) ois. readObject ();
System. out. println ("Object deserialization success! ");
Return Object;
}
The above Code Description: After successful serialization of object, an object.txt file is generated on the mdisk, and deserialization of objectis generated after reading the object.txt file on the mdisk.
Of course, not all fields and attributes of a class that implements the serialization interface can be serialized:
If the class has a parent class, consider the following two cases: if the parent class has implemented a serializable interface, the corresponding fields and attributes of the parent class are the same as those of the class; if the parent class of this class does not implement the serializable interface, all the field attributes of the parent class of this class will not be serialized, in addition, during deserialization, the default constructor of the parent class is called to initialize the attributes of the parent class, but the subclass does not call the default constructor, but directly restores the attribute values from the stream.
If a property of this class is identified as static, the property cannot be serialized.
If a property of this class is identified by the transient keyword, the property cannot be serialized.
So, under what circumstances does the serialization method need to be customized? A simple example is as follows:
Public class SeriDemo1 implements Serializable {
Private String name;
Transient private String password;
// Transient, not serializable. the lifecycle of this field exists in the caller's memory.

Public SeriDemo1 (){
}
Public SeriDemo1 (String name, String password ){
This. name = name;
This. password = password;
}
// Simulate password encryption
Private String change (String password ){
Return password + "minna ";
}
// Write
Private void writeObject (ObjectOutputStream outStream) throws IOException {
OutStream. defaultWriteObject ();
OutStream. writeObject (change (password ));
}
// Read
Private void readObject (ObjectInputStream inStream) throws IOException,
ClassNotFoundException {
InStream. defaultReadObject ();
String strPassowrd = (String) inStream. readObject ();
// Simulate password decryption
Password = strPassowrd. substring (0, strPassowrd. length ()-5 );
}
// Returns a string indicating the object in text format.
Public String toString (){
Return "SeriDemo1 [name =" + name + ", password =" + password + "]";
}
// Static main
Public static void main (String [] args) throws Exception {
SeriDemo1 demo = new SeriDemo1 ("haom", "0123 ");
ByteArrayOutputStream buf = new ByteArrayOutputStream ();
ObjectOutputStream out = new ObjectOutputStream (buf );
Out. writeObject (demo );
ObjectInputStream in = new ObjectInputStream (new
ByteArrayInputStream (buf. toByteArray ()));
Demo = (SeriDemo1) in. readObject ();
System. out. println (demo );
}
}
As described in the Code above, we can see that the serialization method needs to be customized in the following situations:
Encryption of some sensitive information is supported to ensure the serialization security;
Make sure that the object's member variables meet the correct constraints;
Ensure the serialization performance needs to be optimized.
During the serialization and selection process, security considerations often occur in cross-LAN access scenarios. When communication occurs between companies or across data centers, for security reasons, cross-LAN access is often restricted to HTTP/HTTPS-based ports 80 and 443. If the serialization protocol used is not compatible with the mature HTTP transport layer framework, the following results may occur:
Service availability is reduced due to access restrictions;
Forced re-implementation of security protocols leads to higher implementation costs;
Open more firewall ports and protocol access, but at the expense of security.
Deserialization vulnerability hazards
When the application code accepts serialized data from the user and tries to deserialize and modify the data for further processing, the deserialization vulnerability is generated. The most harmful of this vulnerability is remote code injection.
The cause of this vulnerability is that java ObjectInputStream does not check its own input during deserialization, which indicates that malicious attackers may also construct specific input, after the ObjectInputStream class is deserialized, abnormal results are generated. This method can be used to remotely execute arbitrary code.
The serious risk of this vulnerability is that, even if your code does not use classes in Apache Commons Collections, as long as the Java application Classpath contains the jar package of Apache Commons Collections, can be remotely executed.
The root problem of the vulnerability is not Java serialization, but Apache Commons Collections allows any chained class function reflection calls. Attackers can upload attack code to the server by allowing the Java serialization protocol port, and then run TransformedMap in Apache Commons Collections.
Deserialization vulnerability remediation

Now, Apache Commons Collections has implemented some security processing in version 3.2.2, and added a switch to support serialization of these insecure Java classes. By default, the switch is disabled. Classes involved include CloneTransformer, ForClosure, InstantiateFactory, InstantiateTransformer, InvokerTransformer, PrototypeCloneFactory, PrototypeSerializationFactory, and WhileClosure. Solution for JBoss-related products released by RedHat: https://access.redhat.com/solutions/2045023.
Strictly speaking, Java has fewer security questions. The biggest problem is that it uses the runtime.exe c (String cmd) function to execute External commands. If the JVM can be prohibited from executing external commands, the dangers of unknown vulnerabilities will be greatly reduced, and the security of JVM can be greatly improved. For example:
SecurityManager originalSecurityManager = System. getSecurityManager ();
If (originalSecurityManager = null ){
// Create your own SecurityManager

 

SecurityManager sm = new SecurityManager (){
Private void check (Permission perm ){
// Disable exec
If (perm instanceof java. io. FilePermission ){
String actions = perm. getActions ();
If (actions! = Null & actions. contains ("execute ")){
Throw new SecurityException ("execute denied! ");
}
}
// Disable the setting of a new SecurityManager.
If (perm instanceof java. lang. RuntimePermission ){
String name = perm. getName ();
If (name! = Null & name. contains ("setSecurityManager ")){
Throw new SecurityException (
"System. setSecurityManager denied! ");
}
}
}
@ Override
Public void checkPermission (Permission perm ){
Check (perm );
}
@ Override
Public void checkPermission (Permission perm, Object context ){
Check (perm );
}
};
System. setSecurityManager (sm );
}
As shown above, you can simply add a program to the Java code to prohibit external programs from being executed.
Disabling JVM from executing external commands is a simple and effective way to improve JVM security. You can enhance the check of runtime.exe c code During code security scanning.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.