Vulnerabilidades do PHP

Desserialização PHP e injeção de objetos explicadas

Ilustração: desserialização PHP e injeção de objetos

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.

Diagrama: dado controlado, unserialize, métodos mágicos e cadeia POP até uma ação perigosa
O princípio: um dado forjado desperta métodos que se encadeiam até a ação final.

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.

ItemValor
IdentificadorCVE-2024-5932
TipoInjeção de objeto PHP (CWE-502), sem autenticação
Versões afetadasAté a 3.14.1, inclusive
Versão corrigida3.14.2 (7 de agosto de 2024)
Pontuação CVSS10,0 (Wordfence), 9,8 (NVD)
ImpactoExecução de código, exclusão de arquivos
CVE-2024-5932: uma injeção de objeto com nota máxima pela Wordfence.

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.

Linha do tempo de casos de injeção de objeto PHP no ecossistema WordPress de 2023 a 2025
A desserialização continua sendo uma fonte regular de falhas críticas, tanto no núcleo quanto nos plugins.

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(); preferir json_decode() e json_encode() para trocar dados.
  • Se a desserialização for inevitável, usar a opção allowed_classes (como false para 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 chama unserialize() 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

Uma explicação visual do princípio da desserialização insegura (em inglês).
Introdução prática à injeção de objetos PHP e às cadeias de gadgets (em inglês).

Fontes

Outras fontes consultadas: outros registros CVE, documentação oficial e banco de dados Wordfence.

Vulnerabilidades do PHP6 min

CVE-2024-2961: a falha glibc iconv que mira o PHP

Uma falha de 24 anos na glibc permite transformar uma leitura de arquivo PHP em execução de código. Mecanismo, versões afetadas, verificação e correção.

Vulnerabilidades do PHP6 min

CVE-2024-4577: a falha do PHP-CGI no Windows explicada

Uma conversão de caracteres do Windows reabriu uma falha do PHP-CGI de doze anos atrás. Condições de exposição, cronologia da exploração, versões corrigidas e verificações a…

Segurança WordPress, sem ruído

Um e-mail quando importa: novos ataques observados, atualizações do plugin e guias práticos. Sem spam, cancelamento com um clique.

Comece de graça e mude para o Pro quando estiver pronto

A versão gratuita já oculta o WordPress e muda o endereço da página de login. O Pro acrescenta aliases, verificação em duas etapas e monitoramento.