Serializar é transformar um dado estruturado (um array, um objeto) em texto para armazená-lo ou transmiti-lo; desserializar é a operação inversa. O problema surge quando o dado a ser reconstruído vem de fora: um cookie, um campo de formulário, um parâmetro de URL. O MITRE classifica essa fraqueza como CWE-502, “desserialização de dados não confiáveis”; em PHP, também se fala em injeção de objeto (PHP Object Injection).
Como o ataque funciona em PHP
Uma string serializada do PHP descreve ela mesma o tipo do que contém. Por exemplo, O:4:"User":1:{s:4:"name";s:3:"Bob";} designa um objeto da classe User com uma propriedade name. Um atacante que controla essa string pode, portanto, pedir a unserialize() que crie um objeto de qualquer classe carregada pelo site, com os valores que quiser.
Esse objeto se torna perigoso por causa dos métodos mágicos que o PHP chama automaticamente: __wakeup() na reconstrução, __destruct() na destruição, __toString() quando o objeto é usado como texto. Encadeando classes já presentes no código do site, cujos métodos chamam uns aos outros, o atacante monta uma cadeia de gadgets (cadeia POP) que termina em uma ação perigosa: exclusão de arquivo, gravação de um arquivo PHP, execução remota de código.

Um exemplo no WordPress: GiveWP
A falha CVE-2024-5932 do plugin de doações GiveWP, até a versão 3.14.1 inclusive, permitia que um atacante não autenticado injetasse um objeto PHP pelo parâmetro give_title. Uma cadeia de gadgets presente no próprio plugin levava à execução de código e à exclusão de arquivos; a pontuação CVSS 3.1 publicada é 10. Nosso artigo sobre injeção de objetos PHP detalha esse caso e o mecanismo.
A desserialização também serve aos atacantes depois que eles já estão dentro: o backdoor adicionado em 2025 ao portfólio de plugins EssentialPlugin dependia de unserialize, como lembra nosso artigo sobre ataques à cadeia de suprimentos.
No WordPress: unserialize e maybe_unserialize
O WordPress armazena muitos dados serializados, principalmente na tabela de opções e nos metadados. A função maybe_unserialize() serve para lê-los: se o dado parece serializado (is_serialized()), ela chama unserialize(), sem restringir as classes permitidas. Ela não traz, portanto, nenhuma proteção e nunca deve receber um dado vindo de um visitante.
- Troque dados em JSON: a documentação do PHP recomenda
json_encode()ejson_decode()para todo dado que passa pelo usuário. O JSON nunca cria objetos de classes arbitrárias. - Não espere demais de
allowed_classes: essa opção deunserialize()limita as classes instanciadas, mas o manual do PHP avisa que não se deve passar dados não confiáveis para essa função, seja qual for o valor dela. - Assine o que precisa ir e voltar: se um dado serializado realmente precisa passar pelo navegador, uma assinatura HMAC verificada antes de qualquer leitura impede que ele seja alterado.
- Mantenha o PHP atualizado: desde o PHP 8.0, os metadados dos arquivos phar não são mais desserializados automaticamente, o que fechou um caminho de ataque ligado à inclusão de arquivos e aos wrappers.
Do lado do administrador, a principal defesa continua sendo atualizar os plugins afetados, já que a falha está no código deles. Um firewall de aplicação web pode bloquear strings serializadas suspeitas enquanto isso, e os alertas de vulnerabilidades do WP Masquerade Pro avisam quando um plugin instalado está entre as versões afetadas. O WP Masquerade não filtra as requisições por conta própria.