SuiteCRM: vulnerabilidade de desserialização de PHAR permite execução de código
Sam Sanoop
7 de maio de 2021
0 minutos de leituraO SuiteCRM é um aplicativo de gerenciamento de relacionamento com o cliente gratuito e de código aberto para servidores. Este comunicado detalha uma vulnerabilidade de desserialização de PHAR no SuiteCRM que pode ser explorada por um administrador autenticado para executar comandos no sistema operacional subjacente. Esse problema foi corrigido na versão 7.11.19.
No PHP, arquivos PHAR (PHP Archive) podem ser usados para empacotar aplicativos e bibliotecas PHP em um único arquivo compactado. O formato PHAR no PHP usa um único formato de arquivo que pode armazenar e executar vários códigos PHP. Os arquivos PHAR contêm metadados sobre os arquivos do pacote. Em um arquivo PHAR, esses metadados são armazenados em formato serializado.
Quando uma operação de arquivo é realizada em um arquivo PHAR por meio do wrapper phar://, os metadados do arquivo PHAR são desserializados. Assim, um invasor pode realizar a injeção de objetos PHP sem usar a função unserialize(), fazendo upload de um arquivo PHAR. Essa vulnerabilidade ganhou notoriedade depois que Sam Thomas publicou sua pesquisa na BlackHat USA 2018, intitulada It's a PHP Unserialization Vulnerability Jim, but Not as We Know It, que afetou vários sistemas de gerenciamento de conteúdo. Para explorar essa vulnerabilidade, duas condições precisam ser atendidas:
Uma função do sistema de arquivos PHP, como
file_exists, que possa ser controlada e acione a funçãounserialize()A possibilidade de fazer upload de um arquivo PHAR com extensão .phar, .zip ou .jpeg para o sistema-alvo, e de conhecer o caminho desse arquivo
Detalhes técnicos da desserialização de PHAR
Causa raiz
Essa vulnerabilidade contorna os mecanismos de segurança implementados pelos responsáveis pelo SuiteCRM para corrigir o CVE-2020-8801. Conforme descrito no comunicado sobre o CVE-2020-8801, várias áreas do painel de administração do SuiteCRM, incluindo Backups, Import e UpgradeWizard, podem ser usadas para acionar a desserialização de PHAR. Os responsáveis corrigiram o problema na versão 7.11.13, com o commit 571cbfa209da4c8280a5359f301115de25b4c6e3.

A função strpos é usada para verificar se um parâmetro do usuário contém uma ocorrência do URI phar://. No entanto, como a função strpos é usada, essa verificação diferencia maiúsculas de minúsculas. Assim, é possível contorná-la usando letras maiúsculas e acionar a desserialização de PHAR chamando o URI como PHAR://.
Encontrar um gadget utilizável
Embora seja possível contornar a correção do SuiteCRM para a verificação do URI PHAR, descobrimos que os responsáveis pelo SuiteCRM tomaram precauções para impedir o uso de todos os possíveis gadgets POP que poderiam ser acionados por um invasor por meio da desserialização. Para isso, adicionaram um método mágico __wakeup às classes consideradas perigosas. Esse método é invocado automaticamente sempre que um objeto é desserializado e garante que todas as propriedades do objeto sejam destruídas durante a desserialização. Veja um exemplo abaixo.

Em modules/Import/sources/ImportFile.php, existe um método mágico __destruct que poderia ser explorado para excluir arquivos arbitrários de um sistema por meio de desserialização insegura. Porém, devido à presença do método __wakeup mencionado acima, um invasor não consegue explorar esse método __destruct. Essa verificação foi encontrada em toda a base de código do SuiteCRM.
No entanto, ao analisar mais de perto as dependências do SuiteCRM, foi possível encontrar um método __destruct utilizável, que poderia ser explorado para excluir arquivos arbitrários. O SuiteCRM usa a biblioteca zend-gdata, que tem zf1/zend-http como dependência transitiva.
No arquivo Stream.php do pacote zf1/zend-http, existe um método __destruct que, quando acionado, executa a função @unlink na propriedade $stream_name de um objeto. A função @unlink nesse método pode ser explorada para excluir um arquivo. Para que essa função seja acionada, o objeto também precisa ter uma propriedade $_cleanup. O código desse método __destruct pode ser visto abaixo.

