CVE-2024-23108: Fortinet FortiSIEM 2nd Order Command Injection Deep-Dive

by | May 28, 2024 | Attack Blogs, Disclosures

In November of 2023, preparing for a call for papers, I attempted to investigate the FortiSIEM patch for CVE-2023-34992. I kindly inquired with the PSIRT if I could have access to the most recent versions to some of their appliances to validate the patches, to which they declined. Acquiring access a different way, I eventually was able to analyze the patch.

While the patches for the original PSIRT issue, FG-IR-23-130, attempted to escape user-controlled inputs at this layer by adding the wrapShellToken() utility, there exists a second order command injection when certain parameters to datastore.py are sent. There exist two distinct vulnerabilities which were assigned CVE-2024-23108 and CVE-2024-23109, both with a CVSS3 score of 10.0, which allows remote, unauthenticated command execution as root. This blog will only cover the first, CVE-2024-23108, given they’re both patched in the same release.

CVE-2023-34992 Patch and Code Flow Analysis

In CVE-2023-34992, the phMonitor service on tcp/7900 was abused by sending it a handleStorageRequest message with a malicious server_ip value. When phMonitor received this message the specific command to be executed would be:
/usr/bin/python3.9 /opt/phoenix/deployment/jumpbox/datastore.py nfs test ‘<server_ip>’ ‘<mount_point>’ online. Inspecting the control flow of datastore.py for this type of request, we see that the server_ip field is validated by attempting to connect to the IP address.

Figure 1. datastore.py validating server_ip

After this, control is eventually passed to /opt/phoenix/deployment/jumpbox/datastore/nfs/test.py. Here, a call to __testMount() formats a call to os.system() on line 23, which derives the nfs_string value from our user-controlled mount_point payload value.

Figure 2. __testMount() calls os.system()

By formatting a request to the phMonitor client with a command type of 81, and the following payload, an unauthenticated attacker can achieve remote code execution as root.

Figure 3. Exploiting for reverse shell

The astute reader will notice that there is very little difference in the exploitation of the previous command injection, CVE-2023-34992, to this one, CVE-2024-23108, reported 6 months later.

Figure 4. CVE-2023-34992 vs CVE-2024-23108

Our proof of concept exploit can be found on our GitHub.

Indicators of Compromise

The logs for the phMonitor service will verbosely log many details of messages it receives and can be found at /opt/phoenix/logs/phoenix.log. Attempts to exploit CVE-2024-23108 will leave a log message containing a failed command with datastore.py nfs test. These lines should be inspected for malicious looking input.

Figure 5. Malicious commands logged


29 November 2023 – Reported CVE-2024-23108

30 November 2023 – Reported CVE-2024-23109

3 January 2024 – PSIRT reproduces issues

16 January 2024 – Fortinet silently fixes the issues in v7.1.2 build 0160 with no mention of the vulnerabilities, PSIRT releases, or CVEs published

31 January 2024 – Fortinet publicly “discloses” the issues by adding unpublished CVE IDs to the PSIRT released for CVE-2023-34992 6 months prior without adding a changelog entry

7 February 2024 – Fortinet publicly publishes the CVE IDs, but states they were duplicates published in error, and then states they were real

Sometime later in 2024 – Fortinet eventually adds a changelog entry to the PSIRT and adds CVE IDs to the release documents

28 May 2024 – This blog


Figure 6. NodeZero exploiting CVE-2024-23108 to load a remote access tool for post-exploitation activities

Horizon3.ai clients and free-trial users alike can run a NodeZero operation to determine the exposure and exploitability of this issue.

Sign up for a free trial and quickly verify you’re not exploitable.

Start Your Free Trial





How can NodeZero help you?

Let our experts walk you through a demonstration of NodeZero, so you can see how to put it to work for your company.