Atlassian Confluence Broken Access Control Vulnerability (CVE-2023-22515)

Mayank Deshmukh

Atlassian issued an Advisory on October 4, 2023, for CVE-2023-22515, a critical severity vulnerability affecting Confluence Server and Data Center. According to the advisory, the vulnerability was initially published as a Privilege Escalation vulnerability but was later updated to a Broken Access Control Vulnerability, Atlassian has also rated the vulnerability with 10 CVSS score. On October 5, 2023, the vulnerability was included in “CISA’s Known Exploited Vulnerabilities Catalog”.

Qualys Web Application Scanning released two QIDs, 150725 & 150745, to address CVE-2023-22515.

QID 150725 was released with detection logic that detects the vulnerable version of the Confluence application based on the response to requests sent to the server. 

QID 150745 is an intrusive detection that exploits vulnerable servers by sending requests to the vulnerable endpoint. Vulnerable and unpatched servers are flagged when application configuration alteration is confirmed. Subsequently, it verifies the accessibility of Administrator endpoints and finally leverages the same vulnerability to restore the application configuration. 

About CVE-2023-22515

CVE-2023-22515 is an unauthenticated critical severity vulnerability allowing remote attackers to create unauthorized Confluence Administrator accounts and access Confluence instances. Although the vulnerability is categorized as a Broken Access Control, the initial exploitation stage requires Injection which modifies the application’s configuration, granting unrestricted access to Administrator setup endpoints. The vulnerability affects Confluence versions 8.0.0, 8.0.1, 8.0.2, 8.0.3, 8.0.4, 8.1.0, 8.1.1, 8.1.3, 8.1.4, 8.2.0, 8.2.1, 8.2.2, 8.2.3, 8.3.0, 8.3.1, 8.3.2, 8.4.0, 8.4.1, 8.4.2, 8.5.0, 8.5.1 and is fixed in versions 8.3.3, 8.4.3 and 8.5.2 or later.

Exploitation Overview

The Exploitation chain consists of three stages:

  • First, we modify the setup completion status of the Confluence application, thereby gaining unrestricted access to the setup administrator page.
  • Following that, we evade the Confluence application’s XSRF security token policy check, which allows us to register an attacker-controlled Administrator account.
  • Lastly, we exit the setup wizard to prevent the “setup successful” message from being displayed to all users.

Vulnerability Analysis

Stage 1: Flipping Setup Completion Status

The initial request is sent to server-info action with bootstrapStatusProvider.applicationConfig.setupComplete=false as the payload parameter. When we access server-info.action endpoint without authentication returns a simple response with a “success” status message.

GET /server-info.action?bootstrapStatusProvider.applicationConfig.setupComplete=false

The ‘success’ response confirms that the server is operational and doesn’t expose sensitive or detailed information directly through this endpoint.

Analyzing ServerInfoAction code within the com.atlassian.confluence.core.actions package:

package com.atlassian.confluence.core.actions; import; import com.atlassian.confluence.core.ConfluenceActionSupport; import; import com.atlassian.xwork.HttpMethod; import com.atlassian.xwork.PermittedMethods; public class ServerInfoAction extends ConfluenceActionSupport {   @PermittedMethods({HttpMethod.ANY_METHOD})   @XsrfProtectionExcluded   @PublicAccess   public String execute() throws Exception {     return "success";   } }

The class ServerInfoAction extends the ConfluenceActionSupport class, which likely handles specific functionalities. Within this class, there’s a method named execute(). It’s designed to be invoked using any HTTP method, exempt from XSRF protection, and accessible to the public without requiring authentication. When the execute method is called, it returns the string “success” once the action was executed successfully.

Moving forward, we’ll examine the extended class ConfluenceActionSupport located at com.atlassian.confluence.core:

