# Xen Orchestra Authentication Bypass (VSA-2026-062) Actively Exploited to Hijack VM Servers

> A critical authentication bypass in Xen Orchestra and Xen Orchestra Appliance (XOA) lets an unauthenticated attacker log in as an existing token owner by sending a crafted authenticationToken cookie that parses to an empty JSON object. Vates confirmed active exploitation by an actor operating from 91.211.251.112 and a Tor onion service; fixes ship in Xen Orchestra 6.9.1/6.10.0 (xo-server 5.211.2/5.213.1).

- **Published:** 2026-11-10T16:44:59Z
- **Last reviewed:** 2026-11-11T15:54:02.446Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-5663
- **ID:** TL-2026-5663
- **Severity:** CRITICAL
- **Category:** VULNERABILITY
- **Status:** ACTIVE
- **Detections:** 9 (1 shown free below) · **IOCs:** 25 (3 shown free below)

## Description

VSA-2026-062 ("Empty-object login token") is an authentication bypass in the REST API of Xen Orchestra (XO), the management plane for XCP-ng/XenServer pools, and in the Xen Orchestra Appliance (XOA). REST cookie parsing converts a crafted authenticationToken cookie (authenticationToken=j:{} or URL-encoded authenticationToken=j:%7B%7D) into an empty JavaScript object. The REST authentication path passes that object to the token provider without verifying that it is a string. The token collection lookup treats the empty object as an unfiltered query and returns the first stored token; if that token is unexpired, the requester is authenticated as the token's owner without any credentials.

After bypassing authentication, the attacker calls the authenticated endpoint /rest/v0/users/me/authentication_tokens to retrieve reusable login token IDs, giving durable access that survives patching unless tokens are revoked. Vates states the attacker can perform actions with Admin privilege, which can lead to arbitrary code execution on managed pools and full root takeover of XCP-ng nodes.

Vates attributes exploitation observed in the wild to a threat actor using IP address 91.211.251.112 (port 8001 listed) and the Tor onion service ustar3rqxgnskzgnwkgpofgtvxevm6cx3lxdbwt4mndtveqyaohid.onion (port 3333 listed). Reported host-side artifacts of this campaign include a VM named 'pivot2', VMs configured with the hvm_serial: file platform parameter (visible as '-serial file:' in /var/log/xensource.log*), cron files /etc/cron.d/zz-ustar and /etc/cron.d/zz-ustar2, files /.ustar5 and /.ustar6, and Vates also directs responders to inspect /etc/ld.so.preload. Vates stresses these indicators cover only this campaign and their absence does not prove no compromise.

The flaw was fixed in upstream PR #10748 ("fix(xo-server): validate authentication token IDs", XO-3331, merge commit 50166fe), which rejects non-string and empty token IDs before collection lookups and builds the query only from validated fields while preserving valid string tokens and compound {id, user_id} lookups; the bug was introduced by commit 115bc8f. The PR author reports validation on an appliance running xo-server 5.213.0 showing non-string and empty token IDs are rejected across the REST API, /signin and JSON-RPC session.signIn; stable-branch backport validation was not run per the PR. Exploitation leaves no identifiers in Xen Orchestra logs, so detection requires HTTP traffic inspection (tcpdump/Wireshark, WAF or reverse-proxy logging) for the empty-object cookie. No CVE or CVSS score had been assigned at the time of publication; Vates rates it Critical (CVSS 4.0 'not available yet'). The advisory page's affected-version text lists xo-server 5.213.2 as affected while naming 5.213.1 as fixed, an inconsistency that should be verified against upstream release notes. Discovered by Filip Magic and Christoffer Olsen of TDC NET Security. No public PoC or named threat actor is reported in the sources.

## MITRE ATT&CK

- T1190 Exploit Public-Facing Application
- T1078 Valid Accounts
- T1528 Steal Application Access Token
- T1550.001 Application Access Token
- T1059 Command and Scripting Interpreter
- T1053.003 Cron
- T1574.006 Dynamic Linker Hijacking
- T1090.003 Multi-hop Proxy
- T1571 Non-Standard Port
- T1564.006 Run Virtual Instance
- T1059.004 Command and Scripting Interpreter
- T1068 Exploitation for Privilege Escalation
- T1611 Escape to Host

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**Xen Orchestra Empty-Object authenticationToken Auth Bypass (VSA-2026-062) — Exploitation** (`TL-2026-5663-SPL-001`)

