In late January 2026, an advisory covering two remote code execution vulnerabilities (CVE-2026-1281 & CVE-2026-1340) in Ivanti Endpoint Manager Mobile (EPMM) was published. Shortly after, reports (in example by tenable) mentioned publicly available proof-of-concept exploits.
On February 9th 2026, Defused published a blog post describing a specific webshell being deployed on EPMM devices via this vulnerability. In essence, they reported that exploits result in deployment of a dormant in-memory Java class loader at the location /mifs/403.jsp, starting with February 4th 2026. While this webshell has the capability to receive a Java class with the parameter k0f53cf964d387, they have not observed any dynamic command being executed via this webshell. Based on this, they also referenced these as Sleeper Shells and the 403.jsp campaign. We will also use these terms in this post to reference the same activities.
In a recent incident that NVISO CSIRT handled, we came across a compromised Ivanti EPMM device, and the logs quickly revealed that the aforementioned vulnerabilities were used to compromise the device. From the log entries, we quickly identified what we believe is the same webshell Defused was reporting on.
Noteable indications:
/mifs/403.jspwritten to the file system- Requests for the
/mifs/403.jspfile, including a base64 encoded parameterk. - Requests including the parameter
k0f53cf964d387, just followed by two characters, leading to no dynamic code execution.
One important difference is that these requests were detected on February 3rd 2026, one day before the attack described by Defused.
When we were pivoting from the combination of /mifs/403.jsp and the presence of the k parameter (/mifs/403.jsp?k=…), we found requests not containing the k0f53cf964d387 parameter, leading us to the conclusion that this campaign was perhaps a bit more active than we have read in the Defused blog post.
A few dates and numbers first:
- We have seen approximately 140 requests for
/mifs/403.jsp?k=…&k0f53cf964d387=..between February 3rd 2026 and February 11th 2026. - We have seen close to 30 requests for
/mifs/403.jsp?k=…NOT including thek0f53cf964d387parameter on two days within the timeframe of February 3rd 2026 to February 11th 2026. - For these k-only requests, the
kparameter was carrying four different base64 encoded payloads. These four payloads typically formed a block of four consecutive requests, showing up seven times in the logs. Only one occurrence had a/mifs/403.jsp?k=…&k0f53cf964d387=..request in between.
Looking at the k-only related payloads. All four of them are sent URL- and base64-encoded. If we write them to a file and remove the two encodings, we end up with a standard Java class file. To gain the plain Java code, we need to take a Java decompiler – we used cfr , ran our class file through it and we can investigate the Java code.
Decompiling all four payloads/Java classes showed that they serve the same purpose and have the same structure. In short: When invoked, the class retrieves the servlet request/response from whatever object it’s given, runs a hardcoded command as a separate process via the exec(String[] cmdarray) method of java.lang.Runtime. The hardcoded command is stored in the String Array called var9 and returns any output in the HTTP response. The content of the String Array var9 is also the only difference in the decompiled code.
Observed commands stored in public String[] var9:
new String[]{"/bin/sh", "-c", "/usr/bin/env /bin/sh -p -c 'mysqldump --databases mifs --tables mi_user mifs_ldap_users mifs_ldap_server_config > /mi/tomcat/webapps/mifs/css/mibasecss.css'"};
new String[]{"/bin/sh", "-c", "/usr/bin/env /bin/sh -p -c 'tar -czvf /mi/tomcat/webapps/mifs/css/mibasecss3.css /mi/tomcat-properties'"};
new String[]{"/bin/sh", "-c", "/usr/bin/env /bin/sh -p -c 'tar -czvf /mi/tomcat/webapps/mifs/css/mibasecss2.css /mi/files/system'"};
new String[]{"/bin/sh", "-c", "/usr/bin/env /bin/sh -p -c 'rm -f /mi/tomcat/webapps/mifs/css/mibasecss*'"}; JavaThe first command tries to create a database dump of the database mifs and write it to /mi/tomcat/webapps/mifs/css/mibasecss.css. It utilizes the tool mysqldump and limits the output to include the tables mi_user, mifs_ldap_users, and mifs_ldap_server_config.
The second and third commands use the tool tar to create archives of two locations on the file system: /mi/tomcat-properties and /mi/files/system. The archives are stored as /mi/tomcat/webapps/mifs/css/mibasecss3.css and /mi/tomcat/webapps/mifs/css/mibasecss2.css.
The last command serves as a cleanup command, deleting every file matching the given glob: /mi/tomcat/webapps/mifs/css/mibasecss*.
The observed sequence of commands was always from 1 to 4, as shown in the above listing. The first command observed in all seven blocks is the command to achieve a database dump, followed by the two archive-creating commands and closed by the cleanup command deleting the expected result files. If these commands are executed successfully, they will expose potentially sensitive information from the database and local files, likely supporting further reconnaissance.
Summary
We have also not seen any code being sent and dynamically executed via the approximately 140 observed /mifs/403.jsp?k=…&k0f53cf964d387=.. requests, confirming what Defused has written on these specific requests. However, in between these requests we have seen commands executed via the k-only requests. We cannot tell for sure that these two types of requests were sent from the same actor, but it seems rather unlikely that two unrelated groups were using the same file (/mifs/403.jsp) and the same parameter (k) at the same time on the same system to submit their commands.
So, based on the time correlation and the similarity in filename and parameter, we concluded that the 403.jsp campaign might not have been as sleepyas initially reported. They likely just created a different webshell, including a static command, to gain additional data from the affected system.
We share this information in addition to what Defused has already published, as we are convinced this additional information is relevant for defenders.
For organizations operating EPMM instances, we highly recommend checking for signs of compromise, even if the patch has already been applied. If signs of compromise are found, measures like credential reset, checks for lateral movement, and EPMM instance rebuild should be carefully considered.

One thought on “Ivanti EPMM ‘Sleeper Shells’ not so sleepy?”
Comments are closed.