package com.atlassian.confluence.core; [..SNIP..] public class ConfluenceActionSupport extends ActionSupport implements LocaleProvider, WebInterface, MessageHolderAware { [..SNIP..]   public BootstrapStatusProvider getBootstrapStatusProvider() {     if (this.bootstrapStatusProvider == null)       this.bootstrapStatusProvider = BootstrapStatusProviderImpl.getInstance();     return this.bootstrapStatusProvider;   } [..SNIP..]

Inside the Java class ConfluenceActionSupport, we see a public method named getBootstrapStatusProvider returning an object bootstrapStatusProvider. If the bootstrapStatusProvider is null, it initializes by calling BootstrapStatusProviderImpl.getInstance(), where the getInstance() method appears to get an instance of the bootstrap status provider. Once the object bootstrapStatusProvider is created or already exists, the method returns it.

Following that, BootstrapStatusProviderImpl class at com.atlassian.confluence.impl.setup, comprises a public method named getApplicationConfig which returns the ApplicationConfiguration object.

package com.atlassian.confluence.impl.setup; [..SNIP..] public class BootstrapStatusProviderImpl implements BootstrapStatusProvider, BootstrapManagerInternal {   private static final Supplier instance = (Supplier)Suppliers.memoize(BootstrapStatusProviderImpl::initialiseBootstrapStatusProvider); [..SNIP..]   public ApplicationConfiguration getApplicationConfig() {     return this.delegate.getApplicationConfig();   } [..SNIP..] }

Inside the getApplicationConfig method, the method call to this.delegate.getApplicationConfig(); is using delegation where getApplicationConfig() is delegating the task of fetching application configuration on another object referred to as delegate.  

ApplicationConfiguration is an interface specifying multiple methods that any class can implement. Whichever class implements this interface will define the behavior of the methods. 

public interface ApplicationConfiguration { String getApplicationHome(); void setApplicationHome(String paramString) throws ConfigurationException; boolean isApplicationHomeValid(); void setProperty(Object paramObject1, Object paramObject2); [..SNIP..]   void setBuildNumber(String paramString);   boolean isSetupComplete();   void setSetupComplete(boolean paramBoolean);  //   void setConfigurationPersister(ConfigurationPersister paramConfigurationPersister); [..SNIP..]   void setConfigurationFileName(String paramString); }

Interestingly, it does have a method named setSetupComplete expecting one parameter of type Boolean.

ApplicationConfig class implements the ApplicationConfiguration interface, and we do find a synchronized method called setSetupComplete:

package com.atlassian.config; [..SNIP..] public class ApplicationConfig implements ApplicationConfiguration { [..SNIP..]  public synchronized void setSetupComplete(boolean setupComplete) { this.setupComplete = setupComplete; } [..SNIP..]  }

setSetupComplete method accepts a boolean parameter named setupComplete used to set the setup completion status.
The setupComplete variable of the class is assigned a value supplied as the parameter. The purpose of this parameter is to define or update the setup completion status of the Confluence application. The setup process is complete when we pass true as the setupComplete parameter. When we pass false, it indicates that the setup process is incomplete.

Unifying components from classes such as ConfluenceActionSupport, BootstrapStatusProviderImpl, and ApplicationConfig, we can chain method calls, including getBootstrapStatusProvider(), getApplicationConfig(), and setSetupComplete(), which we’ve explored thus far.

  • getBootstrapStatusProvider(): This method is called to obtain an instance of the BootstrapStatusProvider.
  • getApplicationConfig(): This is called on the result of getBootstrapStatusProvider(). It retrieves the ApplicationConfig object. This object manages application configuration settings, including the setupComplete status.
  • setSetupComplete(): Finally, setSetupComplete() is called on the ApplicationConfig object. This method sets the setupComplete status to either true or false, indicating the setup process for the application.

By chaining method calls, we efficiently set the setupComplete value to false using getBootstrapStatusProvider().getApplicationConfig().setSetupComplete(false);

Confluence uses the XWork2 framework, which manages actions, interceptors, and parameter binding, among other things. In XWork2, HTTP parameters are used to set properties in action classes, and the framework automatically maps these parameters to setter methods based on naming conventions.

Due to this, we can form an HTTP parameter that enables a series of method invocations.


Using the payload against the server-info.action endpoint would adjust the setupComplete value to false, signifying that the setup process remains incomplete. 

Stage 2:  Accessing setupadministrator endpoint

After the setupComplete attribute has been updated, the expected behavior would allow us to access the setup/setup administrator.action endpoint and create an Administrator account.

However, when we send a POST request to this endpoint, we receive a 403 Forbidden response status code and a response body containing the following message: ‘Your request could not be processed because a required security token was not present in the request. You may need to re-submit the form or reload the page.’

According to Atlassian’s Enable XSRF protection in your app guide for Confluence:

Scripts that access Confluence remotely may have trouble acquiring or returning a security token or maintaining an HTTP session with the server. To opt out of token checking, include the following HTTP header in the request: X-Atlassian-Token: no-check

Concerning the above guide, including X-Atlassian-Token: no-check in the HTTP Request Headers, we trigger the same request:

That worked! We have now gained unrestricted access to the endpoint, receiving a 200 status for the Configure System Administrator Account – Confluence page. All that’s left is to include the POST request body with the necessary parameters for the Administrator account.

A 302 redirect at the /setup/finishsetup.action endpoint is a sign of a successful request.

Stage 3: Finishing Setup

In the final step, we proceed with another POST request to the /setup/finishsetup.action endpoint, effectively exiting the setup wizard.

Logging in as Administrator coldfx

Detecting the Vulnerability with Qualys WAS

When this vulnerability was disclosed, Atlassian Security Advisory mentioned this as a Privilege Escalation Vulnerability. Following that, Qualys WAS had released the following QID:

150725: Atlassian Confluence Server and Data Center Privilege Escalation Vulnerability (CVE-2023-22515)

However, Later Atlassian Security Advisory updated the vulnerability to a Broken Access Control Vulnerability. Thereafter, Qualys WAS has also updated the QID title. 

Customers can detect this vulnerability on the target Confluence application using QIDs: 

150725: Atlassian Confluence Server and Data Center Broken Access Control Vulnerability
150745: Atlassian Confluence Server and Data Center Broken Access Control Vulnerability
(CVE-2023-22515) (Exploitation Check)

Qualys WAS Report

Once the vulnerability is successfully detected, users shall see similar results in the vulnerability scan report for both the QIDs:

QID 150725 – Vulnerability Scan Report
QID 150745 – Vulnerability Scan Report

Solution & Mitigation

Due to the Vulnerability marked as Critical Severity and highlighted as CISA’s Known Exploited Vulnerabilities, organizations using the confluence application are strongly advised to upgrade to version 8.3.3, 8.4.3, 8.5.2, or later releases to remediate CVE-2023-22515 vulnerability. 
For more patching and threat detection-related details, please refer to Atlassian Security Advisory.


Atlassian Security Advisory:

CVE Details:


Share your Comments


Your email address will not be published. Required fields are marked *