Segurança de Aplicação

Nova CVE-2023-4314 identificada em plugin do WordPress

Neste artigo, vamos analisar um estudo de caso de uma CVE encontrada em um plugin do WordPress – wpDataTables, quando anterior à versão 2.1.66, que consiste em uma vulnerabilidade da categoria A8: Insecure Deserialization (desserialização insegura).

Estudo de Caso: plugin do WordPress

Recentemente foi identificada uma vulnerabilidade em um plugin do WordPress – wpDataTables, classificada como CWE-502: Deserialization of Untrusted Data. Esta  vulnerabilidade pode ser classificada como A8: Insecure Deserialization.

Através desta vulnerabilidade, tecnicamente, é possível passar conteúdo desserializável por um parâmetro de um endpoint admin ajax do WordPress e realizar injeção de objetos PHP. Além disso, caso seja encontrado um ou múltiplos gadgets chains adequados é possível obter execução remota de comando no sistema. Ademais, a brecha de segurança também pode ser explorada pelo frontend do plugin.

A vulnerabilidade ocorre em uma função chamada serializedPhpRenderData do arquivo class.wpdatatables.php, a qual faz uma requisição HTTP a uma URL externa e desserializa o conteúdo através da função nativa unserialize do PHP.

função nativa unserialize do PHP

Exploração

Primeiramente, para explorarmos a vulnerabilidade podemos simular um gadget chain adicionando no final do arquivo source/class.wpdatatables.php do plugin o seguinte código:

class Evil {

  public function __wakeup() : void {

    die(“Arbitrary deserialization”);

  }

}

Este código representa uma classe chamada Evil e possui a função mágica __wakeup que será chamada logo após instanciar a classe através da desserialização insegura e que invocará a função die do PHP para fins de testes. 

demonstração

Após isso, é necessário armazenar o payload O:4:”Evil”:0:{}; em um arquivo acessível por URL pública (ex.: por webserver, pastebin e etc) para que seja posteriormente executado  pelo plugin. Este é o payload que vai instanciar a classe Evil do gadget chain que adicionamos no código para fins de testes durante a desserialização insegura.

evil

Em seguida, entramos na página wpDataTables > Create a Table > Create a data table linked to an existing data source.

página wpDataTables

Na entrada de seleção Input data source type selecionamos Serialized PHP array.

seleção Input data source type

Em Input file path or URLcolocamos a URL contendo o payload e pressionamos Save Changes.

Input file path or URL

Após salvar as alterações, é possível observar o payload sendo executado e retornando como resposta “Arbitrary deserialization”.

payload sendo executado

Análise da vulnerabilidade

Ao identificar a utilização da função unserialize, foi necessário pensar em explorar a sequência de funções antecedentes e encontrar o endpoint raíz.

Através da análise do código fonte do plugin, foi possível chegar a uma ajax action no arquivo wdt_admin_ajax_actions.php que dava início a sequência de chamadas necessárias para alcançar a função serializedPhpRenderData.

análise do código fonte

Esta ajax action chama a função wdtSaveTableWithColumns que recebe um parâmetro POST table e que ao final da função invoca a função saveTableConfig passando o valor do table como um JSON.

Entrando na função saveTableConfig do arquivo class.wdtconfigcontroller.php, foi possível identificar que a função chama tryCreateTable passando os valores table_type e content do JSON passado no parâmetro POST citado anteriormente. Vale ressaltar que, foi preciso definir o valor da chave table_type do JSON como “serialized” para a desserialização ser engatilhada nas funções posteriores e o valor da chave content como a URL do webserver contendo o nosso payload.

análise do código fonte

Posteriormente, analisando a função tryCreateTable do arquivo class.wdtconfigcontroller.php foi possível identificar que é instanciada uma variável chamada $tableData onde será definida algumas propriedades baseadas nos valores que passamos por POST anteriormente, e, em seguida, ser passada na função fillFromData na linha 708.

função fillFromData

