Ivanti Connect Secure UTA0576 — Actively Exploited Three-CVE Root Chain

Threat Overview

An unauthenticated attacker can chain CVE-2026-104935 (CGI routing authentication bypass and file execution), CVE-2026-118527 (predictable temporary upload location), and CVE-2026-111357 (privilege escalation through a privileged service) to execute commands as root on Ivanti Connect Secure gateways. Volexity documented UTA0576 using this access to collect LDAP service-account credentials, enumerate AD for LAPS and BitLocker recovery information, test credentials, and manipulate appliance logs. The actor re-ran the exploit chain for commands rather than installing a conventional web shell. The October 29 update fixed the remaining two chain components, making this a new patch-verification priority rather than recycled coverage of the October 13 disclosure.

References

Volexity original investigation and Oct 29 update — 2026-10-13 / 2026-10-29

SOCRadar updated exploit-chain briefing — 2026-11-02

Ivanti security advisory (vendor; referenced by SOCRadar)

Impacted Systems

Vendor/product: Ivanti Connect Secure (ICS), on-premises or virtual VPN gateway appliance, Internet-facing HTTPS VPN portal. Confirmed affected branches for the original auth-bypass: 25.1.1.1 and earlier, 25.1.2.2 and earlier, 22.8R2.4 and earlier. The subsequent CVEs also affect 25.1.1.2 and earlier and 22.8R2.5 and earlier. Fixed for full chain: 25.1.1.3, 22.8R2.6; newer 25.1.3.x builds were reported fixed for original vulnerability, but confirm complete chain coverage against Ivanti advisory. The 22.7R2.14-and-earlier branch is explicitly not affected by CVE-2026-104935. Exposure: reachable VPN portal, no credentials required for the complete chain. Other Ivanti products are not asserted affected.

Why this matters

Confirmed exploitation of Internet-facing remote-access infrastructure can lead to privileged access to Active Directory. The staged October 29 fixes mean a device patched only on October 13 may still need an upgrade.

Exploitation Status

Confirmed. Volexity investigated exploitation beginning October 3, 2026, and Ivanti acknowledged limited affected customers. CISA KEV additions on October 13 and October 30 reinforce the urgency. No claim is made about any specific MSSP customer.

Observed activity / IOCs and caveats: Observed: repeated welcome.cgi requests with X-DSCGI-PATH selecting protected handlers; temporary uploaded Perl scripts; in-memory Python execution; DSCache manipulation; LDAP credential access, LAPS/BitLocker searches, password spraying, log deletion and packet capture. Volexity reported infrastructure 108.165.147[.]64. Attribution to criminal motives is low confidence; LLM-assisted tooling is a medium-confidence researcher assessment, not confirmed vendor attribution.

What this hunt looks for

An edge VPN appliance has direct access to identity infrastructure, and exploitation can bypass ordinary endpoint visibility. The October 29 remediation closes a gap for organizations that applied only the October 13 patch.

Required logs

CommonSecurityLog; SecurityEvent; Syslog — only where ingested into Microsoft Sentinel. No customer workspace was queried.

I01 — Ivanti CGI routing and file-upload exploit patterns

Required: CommonSecurityLog.

CommonSecurityLog
| where TimeGenerated >= ago(30d)
| extend Raw = strcat(tostring(RequestURL), ' ', tostring(Message), ' ', tostring(AdditionalExtensions))
| where Raw has 'welcome.cgi' and (Raw has 'wu.cgi' or Raw has 'X-DSCGI-PATH' or Raw has '/home/runtime/tmp/')
| project TimeGenerated, DeviceName, SourceIP, DestinationIP, RequestURL, Activity, DeviceAction, Raw
| order by TimeGenerated desc

I02 — High-frequency Ivanti welcome.cgi requests

Required: CommonSecurityLog.

CommonSecurityLog
| where TimeGenerated >= ago(30d)
| extend Raw = strcat(tostring(RequestURL), ' ', tostring(Message))
| where Raw has '/dana-na/auth/url_default/welcome.cgi'
| summarize Requests=count(), DistinctActions=dcount(DeviceAction), Sample=take_any(Raw) by bin(TimeGenerated, 5m), SourceIP, DestinationIP
| where Requests >= 20
| order by Requests desc

I03 — Published UTA0576 infrastructure traffic

Required: CommonSecurityLog.

let KnownIP = '108.165.147.64';
CommonSecurityLog
| where TimeGenerated >= ago(45d)
| where SourceIP == KnownIP or DestinationIP == KnownIP
| extend MatchedIOC=iff(SourceIP == KnownIP, SourceIP, DestinationIP)
| project TimeGenerated, MatchedIOC, SourceIP, DestinationIP, DeviceName, DeviceAction, Activity, RequestURL
| order by TimeGenerated desc

I04 — Ivanti appliance log indicators and anti-forensic artifacts

Required: Syslog.

Syslog
| where TimeGenerated >= ago(30d)
| where SyslogMessage has_any ('dsstatmond','/data/.icscap','/tmp/ml.py','/tmp/rq5.py','/tmp/mk.py','/tmp/rr.py','ics-root-','/home/runtime/tmp/')
| project TimeGenerated, Computer, Facility, SeverityLevel, ProcessName, SyslogMessage
| order by TimeGenerated desc

I05 — Possible password spraying from a single internal source

Required: SecurityEvent.

SecurityEvent
| where TimeGenerated >= ago(30d)
| where EventID == 4625
| where isnotempty(IpAddress) and IpAddress !in ('-','127.0.0.1','::1')
| summarize Failures=count(), TargetAccounts=dcount(TargetUserName), SampleAccounts=make_set(TargetUserName, 8) by bin(TimeGenerated, 15m), IpAddress
| where Failures >= 20 and TargetAccounts >= 8
| order by Failures desc

I06 — Unusual Kerberos ticket bursts from one client

Required: SecurityEvent.

SecurityEvent
| where TimeGenerated >= ago(30d)
| where EventID == 4769
| extend ClientIP = tostring(column_ifexists('IpAddress',''))
| where isnotempty(ClientIP) and ClientIP != '-'
| summarize Tickets=count(), DistinctServices=dcount(ServiceName), Services=make_set(ServiceName, 12) by bin(TimeGenerated, 15m), ClientIP, Account
| where Tickets >= 30 and DistinctServices >= 12
| order by Tickets desc

I07 — Unusual LDAP or AD-service network activity from VPN appliance

Required: CommonSecurityLog.

CommonSecurityLog
| where TimeGenerated >= ago(30d)
| where DestinationPort in (389,636,88,445,53)
| summarize Connections=count(), DistinctDestinations=dcount(DestinationIP), Destinations=make_set(DestinationIP, 15) by bin(TimeGenerated, 1h), SourceIP, DestinationPort
| where Connections >= 50 and DistinctDestinations >= 4
| order by Connections desc

Detection Notes

Highest signal: I01 if the HTTP header is actually ingested; I04 if appliance logs contain artifacts; I03 is a time-bounded published IOC. I02 can be normal login noise. I05–I07 are generic follow-up patterns and need gateway-IP attribution. The actor intentionally removed debug/audit records and did not leave a persistent web shell; clean local logs or Integrity Checker output do not rule out compromise. CommonSecurityLog often lacks request headers; Syslog and Windows SecurityEvent may not include appliance or DC events. No customer telemetry was queried.

Scope: conclusions are limited to Sentinel-ingested data and retention. No customer-specific finding is asserted.

Leave a Reply