A existência desse gadget já é conhecida e ele está disponível na biblioteca PHPGGC. O PHPGGC é uma biblioteca de payloads de unserialize() que inclui um script para gerar um payload de gadget POP com base nos parâmetros informados pelo usuário.
Observação: Se as dependências de desenvolvimento também estiverem instaladas em uma instalação do SuiteCRM, uma versão vulnerável do PHP-CS-Fixer também poderá ser explorada para excluir arquivos arbitrários, em vez do zf1/zend-http. Veja aqui o pull request que integra esse gadget POP ao PHPGGC: https://github.com/ambionics/phpggc/pull/93.
Encontrar e explorar uma funcionalidade de upload
Embora o comunicado sobre o CVE-2020-8801 explique os parâmetros e as áreas do SuiteCRM que podem ser usadas para desserialização de PHAR, nem o comunicado nem o blog relacionado do pesquisador que descobriu o problema indicam onde é possível fazer upload de um arquivo PHAR ou qual caminho/localização poderia ser explorado. Além disso, descobrimos que todos os arquivos enviados ao SuiteCRM são renomeados sem extensão, e o nome é alterado para um identificador UUID aleatório. Por exemplo, o arquivo party-parrot.png, enviado como parte de um documento, passa a se chamar 51eea769-ce13-40bb-fb25-60197bf855ae.

No entanto, após analisar melhor as funcionalidades do SuiteCRM, descobrimos que os arquivos ZIP enviados pelo Module Loader não seguem esse comportamento. Os arquivos ZIP de módulos são enviados e salvos em um local arbitrário, com a extensão .zip, que um invasor pode adivinhar. Isso permite atender aos requisitos para explorar uma vulnerabilidade de desserialização de PHAR. Veja um exemplo abaixo:

O arquivo examplemodule.zip enviado será armazenado no local a seguir. O arquivo manifest.php é retirado do diretório module.zip e também fica disponível nesse mesmo local.

Acionar a exclusão de arquivos arbitrários
Agora que o caminho de um arquivo ZIP enviado é conhecido, que há um gadget de exclusão de arquivos e que existem funções capazes de acionar a desserialização de PHAR, é possível explorar essas condições em uma instalação do SuiteCRM.
Com o PHPGGC, é possível criar um arquivo PHAR de exemplo da seguinte forma:
O comando acima cria um arquivo PHAR no formato ZIP chamado malicious.zip. Ele insere um payload serializado do gadget POP zf1/zend-http mencionado anteriormente e define a propriedade $stream_name desse objeto serializado como /tmp/test.txt. Além disso, a opção -f do PHPGGC também pode ser usada para garantir que o objeto serializado seja destruído logo após a chamada de unserialize(), tornando o payload mais confiável.
Observação: Para que o aplicativo aceite esse arquivo ZIP, também é preciso adicionar a ele um arquivo manifest.php de exemplo. No Linux, isso pode ser feito da seguinte forma:
Depois do upload, esse arquivo ficará no diretório upload/upgrades/module.

Agora, é possível acionar esse arquivo pela seção Backups do painel de administração do SuiteCRM.

