Insecure Deserialization
Insecure Deserialization in Java
Vulnerability: Insecure Deserialization
Vulnerable Code:
javaCopy codeObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser"));
Object obj = ois.readObject();
Reason for vulnerability: Deserializing untrusted data can lead to remote code execution or other security issues.
Fixed Code:
javaCopy codeObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.ser")) {
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!allowedClasses.contains(desc.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
};
Object obj = ois.readObject();
Reason for fix: Restricting the classes that can be deserialized prevents malicious code execution.
Insecure Deserialization in Python
Vulnerability: Insecure Deserialization
Vulnerable Code:
pythonCopy codeimport pickle
data = pickle.loads(request.data)
Reason for vulnerability: Deserializing untrusted data with pickle
can lead to arbitrary code execution.
Fixed Code:
pythonCopy codeimport json
data = json.loads(request.data)
Reason for fix: Using json
for deserialization instead of pickle
prevents arbitrary code execution since json
only handles basic data types.
Example 2: Python
Vulnerable Code:
pythonCopy codeobj = pickle.load(open('file.pkl', 'rb'))
Reason for vulnerability: Deserializing untrusted data, leading to insecure deserialization.
Fixed Code:
pythonCopy codeclass SafeUnpickler(pickle.Unpickler):
def find_class(self, module, name):
if module == "allowed.module" and name == "AllowedClass":
return super().find_class(module, name)
raise pickle.UnpicklingError("Unauthorized deserialization attempt")
obj = SafeUnpickler(open('file.pkl', 'rb')).load()
Reason for fix: Restrict the classes that can be deserialized.
Java Example
Vulnerable Code:
javaCopyimport java.io.*;
public class UserDeserializer {
public static User deserializeUser(String serializedUser) {
try (ByteArrayInputStream bis = new ByteArrayInputStream(Base64.getDecoder().decode(serializedUser));
ObjectInputStream ois = new ObjectInputStream(bis)) {
return (User) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}
Reason for Vulnerability:
This code blindly deserializes user-provided data, which can lead to remote code execution if the User class or any of its members are not designed securely.
Fixed Code:
javaCopyimport com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
public class UserDeserializer {
private static final ObjectMapper mapper = JsonMapper.builder()
.activateDefaultTyping(null, ObjectMapper.DefaultTyping.NON_FINAL)
.build();
public static User deserializeUser(String serializedUser) {
try {
return mapper.readValue(serializedUser, User.class);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
Reason for Fix:
The fixed code uses Jackson for JSON deserialization instead of Java's built-in serialization. This approach is generally safer and allows for fine-grained control over deserialization behavior.
Java Example
Vulnerable Code:
javaCopyimport org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
public class CommandExecutor {
public static void executeCommand(String command) {
InvokerTransformer transformer = new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{command});
Map<String, String> map = new HashMap<String, String>();
map.put("key", "value");
Map<String, String> transformedMap = TransformedMap.decorate(map, null, transformer);
// Use transformedMap...
}
}
Reason for Vulnerability:
This code uses Apache Commons Collections' TransformedMap with InvokerTransformer, which can be exploited in deserialization attacks to execute arbitrary commands.
Fixed Code:
javaCopyimport java.util.HashMap;
import java.util.Map;
public class CommandExecutor {
public static void executeCommand(String command) {
// Validate and sanitize the command
if (!isValidCommand(command)) {
throw new IllegalArgumentException("Invalid command");
}
// Execute the command safely
ProcessBuilder processBuilder = new ProcessBuilder(command.split("\\s+"));
processBuilder.start();
}
private static boolean isValidCommand(String command) {
// Implement command validation logic
return command.matches("^[a-zA-Z0-9\\s-]+$");
}
}
Reason for Fix:
The fixed code removes the use of potentially dangerous Apache Commons Collections classes and implements a safer way to execute commands with proper validation.
Python Example
Vulnerable Code:
pythonCopyimport pickle
import base64
def process_data(encoded_data):
data = base64.b64decode(encoded_data)
return pickle.loads(data)
Reason for Vulnerability:
This code uses Python's pickle module to deserialize data, which can lead to arbitrary code execution if an attacker controls the serialized data.
Fixed Code:
pythonCopyimport json
import base64
def process_data(encoded_data):
data = base64.b64decode(encoded_data)
return json.loads(data)
Reason for Fix:
The fixed code uses JSON for deserialization instead of pickle. JSON is a data-only format and doesn't allow for code execution, making it a safer choice for deserializing untrusted data.
Last updated