CVE-2021-26084 PoC write-up

Your vote is:
5.00 of 84 votes

CVSS Rating

This is my PoC write-up for CVE-2021-26084, which amounts to RCE and affects certain versions of Confluence Server and Data Center instances. I've come across this vulnerability a few times during the course of my research, so decided to add a brief PoC write-up for ease of future reference.


CVE-2021-26084 is an OGNL injection vulnerability allowing an unauthenticated attacker to execute arbitrary code on the targeted instance. It may be worth noting that statements from the vendor indicate this vulnerability is being actively exploited in the wild and that affected servers should be patched imediately.

Steps to Reproduce

I have included a downloadable PoC (proof-of-concept) Python script below, which enables owners of vulnerable instances to safely (and remotely) reproduce the necessary steps to validate this vulnerability themselves.

Python PoC Script FileDownload Python Script

Example Usage:
python3 -u https://[TARGET HOST HERE] -p /pages/[PAGE VARIABLE HERE].action?SpaceKey=x

Python PoC Example Open Shell

Python PoC Example ID Command

Python PoC Example Hostname Command

Python PoC Example List Filesystem Command

The Vulnerability

Atlassian Confluence is a widely used platform written in Java for managing project documentation and planning, typically deployed in corporate environments for teams to collaborate in shared workspaces. Back in 2017, security researcher Benny Jacob discovered that unauthenticated users could execute arbitrary code by targeting HTML queries with ONGL injection techniques.

HTTP is a request/response protocol described in RFCs 7230 - 7237 and other RFCs. A request is sent by a client to a server, which in turn sends a response back to the client. A HTTP request consists of a request line, various headers, an empty line, and an optional message body:

HTTP Request Example Example #1

Where CRLF represents the new line sequence Carriage Return (CR) followed by Line Feed (LF), SP represents a space character. Parameters can be passed from the client to the server as name-value pairs in either the Request-URI or in the message-body, depending on the Method used and the Content-Type header. For example, a simple HTTP request passing a parameter named "param" with value "1", using the GET method might look like:

HTTP Request Example Example #2

A corresponding HTTP request using the POST method might look as follows:

HTTP Request Example Example #3

Confluence uses the Webwork web application framework to map URLs to Java classes, creating what is known as an action. Action URLs end with the '.action' suffix and are defined in the xwork.xml file in confluence- .jar and in the atlassian-plugin.xml file in JAR files of included plugins.

Each action entry contains at least a name attribute, defining the action name, a class attribute, defining the Java class implementing the action, and at least one result element which decides the Velocity template to render after the action is invoked based on the result of the action. Common return values from actions are "error", "input";, and "success", but any value may be used if there is a matching result element in the associated XWork XML. Action entries can contain a method attribute, which allows invocation of a specific method of the specified Java class. When no command is specified, the doDefault() method of the action class is called. The following is a sample action entry for the doenterpagevariables action:

XML Entry Example

In the above example, the doEnter() method of the com.atlassian.confluence.pages.actions.PageVariablesAction class handles requests to doenterpagevariables.action and will return values such as "success", "input";, or "error". This results in the appropriate Velocity template being rendered.

Confluence supports the use of Object Graph Navigational Language (OGNL) expressions to dynamically generate web page content from Velocity templates using the Webwork library. OGNL is a dynamic Expression Language (EL) with terse syntax for getting and setting properties of Java objects, list projections, lambda expressions, etc. OGNL expressions contain strings combined to form a navigation chain. The strings can be property names, method calls, array indices, and so on. OGNL expressions are evaluated against the initial, or root context object supplied to the evaluator in the form of OGNL Context.

Confluence uses a container object of class com.opensymphony.webwork.views.jsp.ui.template.TemplateRenderingContext to store objects needed to execute an Action. These objects include session identifiers, request parameters, spaceKey, etc. TemplateRenderingContext also contains a com.opensymphony.xwork.util.OgnlValueStack object to push and store objects against which dynamic Expression Languages (EL) are evaluated. When the EL compiler needs to resolve an expression, it searches down the stack starting with the latest object pushed into it. OGNL is the EL used by the Webwork library to render Velocity templates defined in Confluence, allowing access to Confluence objects exposed via the current context. For example, the $action variable returns the current Webwork action object.

