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"); }
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.
And HTTP request from IMSVA observed at another machine.
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.