Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-43783 — Prueba de concepto y análisis técnico de CVE-2026-43783, una escalada de privilegios local en macOS a través de DesktopServicesHelper XPC con chown arbitrario para obtener root. | Kitploit
Herramientas/GitHubGitHub/andrd3v/cve-2026-43783
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónIngeniería InversaPruebas de PenetraciónAnálisis de BinariosPapers e Investigación
GitHubandrd3v/cve-2026-43783

CVE-2026-43783

Prueba de concepto y análisis técnico de CVE-2026-43783, una escalada de privilegios local en macOS a través de DesktopServicesHelper XPC con chown arbitrario para obtener root.

Ver Repositorio
21426hace 1 mesRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-43783: Repair Permissions - Get Root: LPE via DesktopServicesHelper en macOS 26.5

Publicado originalmente en PT SWARM o andrd3v.github.io

El daemon que Finder utiliza para "reparar" los permisos de los archivos de iCloud resultó estar dispuesto a reparar permisos de cualquier cosa, incluidos los directorios del sistema. En este artículo veremos cómo funciona DesktopServicesHelper internamente y por qué una sola solicitud XPC fue suficiente para obtener root.

Dentro de DesktopServicesHelper

Estaba buscando objetivos con com.apple.private.tcc.allow con el valor kTCCServiceSystemPolicyAllFiles y DesktopServicesHelper llamó mi atención. DesktopServicesHelper se encuentra en /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/Versions/A/Resources/DesktopServicesHelper, y Finder lo utiliza para operaciones de archivos que requieren privilegios elevados: mover archivos, establecer permisos, trabajar con la Papelera.

Entitlements DesktopServicesHelper

Cargué el binario en IDA y fui a start(). Pasada la configuración habitual de temporizadores y colas, crea un listener XPC, el punto de entrada del daemon. El listener registra un servicio mach bajo un nombre específico y comienza a escuchar conexiones entrantes. Cualquier proceso que conozca este nombre puede conectarse y enviar una solicitud. Aquí está la parte clave:

// get the service name
v16 = (const char *)sub_1000709F4(a1: 0);

// register the listener
mach_service = xpc_connection_create_mach_service(name: v16, targetq: nullptr, flags: 1u);

// set the incoming event handler
xpc_connection_set_event_handler(connection: mach_service, handler: &stru_1000B4B48);
xpc_connection_resume(connection: mach_service);

// start the event loop
CFRunLoopRun();

La función sub_1000709F4 devuelve el nombre del servicio mach. En start() se llama con el argumento 0, lo que significa que el daemon se registra bajo el nombre com.apple.DesktopServicesHelper.

const char *__fastcall sub_1000709F4(int a1)
{
  if ( a1 != 0 )
    return "com.apple.DesktopServicesScriptingHelper";
  else
    return "com.apple.DesktopServicesHelper";
}

stru_1000B4B48 es un bloque manejador (callback) que el daemon invoca para cada evento entrante. XPC está basado en mensajes: el cliente construye un diccionario con claves y valores, lo envía al daemon, y el daemon analiza el contenido y decide qué hacer. Todos los eventos entrantes terminan en este manejador. Veamos su interior.

stru_1000B4B48 en IDA

La función de invocación del bloque es sub_100032044. En una nueva conexión, el daemon primero obtiene el euid y el egid del cliente - ID de usuario efectivo e ID de grupo - los identificadores del usuario y del grupo bajo los cuales se ejecuta el proceso que se conecta:

euid = xpc_connection_get_euid(connection: v8);
egid = xpc_connection_get_egid(connection: v8);
sub_100071268(a1: euid, a2: egid);

Luego asigna un manejador para los mensajes entrantes en la conexión:

v15[2] = sub_10003AB2C;  // block's invoke function
xpc_connection_set_event_handler(connection: v14, handler: v15);
xpc_connection_resume(connection: v14);

sub_10003AB2C - aquí es donde llegan las solicitudes XPC reales del cliente. Ahora necesitamos entender cómo el daemon decide qué solicitudes ejecutar y cuáles rechazar.

Despachador de solicitudes