OGNL expressions in Velocity templates are parsed using the ognl.OgnlParser.expression() method. The expression is parsed into a series of tokens based on the input string. The ognl.JavaCharStream.readChar() method, called by the OGNL parser, evaluates Unicode escape characters in the form of uXXXX where "XXXX" is the hexadecimal code of the Unicode character represented. Therefore, if an expression includes the character u0027, the character is evaluated as a closing quote character ('), escaping the context of evaluation as a string literal, allowing to append an arbitrary OGNL expression. If an OGNL expression is parsed in a Velocity template within single quotes and the expression's value is obtained from user input without any sanitization, an arbitrary OGNL expression can be injected.

An OGNL injection vulnerability exists in Atlassian Confluence. The vulnerability is due to insufficient validation of user input used to set variables evaluated in Velocity templates within single quotes. By including the u0027 character in user input, an attacker can escape the string literal and append an arbitrary OGNL expression.

Before OGNL expressions are evaluated by Webwork, they are compared against a list of unsafe node types, property names, method names, and variables names in the com.opensymphony.webwork.util.SafeExpressionUtil.containsUnsafeExpression() method. However, this list is not exhaustive, and arbitrary Java objects can be instantiated without using any of the unsafe elements listed. For example, the following expression, executing an OS command, would be accepted as a safe expression by this method:

OGNL Expression Example

A remote attacker can exploit this vulnerability by sending a crafted HTTP request containing a malicious parameter to a vulnerable server. Successful exploitation can result in the execution of arbitrary code with the privileges of the server.

Remote Detection of Generic Attacks

To detect this attack, you should monitor all HTTP traffic requests where the path component of the request-URI contains one of the strings in the "URI path" column of the following table:

URI Path Vulnerable Parameters
--------------------------------------------------------------------- ---------------------------------------------------------------------
/users/darkfeatures.action featureKey
/users/enabledarkfeature.action featureKey
/users/disabledarkfeature.action featureKey
/login.action token
/dologin.action token
/signup.action token
/dosignup.action token
/pages/createpage-entervariables.action queryString, linkCreation
/pages/doenterpagevariables.action queryString
/pages/createpage.action queryString
/pages/createpage-choosetemplate.action queryString
/pages/docreatepagefromtemplate.action queryString
/pages/docreatepage.action queryString
/pages/createblogpost.action queryString
/pages/docreateblogpost.action queryString
/pages/copypage.action queryString
/pages/docopypage.action queryString
/plugins/editor-loader/editor.action syncRev

If such a request is found, you should inspect the HTTP request method. If the request method is POST, look for the respective vulnerable parameters from the table above in the body of the HTTP request, and if the request method is GET, you should look for the parameters in the request-URI of the HTTP request. Check to see if the value of any of the vulnerable parameters contains the string u0027 or its URL-encoded form. If so, the traffic should be considered malicious and an attack exploiting this vulnerability is likely underway.


If you are running an affected version upgrade to version 7.13.0 (LTS) or higher.
If you are running 6.13.x versions and cannot upgrade to 7.13.0 (LTS) then upgrade to version 6.13.23.
If you are running 7.4.x versions and cannot upgrade to 7.13.0 (LTS) then upgrade to version 7.4.11.
If you are running 7.11.x versions and cannot upgrade to 7.13.0 (LTS) then upgrade to version 7.11.6.
If you are running 7.12.x versions and cannot upgrade to 7.13.0 (LTS) then upgrade to version 7.12.5.

If you are unable to upgrade Confluence immediately, then as a temporary workaround, you can mitigate the issue by following the steps outlined in the official advisory:

Confluence Server or Data Center Node running on Linux:

If you run Confluence in a cluster, you will need to repeat this process on each node. You don't need to shut down the whole cluster.

  1. Shut down Confluence.
  2. Download the to the Confluence Linux Server.
  3. Edit the file and set INSTALLATION_DIRECTORY to your Confluence installation directory, for example:
  4. Save the file.
  5. Give the script execute permission.
    chmod 700
  6. Change to the Linux user that owns the files in the Confluence installation directory, for example: $ ls -l /opt/atlassian/confluence | grep bin
    drwxr-xr-x 3 root root 4096 Aug 18 17:07 bin

    # In this first example, we change to the 'root' user
    # to run the workaround script

    $ sudo su root

    $ ls -l /opt/atlassian/confluence | grep bin
    drwxr-xr-x 3 confluence confluence 4096 Aug 18 17:07 bin

    # In this second example, we need to change to the 'confluence' user
    # to run the workaround script

    $ sudo su confluence
  7. Run the workaround script.
  8. The expected output should confirm up to five files updated and end with
    Update completed!
    The number of files updated will differ, depending on your Confluence version.
  9. Restart Confluence.

Confluence Server or Data Center Node running on Windows:

If you run Confluence in a cluster, you will need to repeat this process on each node. You don't need to shut down the whole cluster.

  1. Shut down Confluence.
  2. Download the cve-2021-26084-update.ps1 to the Confluence Windows Server.
  3. Edit the cve-2021-26084-update.ps1 file and set the INSTALLATION_DIRECTORY. Replace Set_Your_Confluence_Install_Dir_Here with your Confluence installation directory, for example:
    $INSTALLATION_DIRECTORY='C:Program FilesAtlassianConfluence'
  4. Save the file.
  5. Open up a Windows PowerShell (use Run As Administrator).
  6. Due to PowerShell's default restrictive execution policy, run the PowerShell using this exact command:
    Get-Content .cve-2021-26084-update.ps1 | powershell.exe -noprofile -
  7. The expected output should show the status of up to five files updated, encounter no errors (errors will usually show in red) and end with:
    Update completed!
    The number of files updated will differ, depending on your Confluence version.
  8. Restart Confluence.

Remember, if you run Confluence in a cluster, make sure you run this script on all of your nodes.


Jacob Riggs

Jacob Riggs is a senior cyber security professional based in the UK with over a decade of experience working to improve the cyber security of various private, public, and third sector organisations. His contributions focus on expanding encryption tools, promoting crypto-anarchist philosophy, and pioneering projects centred on leveraging cryptography to protect the privacy and political freedoms of others.

E3FE 4B44 56F5 69BE 76C1 E169 E3C7 0A52 9AEF DB6F

Subscribe to my Blog

I agree with the Privacy Policy terms.