Já na função fillFromData do arquivo class.wpdatatable.phpé possível identificar na linha 2268 um switch condicional que verifica o valor de $tableData->table_type. Se o valor for serialized então ele passa o content para a função serializedPHPBasedConstruct, como pode ser visto na linha 2296.

função fillFromData

Entrando na função serializedPHPBasedConstruct do arquivo class.wpdatatable.php é possível perceber que o primeiro parâmetro da função é chamado $url, assim, é conclusivo que o content é utilizado como uma URL posteriormente. Esse parâmetro é passado na função sourceRenderData na linha 1647.

sourceRenderData

Fazendo uma análise da função sourceRenderData do arquivo class.wpdatatable.php foi possível identificar que na linha 1799 é verificado se o sourceType é serialized e sem seguida passado o parâmetro $source (nossa URL) na função serializedPhpRenderData.

análise da função sourceRenderData

Ao explorar a função serializedPhpRenderData do mesmo arquivo, é possível identificar que na segunda linha é realizada uma requisição para a nossa URL, salvo em uma variável chamada $serialized_content, e, em seguida, desserializada na nossa função alvo que é a unserialize.

serializedPhpRenderData

Conclusivamente, a ordem da sequência de funções seria essa:

  1. add_action(‘wp_ajax_wpdatatables_save_table_config’, ‘wdtSaveTableWithColumns’);
  2. saveTableConfig
  3. WDTConfigController::tryCreateTable
  4. $tbl->fillFromData($tableData, array())
  5. $this->serializedPHPBasedConstruct(…
  6. $PHPArray = self::sourceRenderData($this, ‘serialized’, $url);
  7. $sourceArray = self::serializedPhpRenderData($source, $wpId);
  8. unserialize

Impacto

A vulnerabilidade requer um privilégio mínimo de administrador no WordPress, além disso, ela permite que sejam realizados ataques em um ambiente multisite. O multisite é um recurso especial do WordPress que as empresas e marcas utilizam para gerenciar vários sites a partir de um único painel do CMS (Content Management System), ou seja, é possível ampliar a invasão para outros sites além do atual.

Além disso, caso seja encontrado um gadget chain apropriado, é possível obter execução remota de comandos.

Mitigação

Neste contexto, podem existir diversas maneiras de mitigar essa vulnerabilidade, algumas delas são:

Caso seja necessário a utilização do unserialize:

  • Realizar filtragem na URL de origem por whitelist
  • Realizar filtragem no conteúdo da resposta da URL por whitelist, por exemplo, verificar previamente qual classe ou tipo de dado que está prestes a ser instanciado na desserialização.
  • Não permitir que a desserialização seja induzida por valores de entradas vindas de usuários.
  • Definir a propriedade allowed_classes como false para evitar a instanciação de classes.

Outras alternativas ao unserialize:

  • Não utilizar unserialize e desenvolver um sistema próprio de serialização de dados para um tipo específico de dados, caso seja consentido que apenas um tipo de estrutura, seja utilizado.

Referências

Nova call to action
About author

Articles

Desenvolvedor de software, escritor de artigos de cibersegurança e penetration tester certificado com OSCP, OSWE, DCPT, eWPTXv2, eJPT, CCSA v2, DPO, LGPD, ISO/IEC 27001, ISO/IEC 27032 e etc.
Related posts
Segurança de Aplicação

Secure by Design em ASPM - Entenda como as ferramentas se integram nesse processo

Em um momento onde continuamos a ver problemas de vazamentos de dados e vulnerabilidades em…
Read more
Segurança de Aplicação

Mitigação de Vulnerabilidades: Elevando a Segurança no Desenvolvimento de Software

No cenário digital em constante evolução, a importância da segurança de software não pode ser…
Read more
Segurança de Aplicação

A Importância da Supply Chain para a Segurança das Aplicações

Para iniciar, quando pensamos em desenvolvimento de software, geralmente associamos essa área a…
Read more

Deixe um comentário