Da exclusão de arquivos à execução de código
Ao explorar a exclusão de arquivos, é possível apagar arquivos do código-fonte do aplicativo e realizar ataques de negação de serviço. Também é possível usar a exclusão de arquivos para executar código arbitrário em uma instalação do SuiteCRM, apagando um arquivo .htaccess e acessando diretamente os arquivos enviados.
O .htaccess é um arquivo de configuração distribuído que permite ao Apache gerenciar alterações de configuração por diretório. Em uma instalação do SuiteCRM, esse arquivo bloqueia o acesso direto a diretórios como /upload e /files. A desserialização de PHAR pode ser explorada para excluir esse arquivo. Além disso, o manifest.php mencionado anteriormente pode ser usado para inserir e acionar código PHP.
Ao enviar um módulo pela funcionalidade Module Loader, o SuiteCRM exige que também haja um arquivo manifest.php. Veja um exemplo abaixo:

Por padrão, o SuiteCRM verifica se o arquivo enviado não contém chamadas a funções suspeitas, como exec ou system. Veja aqui a lista completa de chamadas de função restritas: Restrições do Module Loader
Essa verificação não considera a função “include”. No PHP, a função include pode ser usada para incluir arquivos (por padrão, arquivos locais), que são executados como código PHP. Assim, é possível inserir uma função include no arquivo de manifesto que receba um parâmetro do usuário (include($_GET['p']);). Em seguida, pode-se fornecer um arquivo enviado (que será renomeado pelo SuiteCRM) contendo código PHP malicioso para executar código.
Resumo da desserialização de PHAR
Em resumo, a desserialização de PHAR para execução de código acontece da seguinte forma:
1. Envie um arquivo para o SuiteCRM
Envie um arquivo ao SuiteCRM usando a funcionalidade normal de armazenamento. Neste exemplo, o seguinte conteúdo é enviado como shell.php: <?php echo system($_GET["cmd"]); ?>

O aplicativo renomeia o arquivo para eb7cde01-6190-9ca9-b81b-601998504b41 e o armazena no diretório /var/www/html/uploads. Esse UID pode ser visto no URL do arquivo:
2. Envie um PHAR em ZIP
Envie um arquivo PHAR no formato ZIP que, quando acionado, exclua o arquivo .htaccess e contenha um manifest.php com código PHP inserido. O PHPGGC pode ser usado da seguinte forma:
Em seguida, adicione o código a seguir a um arquivo manifest.php e inclua-o no arquivo PHAR ZIP.
![Editor de código exibindo uma instrução PHP include destacada que usa um parâmetro GET: include($_GET[123]);](https://res.cloudinary.com/snyk/image/upload/f_auto,w_2560,q_auto/f_auto/q_auto/v1620399714/wordpress-sync/blog-suitecrm-phar-include.png)
Depois, envie esse arquivo ZIP ao sistema usando o componente Module Loader.
3. Acione a desserialização de PHAR
Acione a desserialização de PHAR chamando o arquivo maliciousmodule.zip. A área Backups pode ser usada para acionar a desserialização de PHAR. A solicitação HTTP enviada ao aplicativo é a seguinte:
4. Acesse o manifesto maliciousmodule
Acesse o arquivo de manifesto malicousmodule navegando até o caminho do diretório e incluindo o shell.php.txt enviado. Agora que o arquivo .htaccess foi excluído, o diretório de uploads está acessível. O arquivo malcioiusmodule-manifest.php pode ser acessado da seguinte forma:
Agora, é possível especificar ?123 e fornecer o arquivo shell.php.txt:
O arquivo shell.php.txt incluído será interpretado como código, e é possível fornecer o parâmetro cmd, que será executado pelo comando do sistema.

Conclusão
Em conclusão, ao validar dados fornecidos pelo usuário, é preciso garantir que as verificações não diferenciem maiúsculas de minúsculas. Além disso, ao corrigir e impedir o uso de gadgets de desserialização, leve em conta as dependências transitivas, pois elas são carregadas por um projeto pelo recurso de carregamento automático do Composer. O Snyk Open Source também oferece suporte à análise de PHP e pode ser usado para analisar e identificar bibliotecas conhecidas que removeram gadgets de desserialização do código.
