A Serialização ainda é usada hoje, mas com muita cautela. Ela foi amplamente utilizada no passado para persistência de objetos e comunicação entre sistemas, mas devido a diversos problemas de segurança e eficiência, seu uso tem diminuído.
Atualmente, frameworks modernos e tecnologias como JSON, XML, Protobuf e Avro são preferidos para troca de dados, pois são mais seguros, interoperáveis e eficientes. No entanto, a serialização Java ainda pode ser encontrada em sistemas legados e em aplicações que precisam de compatibilidade com tecnologias antigas.
Se for realmente necessário usar serialização, recomenda-se adotar boas práticas de segurança, como filtragem de objetos e evitar desserialização de fontes não confiáveis.
Item 85: Prefira alternativas à serialização Java
O que é Serialização?
- Processo de transformar um objeto em uma sequência de bytes para armazenamento ou transmissão.
- Desserialização é o processo inverso, reconstruindo o objeto a partir dos bytes serializados.
- Utiliza a interface Serializable no Java.
Problemas da Serialização Java
1. Superfície de Ataque Grande
- O método readObject atua como um "construtor mágico", podendo instanciar objetos inesperados.
- Qualquer classe que implemente Serializable pode ser um ponto de exploração.
2. Vulnerabilidades de Segurança
- Possibilidade de execução remota de código (RCE) ao desserializar objetos de origem desconhecida.
- Uso de gadgets (métodos chamados automaticamente durante a desserialização) para criar cadeias de ataque.
3. Bombas de Desserialização
- Objetos que exigem grande poder computacional para serem desserializados.
- Exemplo: HashSet profundamente aninhado.
Exemplo de bomba de desserialização:
import java.io.*;
import java.util.HashSet;
public class DeserializationBomb {
public static void main(String[] args) throws Exception {
HashSet<Object> root = new HashSet<>();
HashSet<Object> s1 = root;
HashSet<Object> s2;
for (int i = 0; i < 100; i++) {
s2 = new HashSet<>();
s1.add(s2);
s1 = s2;
}
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("bomb.ser"))) {
out.writeObject(root);
}
}
}
Alternativas à Serialização Java
JSON
- Leve, legível e amplamente suportado. Exemplo com Gson:
import com.google.gson.Gson;
class Pessoa {
String nome;
int idade;
}
public class JsonExample {
public static void main(String[] args) {
Gson gson = new Gson();
Pessoa pessoa = new Pessoa();
pessoa.nome = "João";
pessoa.idade = 30;
String json = gson.toJson(pessoa);
System.out.println(json);
}
}
Protocol Buffers (Protobuf)
- Binário e eficiente.
- Necessita da definição de esquemas .proto.
Como Mitigar Riscos se a Serialização for Necessária
- Evite Desserialização de Dados Não Confiáveis
- Use Filtragem de Objetos (ObjectInputFilter desde Java 9)
ObjectInputFilter filter = info -> {
if (info.serialClass() != null && info.serialClass().getName().equals("MinhaClasseSegura")) {
return ObjectInputFilter.Status.ALLOWED;
}
return ObjectInputFilter.Status.REJECTED;
};
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("objeto.ser"));
ois.setObjectInputFilter(filter);
Object obj = ois.readObject();
Utilize Lista Branca em vez de Lista Negra
- Permita apenas classes explícitas na desserialização.
Conclusão
- Evite ao máximo a Serialização Java em sistemas novos.
- Prefira formatos mais seguros e eficientes como JSON e Protobuf.
- Se precisar desserializar objetos, use filtragem rigorosa para evitar ataques.
Exemplo do livro:
Top comments (0)