Behaviour-first Splunk detection for the Xen Orchestra REST authentication bypass: flags HTTP requests whose authenticationToken cookie is the empty-object payload j:{} (or URL-encoded j:%7B%7D) and highlights sources that then call /rest/v0/users/me/authentication_tokens to harvest reusable login tokens. Exploited in the wild by infrastructure including 91.211.251.112.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1190, T1078, T1528, T1550.001
- **Data sources:** splunk_stream_http, reverse_proxy_access_logs, waf_logs
- **Severity:** critical
- **Confidence:** high

### Splunk SPL

```spl
index=network sourcetype="stream:http" http_method IN ("GET","POST","PUT","PATCH","DELETE") cookie=*
| regex cookie="(?i)authenticationToken=j(:|%3A)(\{\s*\}|%7B(\s|%20|\+)*%7D)"
| eval token_endpoint=if(like(lower(uri_path),"%/rest/v0/users/me/authentication_tokens%"),1,0)
| stats count AS requests sum(token_endpoint) AS token_listing_requests min(_time) AS first_seen max(_time) AS last_seen values(uri_path) AS uri_paths values(dest_ip) AS xo_servers values(status) AS http_status BY src_ip
| eval first_seen=strftime(first_seen,"%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen,"%Y-%m-%d %H:%M:%S")
| eval stage=if(token_listing_requests>0,"auth_bypass_plus_token_harvest","auth_bypass_attempt")
| table src_ip xo_servers requests token_listing_requests stage uri_paths http_status first_seen last_seen
```

### Microsoft KQL

```kql
let lookback = 24h;
let bypassCookie = @'(?i)authenticationToken=j(:|%3A)(\{\s*\}|%7B(\s|%20|\+)*%7D)';
let tokenEndpoint = '/rest/v0/users/me/authentication_tokens';
union isfuzzy=true
  ( CommonSecurityLog
    | where TimeGenerated > ago(lookback)
    | extend Raw = strcat(tostring(column_ifexists("RequestCookies", "")), " ", RequestContext, " ", AdditionalExtensions, " ", Message)
    | project TimeGenerated, Computer, SrcIp = SourceIP, Url = RequestURL, Raw ),
  ( Syslog
    | where TimeGenerated > ago(lookback)
    | where ProcessName in~ ("nginx", "haproxy", "httpd", "apache2", "traefik", "caddy")
    | project TimeGenerated, Computer, SrcIp = extract(@'(\d{1,3}(?:\.\d{1,3}){3})', 1, SyslogMessage), Url = extract(@'"(?:GET|POST|PUT|PATCH|DELETE) (\S+)', 1, SyslogMessage), Raw = SyslogMessage )
| extend CookieHit = Raw matches regex bypassCookie, TokenListing = (Url contains tokenEndpoint or Raw contains tokenEndpoint)
| summarize CookieRequests = countif(CookieHit), TokenListingRequests = countif(TokenListing), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), Targets = make_set(Computer, 10), SampleUrls = make_set(Url, 10) by SrcIp
| where CookieRequests > 0
| extend Stage = iff(TokenListingRequests > 0, "auth_bypass_plus_token_harvest", "auth_bypass_attempt")
| project SrcIp, Stage, CookieRequests, TokenListingRequests, Targets, SampleUrls, FirstSeen, LastSeen
```

### Sigma

