A desserialização insegura está entre as falhas mais perigosas do ecossistema PHP: ela leva com frequência à execução remota de código, muitas vezes sem autenticação. Este artigo explica o que é a injeção de objetos PHP, por que uma simples string de texto pode assumir o controle de um site e como desenvolvedores e administradores se protegem, com exemplos reais do WordPress.
Serializar, desserializar: do que estamos falando
A serialização transforma uma variável PHP (array, objeto) em uma string de texto que pode ser armazenada ou transmitida. A função unserialize() faz a operação inversa: reconstrói a variável original. O problema é que reconstruir um objeto também significa instanciar a sua classe e disparar alguns dos seus métodos. A documentação do PHP é explícita: nunca se deve passar dados de usuário não confiáveis para unserialize(), porque a reconstrução pode carregar e executar código.
Um atacante que controla a string serializada pode, portanto, pedir a criação de objetos de qualquer classe presente no código do site, com as propriedades que escolher. Essa é a definição de injeção de objetos PHP, classificada como CWE-502 (desserialização de dados não confiáveis).
Como é uma string serializada? É texto legível que descreve o tipo e o conteúdo. Por exemplo, O:4:"User":1:{s:4:"name";s:3:"Bob";} representa um objeto da classe User com uma propriedade name igual a Bob. Basta trocar o nome da classe e as propriedades para mirar em uma classe útil para o ataque. Por isso um filtro ingênuo, que só verifica se o dado parece serializado, não traz segurança nenhuma.
Os métodos mágicos e a cadeia de gadgets
Sozinho, um objeto forjado não faz nada. O que torna o ataque possível são os métodos mágicos que o PHP chama automaticamente em certos momentos:
__wakeup(): chamado logo depois da reconstrução do objeto__destruct(): chamado quando o objeto é destruído (no fim do script, por exemplo)__toString(): chamado quando o objeto é usado como string
Se um desses métodos, em alguma classe do site, executa uma operação sensível (gravar um arquivo, chamar uma função cujo nome está guardado em uma propriedade…), o atacante pode alcançá-la. Encadeando várias classes cujos métodos chamam uns aos outros, ele monta uma cadeia de gadgets, ou cadeia POP (Property Oriented Programming), que termina em uma ação perigosa. Nenhum código é injetado diretamente: o atacante apenas desvia código que já existe.

Um exemplo no WordPress: GiveWP (CVE-2024-5932)
Em agosto de 2024, a Wordfence publicou uma falha crítica do plugin de doações GiveWP, instalado em mais de 100.000 sites. Um atacante sem autenticação podia injetar um objeto PHP pelo parâmetro give_title do formulário de doação. Como existia uma cadeia de gadgets no próprio código do plugin, a injeção levava à execução remota de código e à exclusão de arquivos.
| Item | Valor |
|---|---|
| Identificador | CVE-2024-5932 |
| Tipo | Injeção de objeto PHP (CWE-502), sem autenticação |
| Versões afetadas | Até a 3.14.1, inclusive |
| Versão corrigida | 3.14.2 (7 de agosto de 2024) |
| Pontuação CVSS | 10,0 (Wordfence), 9,8 (NVD) |
| Impacto | Execução de código, exclusão de arquivos |
A correção não encerrou o assunto: a CVE-2024-8353 mostrou em setembro de 2024 que a verificação original podia ser contornada, por causa de um tratamento stripslashes_deep aplicado aos dados. Um reforço adicional foi incluído na versão 3.16.2. Isso é típico dessas falhas: corrigir a porta de entrada óbvia nem sempre basta, e uma segunda revisão de segurança costuma ser necessária antes de dar o problema por encerrado.
Phar, maybe_unserialize e o núcleo do WordPress
Dois casos esclarecem o papel do ambiente. Primeiro, o wrapper phar://. Antes do PHP 8.0, o simples fato de manipular um arquivo Phar (via file_exists, getimagesize…) desserializava automaticamente os seus metadados. Era esse o vetor explorado no BuddyForms (CVE-2023-26326, CVSS 9,8): um atacante enviava um arquivo Phar disfarçado e depois fazia com que ele fosse chamado via phar://. O PHP 8.0 eliminou essa desserialização automática dos metadados Phar, o que reduz bastante esse risco nas hospedagens modernas.
Depois, o próprio núcleo do WordPress. Em dezembro de 2023, a versão 6.4.2 neutralizou uma cadeia POP introduzida na classe WP_HTML_Token: o seu destrutor chamava uma função cujo nome vinha de uma propriedade. O WordPress adicionou um método __wakeup() que lança uma exceção assim que se tenta desserializar esse objeto. A equipe ressaltou que a falha não era diretamente explorável sozinha, mas podia se tornar grave combinada com certos plugins, sobretudo em multisite. É uma boa ilustração de cadeia POP: o núcleo fornecia o gadget, e um plugin vulnerável teria fornecido a porta de entrada.