sub_10003AB2C es el despachador principal. Aquí es donde el daemon decide qué hacer con una solicitud. La función es grande, así que vamos a desglosarla.

Primero, extrae la cadena "request" del mensaje - el nombre del comando que el cliente quiere ejecutar:

reply = xpc_dictionary_create_reply(original: v12);
string = xpc_dictionary_get_string(xdict: v12, key: "request");
// ...
// logging: "Got Request '%{public}@'"

Luego, el daemon recupera el token de auditoría del proceso que se conecta y verifica si se está ejecutando dentro de App Sandbox. App Sandbox es un mecanismo de aislamiento de aplicaciones de macOS que restringe el acceso al sistema de archivos, la red y otros recursos. Aquí es donde se bifurca:

xpc_dictionary_get_audit_token(a1: v12, a2: buf);
qmemcpy(__p, buf, sizeof(__p));
if ( (unsigned int)sandbox_check_by_audit_token(a1: __p, a2: 0, a3: 0) != 0 )
{
  // client is sandboxed - check against allowlist
  if ( (sub_10003B25C(a1: &v32, a2: "Handshake") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "exit") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "SetDefaultPermissionOnHomeSubdirectories") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "MoveAsideICloudToArchiveInHome") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "RepairPermissionsForCloudItems") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "CopyClientActive") & 1) == 0
    && (sub_10003B25C(a1: &v32, a2: "DeleteItem") & 1) == 0 )
  {
    sub_100034250(a1: v12, a2: &v32); // not in the list - kill the daemon
  }
}
else
{
  // client is not sandboxed - check entitlement
  *(_QWORD *)buf = sub_1000343C0(a1: v12, a2: CFSTR("com.apple.private.tcc.allow"));
  v19 = (const __CFArray *)sub_10003B1E0();
  v20 = v19;
  if ( v19 == nullptr
    || (v35.length = CFArrayGetCount(theArray: v19),
        v35.location = 0,
        CFArrayContainsValue(theArray: v20, range: v35, value: CFSTR("kTCCServiceSystemPolicyAllFiles")) == 0) )
  {
    sub_100034250(a1: v12, a2: &v32); // no entitlement - kill the daemon
  }
}

Si el cliente está en sandbox, el nombre de la solicitud se compara con una lista de permitidos de siete cadenas. Si coincide, la comprobación pasa y la solicitud continúa. Si no, sub_100034250 mata al daemon. Si el cliente no está en sandbox, el daemon comprueba el entitlement com.apple.private.tcc.allow con el valor kTCCServiceSystemPolicyAllFiles. La ausencia del entitlement también significa la muerte.

Tras pasar la comprobación, la solicitud atraviesa dos tablas de controladores. Primero sub_10002F7C8, luego sub_10002A194:

// first table (8 commands, two arguments)
v21 = sub_10002F7C8(a1: buf);
// ...
if ( v21 != 0 )
  v22(a1: v12, a2: v11); // found - invoke

// second table (21 commands, three arguments)
v27 = sub_10002A194(a1: buf);
// ...
if ( v27 != nullptr )
  v27(a1: v12, a2: reply, a3: v11); // found - invoke

Ahora veamos las tablas de controladores. La primera tabla (sub_10002F7C8):

__int64 __fastcall sub_10002F7C8(__int64 a1)
{
  __int64 result; // x0
  void **v3; // x21
  void **v4; // x8
  _BYTE v5[32]; // [xsp+8h] [xbp-128h] BYREF
  __int64 v6; // [xsp+28h] [xbp-108h] BYREF
  __int64 v7; // [xsp+48h] [xbp-E8h] BYREF
  __int64 v8; // [xsp+68h] [xbp-C8h] BYREF
  __int64 v9; // [xsp+88h] [xbp-A8h] BYREF
  __int64 v10; // [xsp+A8h] [xbp-88h] BYREF
  __int64 v11; // [xsp+C8h] [xbp-68h] BYREF
  __int64 v12; // [xsp+E8h] [xbp-48h] BYREF
  __int64 v13; // [xsp+108h] [xbp-28h] BYREF
Descargar herramienta