```yaml
title: Xen Orchestra Empty-Object authenticationToken Cookie Authentication Bypass (VSA-2026-062)
id: 3f6b1a52-7c1e-4d0a-9b8e-5a2c4e7d1f01
status: experimental
description: Detects HTTP requests to Xen Orchestra or XOA carrying the crafted authenticationToken cookie (empty object, plain or URL-encoded) that bypasses REST authentication. XO does not log this, so telemetry must come from a reverse proxy, WAF or web server in front of XO.
references:
    - https://docs.vates.tech/security-advisories/advisories/2026/vates-sa-2026-062/
    - https://github.com/vatesfr/xen-orchestra/pull/10748
author: Threadlinqs Team
date: 2026/11/10
tags:
    - attack.initial-access
    - attack.t1190
    - attack.t1078
    - attack.defense-evasion
    - attack.t1550.001
    - attack.credential-access
    - attack.t1528
logsource:
    category: webserver
detection:
    selection_cookie:
        cs-cookie|contains:
            - 'authenticationToken=j:{}'
            - 'authenticationToken=j:%7B%7D'
            - 'authenticationToken=j%3A%7B%7D'
            - 'authenticationToken=j%3A{}'
    condition: selection_cookie
fields:
    - c-ip
    - cs-uri-stem
    - cs-cookie
    - cs-host
    - sc-status
falsepositives:
    - Authorised vulnerability scanners validating VSA-2026-062 exposure
    - Internal red-team or patch-validation testing against Xen Orchestra
level: critical

```

**Known false positives:**

- Authorised vulnerability scanners or red-team tooling replaying the VSA-2026-062 empty-object cookie against Xen Orchestra
- Patch-validation testing in a lab where the cookie is deliberately sent to confirm the fix

**Tuning notes:** Requires HTTP-layer telemetry in front of Xen Orchestra (Splunk Stream, reverse-proxy or WAF logs that record the Cookie header) because XO itself does not log the bypass. Adjust index/sourcetype to your proxy; allowlist known scanner source IPs; treat any hit from an untrusted source as critical and revoke XO authentication tokens. The regex covers URL-encoded variants, but the vendor notes other encodings may evade simple rules, so pair with patching to xo-server 5.211.2/5.213.1.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- Xen Orchestra Empty-Object Cookie Bypass and Token Harvest (Sentinel) — Exploitation (locked: unlock with TL Creds)
- XCP-ng Persistence and Rogue VM Artifacts (Sentinel) — Post-Exploitation (locked: unlock with TL Creds)
- Xen Orchestra Campaign C2: Actor IP and Onion Service Contact (Sentinel) (locked: unlock with TL Creds)
- Xen Orchestra Empty-Object authenticationToken Cookie (Sigma) — Exploitation (locked: unlock with TL Creds)
- XCP-ng Campaign Persistence Files (Sigma) — Post-Exploitation (locked: unlock with TL Creds)
- Xen Orchestra Campaign C2 Connections (Sigma) — C2 / Multi-hop Proxy (locked: unlock with TL Creds)
- XCP-ng Post-Exploitation Artifacts: zz-ustar Cron, .ustar Files, ld.so.preload, [indicator] / hvm_serial VM (locked: unlock with TL Creds)
- Connections To Xen Orchestra Campaign C2 Infrastructure ([indicator]) (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sample indicators (3 of 25)

Defanged, TLP:CLEAR.

- IP address: `91.211.251[.]112`
- Domain: `ustar3rqxgnskzgnwkgpofgtvxevm6cx3lxdbwt4mndtveqyaohid[.]onion`
- IP address: `193.148.56[.]72`

Full set of 25 indicators unlocks with TL Creds: https://threadlinqs.com/tl-creds

## Sources

- [Critical Xen Orchestra auth bypass flaw exploited to hijack VM servers](https://www.bleepingcomputer.com/news/security/critical-xen-orchestra-auth-bypass-flaw-exploited-to-hijack-vm-servers/)
- [VSA-2026-062: Empty-object login token](https://docs.vates.tech/security-advisories/advisories/2026/vates-sa-2026-062/)
- [fix(xo-server): validate authentication token IDs (PR #10748)](https://github.com/vatesfr/xen-orchestra/pull/10748)
- [Xen Orchestra source repository](https://github.com/vatesfr/xen-orchestra)
- [Vates 2026 security advisories index](https://docs.vates.tech/category/2026)
- [XCP-ng security and maintenance updates (Vates/XCP-ng project blog, product context)](https://xcp-ng.org/blog/)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-5663