Como se proteger: desenvolvedores e administradores
Para quem desenvolve plugins ou temas, as regras são claras:
- Nunca passar entrada de usuário para
unserialize(); preferirjson_decode()ejson_encode()para trocar dados. - Se a desserialização for inevitável, usar a opção
allowed_classes(comofalsepara não aceitar nenhum objeto): disponível desde o PHP 7.0 e estritamente tipada desde o PHP 7.1. - Validar e assinar os dados armazenados (por exemplo com
hash_hmac()) para garantir que não foram alterados. - Desconfiar das entradas que chegam ao
maybe_unserialize()do WordPress, que chamaunserialize()sempre que o dado parece conteúdo serializado.
Para quem administra um site e não mexe no código, a defesa é mais clássica, mas decisiva:
- Atualizar sem demora o núcleo, os plugins e os temas; essas falhas são quase sempre corrigidas por uma nova versão.
- Usar uma versão do PHP com manutenção (8.1 ou superior), o que elimina, entre outras coisas, a desserialização automática dos metadados Phar.
- Reduzir o número de plugins instalados: menos código significa menos cadeias de gadgets possíveis.
- Monitorar a integridade dos arquivos e manter backups testados, para detectar e reparar um comprometimento.
Para lembrar
- A injeção de objeto PHP explora o unserialize() sobre um dado controlado: ela reconstrói objetos cujos métodos mágicos se executam sozinhos.
- Uma cadeia de gadgets (POP) encadeia classes já existentes para chegar a uma ação perigosa, sem injetar código.
- Casos reais (GiveWP CVE-2024-5932, CVSS 10,0; BuddyForms CVE-2023-26326) atingiram plugins do WordPress muito instalados.
- No código: nunca entrada de usuário no unserialize(); no site: atualizações, PHP com manutenção, menos plugins, integridade monitorada.
O papel do WP Masquerade
O WP Masquerade não corrige uma falha de plugin nem filtra uma carga de desserialização: ele não é um firewall de aplicação, e o guia dele diz isso claramente. A contribuição dele é complementar. O mascaramento das assinaturas públicas e o endurecimento dificultam o reconhecimento que precede o ataque a um plugin específico. Sobretudo, depois de um ataque bem-sucedido, a verificação de integridade do núcleo (Pro) aponta os arquivos modificados, e os alertas por e-mail avisam rapidamente. Uma função Pro em desenvolvimento acrescenta alertas sobre plugins vulneráveis, com o detalhe da falha, para disparar a atualização o quanto antes. A defesa de fundo contra a injeção de objeto continua sendo a atualização rápida e um código que nunca desserializa entrada de usuário.
Vídeos para se aprofundar
Fontes
- NVD - CVE-2024-5932 (GiveWP) (abre em uma nova aba)
- NVD - CVE-2023-26326 (BuddyForms, phar) (abre em uma nova aba)
- php.net - Manual: unserialize() e allowed_classes (abre em uma nova aba)
- WordPress.org - Versão 6.4.2 (manutenção e segurança) (abre em uma nova aba)
Outras fontes consultadas: outros registros CVE, documentação oficial e banco de dados Wordfence.


