Executive Summary

    On April 13th, CISA added a critical remote code execution (RCE) vulnerability in FortiClient Enterprise Management Server (EMS) to its Known Exploited Vulnerability (KEV) database. The vulnerability is tracked as CVE-2026-21643 and impacts FortiClient EMS versions 7.4.0 up to 7.4.5. This vulnerability was initially reported by Fortinet on February 6th this year. This announcement comes on the tail of CVE-2026-35616, which was targeting newer releases FortiClient EMS mere days earlier.

    As active exploitation has been documented and proof of concept code exists, Beazley Security recommends that any affected organizations check FortiClient EMS systems for signs of compromise and apply released hotfixes immediately.

    Affected Systems or Products

    Product

    Affected Version

    Patch / Fix Available

    FortiClientEMS 8.0

    Not affected

    Not applicable

    FortiClientEMS 7.4

    7.4.4

    Upgrade to 7.4.5 or above

    FortiClientEMS 7.2

    Not affected

    Not applicable

    Mitigations / Workarounds

    As active exploitation has been confirmed in the wild and updates for this version have already been released, organizations should update as soon as possible. If updating is not an immediate option, risk can be temporarily reduced by:

    • Restricting access to FortiClient EMS management interfaces to internal, trusted networks only.

    • If remote access is required to manage endpoint security, securing access to FortiClient EMS behind a Virtual Private Network.

    • BishopFox reports that disabling multitenancy will set SiteMiddleWare functionality to never read the Site headers used to exploit the flaw, indicating the vulnerable code will not be run on exploitation attempts.

    Patches

    Fortinet released newer EMS versions since this vulnerability was announced, which we have already reported being attacked in the wild. FortiClient EMS 7.4.5 is confirmed to be the oldest supported version of EMS that has this vulnerability fixed. However, given the previously reported attacks to FortiClient EMS 7.4.5, we advise updating to the current release of EMS. If this is not possible, we advise updating to 7.4.5 and including hotfixes for other exploited vulnerabilities. Hotfixes for 7.4.5 can be found by accessing the PSIRT advisory.

    Indicators of Compromise

    At the time of this writing, Fortinet PSIRT confirmed active exploitation in the wild but have not publicly released indicators of compromise or technical details about the vulnerability.

    The attack does not require authentication or user interaction, meaning exploitation can be carried out remotely by an attacker that has network access to an exposed FortiClient EMS instance.

    Although no specific indicators of compromise have been released, defenders can monitor for these signs of attack and post-exploitation activity:

    • Error responses (HTTP 500) involving the EMS API endpoint at /api/v1/init_consts or an egregious number of requests to the endpoint.

    • Unexpected configuration changes to FortiClient EMS devices or modifications to downstream endpoint security policies.

    • Unauthorized user accounts or privilege escalation on FortiClient EMS devices.

    • Unexpected process execution or processes spawned by EMS services.

    Technical Details

    Although Fortinet PSIRT teams have not released technical details regarding this vulnerability at the time of writing, independent researchers at BishopFox have reviewed CVE-2026-21643 and have identified the vulnerable code paths for this vulnerability.

    Functionally, this vulnerability is due to improper input validation on a middleware function. On an unauthenticated HTTP request, FortiClient EMS will log the request before setting variables based on the Site header before opening a connection to the EMS database. This means that attackers could forge a request that has malicious site headers that terminate the correct database connection flow, instead performing the attackers’ SQL commands. Below, you can see the searchpath being set with user-controlled input without sanitization in the decompiled 7.4.4 EMS code:

    class PostgresConnection:
        def __init__(self, vdom, ...):
            self.db_name = f"fcm_{vdom}"
            self.searchpath = f"SET search_path TO '{self._db_prefix}{self.db_name}', public, addons"
    
        def execute(self, query, ...):
            self._connection.execute(self.searchpath)

    Given active exploitation in the wild and downstream impacts of compromise, Beazley Security recommends affected organizations apply hotfixes immediately.

    How Beazley Security is responding

    Beazley Security is monitoring client perimeter devices through our Exposure Management Platform to identify impacted devices and support organizations in remediation of any issues found.

    We are also conducting threat hunts across our MDR environment to detect potential exploitation attempts against our clients.

    If you believe your organization may have been impacted by this attack campaign and need support, please contact our Incident Response team.