
Prueba de concepto que demuestra una omisión de la comprobación de acceso a Windows Cloud Files (CVE-2026-83991) que convierte un archivo de solo lectura en un marcador de posición en la nube mediante semántica de supersedencia, con análisis técnico detallado y pasos de reproducción.
Mantuve estas líneas juntas porque separarlas hace que el fallo parezca más complicado de lo que es:
CreateFileW, GENERIC_WRITE error 5
DeleteFileW error 5
CfCreatePlaceholders, SUPERSEDE S_OK
per-entry Result S_OK
La apertura de escritura, el intento de eliminación y la llamada a Cloud Files usan el mismo nombre de ruta y el mismo token de hilo. Antes de la última llamada, el nombre pertenece a un archivo ordinario con una DACL protegida y sin punto de reanálisis. Después de ella, FSCTL_GET_REPARSE_POINT devuelve IO_REPARSE_TAG_CLOUD.
Microsoft publicó ese resultado como CVE-2026-83991, la vulnerabilidad de manipulación del controlador de minifiltro de Cloud Files de Windows. Yo lo había descrito en el informe como autorización incorrecta y sugerí CWE-863. Microsoft asignó CWE-306 en su lugar.
El programa instala su token de suplantación restringido antes de crear el directorio de prueba, el archivo, las DACL o la raíz de sincronización. No hay una configuración elevada seguida de un cambio de token solo para la llamada interesante. Si la cuenta tiene un SID de Administrators, CreateRestrictedToken lo convierte en solo denegación; si el SID nunca estuvo presente, el programa también registra ese caso. La integridad se establece en Medium.
El padre y la hoja deliberadamente no tienen DACL coincidentes. El usuario actual recibe esto en el directorio:
FILE_GENERIC_READ |
FILE_GENERIC_WRITE |
FILE_GENERIC_EXECUTE |
DELETE
El archivo existente recibe FILE_GENERIC_READ, y su DACL está protegida contra la herencia. SYSTEM y Administrators conservan el control total. Como el SID de Administrators del token está ausente o es solo denegación, la ACE de permiso de Administrators no puede conceder acceso a este hilo.
El bit DELETE en el padre parece sospechoso hasta que se explicita el objeto al que se aplica. Permite la eliminación del propio directorio. Eliminar uno de sus hijos es FILE_DELETE_CHILD, un bit diferente que la ACE del padre no contiene. DeleteFileW acepta DELETE en la hoja o el permiso delete-child en el padre. La prueba no tiene ninguno de los dos, por lo que el error 5 es el resultado de control esperado.
Dejé FILE_GENERIC_WRITE en el padre. Su bit FILE_WRITE_DATA es FILE_ADD_FILE cuando el objeto es un directorio. El llamador puede crear un hijo, y el padre por lo tanto cumple el requisito documentado de WRITE_DATA o WRITE_DAC para CfCreatePlaceholders. Sin ese derecho, la API falla su comprobación de directorio base antes de llegar al caso que reporté.
El programa no registrará la raíz de sincronización a menos que este bloque sea verdadero:
write open denied with ERROR_ACCESS_DENIED
DeleteFileW denied with ERROR_ACCESS_DENIED
read open succeeded
leaf DACL protected
starting object not a reparse point
Hice que se detuviera ahí porque un S_OK más adelante en la ejecución sería inútil si la hoja ya hubiera sido escribible, eliminable o un punto de reanálisis.
Después de esos controles, el programa registra el padre como raíz de sincronización, lo conecta con una tabla de callbacks que contiene solo la entrada terminadora, y envía el nombre de archivo existente con el flag 0x4:
placeholder.RelativeFileName = leaf_name;
placeholder.FsMetadata.BasicInfo = basic_info;
placeholder.FsMetadata.FileSize = standard_info.EndOfFile;
placeholder.FileIdentity = &run_id;
placeholder.FileIdentityLength = sizeof(run_id);
placeholder.Flags = CF_CREATE_SUPERSEDE;
create_hr = cf.Create(root, &placeholder, 1, 0, &processed);
CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE está documentado como sobrescribir un placeholder existente. Este archivo no lo es. El PoC establece FILE_ATTRIBUTE_NORMAL antes de aplicar la DACL de la hoja y confirma que el bit de punto de reanálisis está limpio antes de llamar a Cloud Files.
En el sistema afectado, la llamada por lotes y la entrada devolvieron ambas S_OK, y CreateUsn fue distinto de cero. El archivo adquirió el atributo de punto de reanálisis. Pedir al sistema de archivos los datos de reanálisis devolvió el tag 0x9000001A, que es IO_REPARSE_TAG_CLOUD.
EntriesProcessed == 1 no prueba el éxito porque la documentación de la API también cuenta las entradas fallidas. La confirmación proviene de ambos HRESULT, el USN de creación, el atributo de reanálisis y el tag Cloud.
FILE_ID_INFO no cambió durante la llamada. El objeto de archivo existente adquirió el estado de Cloud Files; no apareció simplemente otro archivo bajo el mismo nombre de ruta.
La compilación afectada más antigua listada por MSRC es 17763.0, la generación de Windows 10 versión 1809 y Windows Server 2019. Eso sitúa el rastro público en 2018, casi ocho años antes de la corrección de septiembre de 2026.