Advisory | CVE-2017-6398 Trend Micro InterScan Messaging Security (Virtual Appliance) Remote Code Execution

In this article, we  will show details and metasploit module for vulnerability that affects Trend Micro’s IMSVA solution.

About Product

Trend Micro™ InterScan™ Messaging Security stops email threats in the cloud with global threat intelligence, protects your data with data loss prevention and encryption, and identifies targeted email attacks,ransomware, and APTs as part of the Trend Micro Network Defense Solution.

Identified Vulnerabilities

We managed to identify two different vulnerability during assessment.

Issue #1 – Remote Code Execution via Command Injection

Severity: Critical

Affected Version: All version until IMSVA 9.1 Patch (build 1631)

Remotely Exploitable: Yes

Technical Details:

Calling /saveCert path of IMSVA will be handled by saveCert method of MTASettingAction class. Here is the first part of saveCert method definition.

public ActionForward saveCert(ActionMapping mapping, ActionForm Form, HttpServletRequest request, HttpServletResponse response)
    throws Exception
  {
    // ... OMITTED CODE ...
    if (mode.equalsIgnoreCase("1"))
    {
      // ... OMITTED CODE ...
    }
    else
    {
      // ... OMITTED CODE ...
      String cert_name = ((String)((DynaActionForm)Form).get("certName")).trim();
      Integer cert_type = (Integer)((DynaActionForm)Form).get("certType");
      Integer key_length = (Integer)((DynaActionForm)Form).get("keyLength");
      Integer valid_days = (Integer)((DynaActionForm)Form).get("validDays");
      String country_code = ((String)((DynaActionForm)Form).get("countryCode")).trim();
      String state = ((String)((DynaActionForm)Form).get("state")).trim();
      String locality = ((String)((DynaActionForm)Form).get("locality")).trim();
      String org = ((String)((DynaActionForm)Form).get("org")).trim();
      String org_unit = ((String)((DynaActionForm)Form).get("orgUnit")).trim();
      String common_name = ((String)((DynaActionForm)Form).get("commonName")).trim();
      String email_address = ((String)((DynaActionForm)Form).get("emailAddress")).trim();
      
      country_code = country_code.replace("\"", "");
      country_code = country_code.replace("/", "");
      state = state.replace("\"", "");
      state = state.replace("/", "");
      locality = locality.replace("\"", "");
      locality = locality.replace("/", "");
      org = org.replace("\"", "");
      org = org.replace("/", "");
      org_unit = org_unit.replace("\"", "");
      org_unit = org_unit.replace("/", "");
      common_name = common_name.replace("\"", "");
      common_name = common_name.replace("/", "");
      
      email_address = email_address.replace("\"", "");
      email_address = email_address.replace("/", "");
      
      // ... OMITTED CODE ...
      
      if (cert_type.intValue() == 0)
      {
        // ... OMITTED CODE ...
        String cmdline = "#!/bin/bash\n";
        cmdline = cmdline + GlobalAccess.getImssHome() + "/script/openssl req -sha256 -newkey rsa:" + key_length + " -keyout " + GlobalAccess.getImssHome() + "/UI/tomcat/csr_key.pem -keyform PEM -out " + GlobalAccess.getImssHome() + "/UI/tomcat/csr.pem -outform PEM -nodes";
        cmdline = cmdline + " -subj '/C=" + country_code + "/ST=" + state + "/L=" + locality + "/O=" + org + "/OU=" + org_unit + "/CN=" + common_name + "/emailAddress=" + email_address + "'";
        cmdline = cmdline + " -config " + GlobalAccess.getImssHome() + "/config/openssl.cnf";
        Utility.writeStringToFile(cmdline, GlobalAccess.getImssHome() + "/temp/gen_csr.temp");
        debugLog.debug("prepare generate csr cmdline: " + cmdline);
        try
        {
          cmdline = "/bin/bash " + GlobalAccess.getImssHome() + "/temp/gen_csr.temp";
          Process process = Runtime.getRuntime().exec(cmdline);
          stderr = process.getErrorStream();
          stdout = process.getInputStream();
          BufferedReader readerOut = new BufferedReader(new InputStreamReader(stdout));
          BufferedReader readerErr = new BufferedReader(new InputStreamReader(stderr));
          debugLog.debug("run wrapped cmdline: " + cmdline);
          ret = process.waitFor();
          // ... OMITTED CODE ...
      }
      if (cert_type.intValue() == 1)
      {
        // ... OMITTED CODE ...
        String cmdline = "" + GlobalAccess.getImssHome() + "/script/openssl req -x509 -sha256 -days " + valid_days + " -newkey rsa:" + key_length + " -keyout " + GlobalAccess.getImssHome() + "/UI/tomcat/ssc_key.pem -keyform PEM -out " + GlobalAccess.getImssHome() + "/UI/tomcat/ssc.pem -outform PEM -nodes";
        cmdline = cmdline + " -subj \"/C=" + country_code + "/ST=" + state + "/L=" + locality + "/O=" + org + "/OU=" + org_unit + "/CN=" + common_name + "/emailAddress=" + email_address + "\"";
        cmdline = cmdline + " -config " + GlobalAccess.getImssHome() + "/config/openssl.cnf" + " -extensions v3_ssc";
        Utility.writeStringToFile(cmdline, GlobalAccess.getImssHome() + "/temp/gen_ssc.temp");
        debugLog.debug("prepare generate ssc cmdline: " + cmdline);
        try
        {
          cmdline = "/bin/bash " + GlobalAccess.getImssHome() + "/temp/gen_ssc.temp";
          Process process = Runtime.getRuntime().exec(cmdline);
          stderr = process.getErrorStream();
          stdout = process.getInputStream();
          // ... OMITTED CODE ...
      }
    }
    return mapping.findForward("success");
  }

Here is the where things going bad. User supplied variables such as common_name, state etc is being used on command generation without proper validation.

Let assume we have filled all variables with test1. That means we will have following command located at /temp/gen_ssc.temp file.

trend micro exploit

As you can see, -subj parameter of openssl command takes data within single quote. But double quote and slashes are blacklisted by application, not a single quote..! Which means we can easily bypass that blacklist and inject your operating system command into the file.

Metasploit Module:

Since the exploitation of this vulnerability is trivial. It was very easy to implement a Metasploit module. I’ve used one trick during implementation which you can find details at comment lines on module.

Issue #2 – XML External Entity (XXE)

Severity: High

Affected Version: All version untill 9.1-1600 build.

Remotely Exploitable: Yes

Technical Details:

Calling /ldap_users path of IMSVA will trigger search method of LdapUserWSAction class.

Here is the first part of saveCert method definition.

public ActionForward search(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
    throws Exception
  {
    BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(), CS));
    String line = null;
    StringBuilder sb = new StringBuilder();
    while ((line = br.readLine()) != null) {
      sb.append(line);
    }
    response.setCharacterEncoding("utf-8");
    response.setHeader("content-type", "text/xml;charset=utf-8");
    
    String searchStr = null;
    try
    {
      Document doc = DocumentHelper.parseText(sb.toString());
      Element root = doc.getRootElement();
      if ((root != null) && (root.getQName().getName().equals("ldapsearchstring"))) {
        searchStr = root.getText();
      }
    }
    catch (Exception e)
    {
      // ... OMITTED CODE ...
    }
    // ... OMITTED CODE ...
  }

Whole HTTP body is taken as a br parameter and then it used parseTextmethod od DocumentHelper class without disabling DTD.

POC:

Following HTTP request will trigger a vulnerable point.

trend-micro-xxe

And HTTP request from IMSVA observed at another machine.

trend-micro-xxe-poc

Metasploit Module is On Action

You can can access the module at here https://github.com/rapid7/metasploit-framework/pull/7969 Yey..! It’s merged to the master branch. Update your metasploit installation 😉

Responsible Disclosure

13 January 2017 – Vulnerability identified during penetration test by PRODAFT pentest team.

13 January 2017 – Details and short term mitigation shared with USTA/GPACT clients.

15 January 2017 10:02 PM – First contact with Trend Micro through [email protected]

16 January 2017 4:17 AM- First response from Trend Micro.

18 January 2017 9:51 AM – Solution plan and patch for #Issue 2 from Trend Micro.

21 January 2017  – Several emails between us and Trend Micro.

16 February 2017 – Trend Micro released a patch.

Mehmet Ince

Master Ninja @ Prodaft / INVICTUS Europe.