Análisis forense de TCC.db: guía para investigadores
Qué registra la base de datos TCC de macOS, qué prueba y qué no, qué servicios importan y un flujo de trabajo repetible para revisar TCC.db en un caso.
Resumen. Transparency, Consent and Control (TCC) es el framework de macOS que decide si un programa puede usar la cámara, el micrófono, la pantalla, los dispositivos de entrada, las API de accesibilidad, las carpetas protegidas, el disco completo u otras apps mediante Apple Events. El daemon tccd guarda cada decisión como una fila en una base de datos SQLite, TCC.db: una para el sistema y otra por usuario. Cada fila indica qué cliente, qué servicio, si se permitió o se denegó, por qué y cuándo cambió la fila por última vez. Es un registro de permisos, no un log de uso. TCC Parser decodifica estas bases de datos en su navegador, incluidas las versiones anteriores de filas que quedan en el archivo WAL; no se sube nada.
Esta guía es el punto de entrada de la serie. Cada sección enlaza con un artículo más detallado.
Qué es TCC y por qué interesa al investigador
Casi todo lo interesante que un malware o un intruso quiere hacer en un Mac pasa por un recurso protegido por TCC: leer Mail, Mensajes o los datos del navegador (requiere acceso total al disco, Full Disk Access), ver la pantalla (grabación de pantalla), registrar pulsaciones de teclas (monitorización de entrada), aceptar cuadros de diálogo (Accesibilidad) o controlar Finder y System Events para actuar en nombre del usuario (automatización mediante Apple Events). Cuando un programa pide una de esas capacidades, tccd muestra una solicitud al usuario, aplica una política o la rechaza, y registra el resultado.
Por eso TCC.db es uno de los lugares donde la intención se hace visible. Un helper identificado por ruta en una carpeta de caché oculta que pide Accesibilidad, o Terminal obteniendo acceso total al disco minutos después de una descarga sospechosa, es justo el tipo de hecho que la base de datos recoge bien.
Qué puede probar una fila y qué no
| Una fila puede mostrar | Una fila no puede mostrar |
|---|---|
| Que un cliente (bundle ID o ruta absoluta) tiene un servicio, o que se le denegó | Que la capacidad se usara realmente, ni con qué frecuencia |
| Si la decisión fue permitido, denegado, desconocido o limitado (auth_value) | Qué se capturó, se leyó o se tecleó |
| Un código de motivo para la decisión (auth_reason, documentado por la comunidad) | Quién estaba físicamente ante el teclado |
| El requisito de firma de código que debe cumplir el cliente (csreq) | Que el binario que hay hoy en disco sea el que se aprobó |
| En Automatización, qué app se controla | Cada estado anterior de la fila (solo el último, salvo que el WAL conserve más) |
Cuándo cambió la fila por última vez (last_modified, segundos Unix en UTC) | Cuándo se concedió el permiso por primera vez, si la fila cambió después |
Dos consecuencias condicionan todo informe. Primera: una concesión es una capacidad, no una actividad. Escriba "tenía acceso total al disco desde las 10:11:37 UTC", no "leyó el correo del usuario". Segunda: la ausencia es una prueba débil. tccutil reset, los restablecimientos en Ajustes del Sistema y la eliminación de apps borran filas. Vea recuperar permisos TCC eliminados del WAL.
Dónde se encuentran las bases de datos
| Base de datos | Ruta | Contenido habitual |
|---|---|---|
| Sistema | /Library/Application Support/com.apple.TCC/TCC.db | Acceso total al disco, Accesibilidad, grabación de pantalla, monitorización de entrada, Herramientas de desarrollo, clientes de Endpoint Security |
| Por usuario | ~/Library/Application Support/com.apple.TCC/TCC.db | Cámara, micrófono, contactos, calendarios, fotos, Automatización, Escritorio/Documentos/Descargas, volúmenes extraíbles y de red |
| Concesiones MDM | /Library/Application Support/com.apple.TCC/MDMOverrides.plist | Concesiones PPPC enviadas por un servidor de gestión |
La columna "contenido habitual" es orientativa: el reparto depende del servicio y ha cambiado entre versiones, así que consulte siempre todas las copias. Para leer cualquiera de estos archivos en un Mac en vivo, el proceso que hace la copia necesita acceso total al disco, y System Integrity Protection protege además la base de datos del sistema contra modificaciones, incluso por parte de root. Los archivos asociados TCC.db-wal y TCC.db-shm también importan. Los detalles de recolección y las trampas de cada herramienta están en ubicación y adquisición de TCC.db.
Cómo leer una fila
La tabla que importa es access. En Big Sur y posteriores, las columnas que más usará son:
| Columna | Qué leer en ella |
|---|---|
service | El servicio TCC, p. ej. kTCCServiceSystemPolicyAllFiles |
client | Bundle ID o ruta absoluta del programa |
client_type | 0 bundle ID, 1 ruta absoluta (client_type) |
auth_value | 0 denegado, 1 desconocido, 2 permitido, 3 limitado |
auth_reason | El motivo (consentimiento del usuario, fijado por el usuario, política MDM, etc.; documentado por la comunidad) |
csreq | Requisito de código compilado que identifica al cliente |
indirect_object_identifier | En Automatización: la app controlada |
last_modified | Segundos de época Unix, UTC |
Mojave y Catalina usaban allowed y prompt_count en lugar de auth_value y auth_reason; Sonoma añadió pid, pid_version, boot_uuid y last_reminded. Compruebe siempre .schema access en su copia. La evolución completa y las tablas secundarias que rodean a access están en la tabla access de TCC en las versiones de macOS.
Los servicios que más importan
| Identificador de servicio | Nombre en Ajustes del Sistema | Por qué importa |
|---|---|---|
kTCCServiceSystemPolicyAllFiles | Acceso total al disco | Lee datos protegidos del usuario: Mail, Mensajes, Safari, otros archivos TCC.db |
kTCCServiceAccessibility | Accesibilidad | Controla la interfaz: clics, pulsaciones de teclas, aceptación de cuadros de diálogo |
kTCCServiceScreenCapture | Grabación de pantalla | Ve todo lo que hay en pantalla |
kTCCServiceListenEvent | Monitorización de entrada | Observa los eventos de teclado y ratón |
kTCCServicePostEvent | (entrada sintética) | Envía eventos de entrada |
kTCCServiceAppleEvents | Automatización | Controla otra app; destino en indirect_object_identifier |
kTCCServiceSystemPolicyDocumentsFolder y afines | Archivos y carpetas | Escritorio, Documentos, Descargas |
kTCCServiceSystemPolicyRemovableVolumes | Volúmenes extraíbles | Unidades USB y similares |
kTCCServiceEndpointSecurityClient | (Endpoint Security) | Agentes de seguridad; uno nuevo merece una revisión |
Quién decidió: usuario, sistema o MDM
auth_reason es lo que permite distinguir un clic del usuario de una política. Entre los valores citados con frecuencia están 2 consentimiento del usuario (respondió a una solicitud), 3 fijado por el usuario (activado en Ajustes del Sistema), 4 fijado por el sistema y 6 política MDM. Apple no documenta estos enteros; trátelos como hipótesis y confírmelos en un Mac de prueba con la misma versión, o en el registro unificado, antes de apoyarse en ellos.
En los Macs gestionados, las concesiones enviadas por un perfil de Privacy Preferences Policy Control (PPPC) se reflejan en MDMOverrides.plist, y las filas pueden hacer referencia a la tabla policies mediante policy_id. Que un agente EDR legítimo tenga acceso total al disco por MDM es normal. Un perfil PPPC inesperado es un hallazgo en sí mismo.
Un flujo de trabajo repetible
- Recopile la carpeta
com.apple.TCCcompleta del sistema y de cada usuario, con-waly-shm, desde un proceso que tenga acceso total al disco (o desde una imagen montada). Calcule el hash de lo recopilado. - Compruebe el esquema de cada base de datos antes de consultarla: las columnas varían según la versión.
- Revise las concesiones de alto impacto: acceso total al disco, Accesibilidad, grabación de pantalla, monitorización de entrada, Post Event, Herramientas de desarrollo, Endpoint Security. Pregúntese quién las tiene y si encaja con el puesto del usuario.
- Examine los clientes identificados por ruta (
client_type = 1) y los clientes en carpetas temporales, compartidas u ocultas. Las apps legítimas casi siempre aparecen con bundle ID. - Decodifique
csreq. Un requisito que solo contiene uncdhashfija una compilación exacta, lo habitual en código con firma ad hoc. Vea decodificar los requisitos de código csreq. - Lea las filas de Automatización en la base de datos de cada usuario: qué app puede controlar Finder, System Events o Terminal.
- Recupere el historial de
TCC.db-waly de las páginas liberadas: concesiones eliminadas y modificadas. - Construya una cronología a partir de
last_modifiedy correlaciónela con el registro unificado (subsystem == "com.apple.TCC"), los eventos de cuarentena, los trabajos de launchd y el historial de shell.
El artículo investigar el abuso de permisos TCC aplica este flujo a una intrusión realista y ficticia.
Herramientas
- sqlite3 sobre una copia, con sus propias consultas. Suficiente para comprobaciones puntuales; los blobs y los códigos de motivo los decodifica usted.
- Plugin
TCCde mac_apt: admite los formatos de Catalina y de Big Sur en adelante, desde una imagen o en modo solo artefactos. - Plugin
macostccde Plaso: espera las columnasallowed/prompt_countanteriores a Big Sur, así que está pensado para bases de datos de Mojave y Catalina. - Velociraptor
MacOS.System.TCC: consultas en vivo a escala de flota. - TCC Parser: suelte la carpeta o un ZIP de triaje en el navegador; decodifica todas las versiones del esquema, los requisitos de código y los códigos de motivo, marca las filas destacables, recupera el historial del WAL y exporta CSV, CSV para Timesketch y JSON. El paso a paso está en analizar TCC.db en el navegador.
Apple y macOS son marcas comerciales de Apple Inc. TCC Parser es una herramienta independiente y no está afiliada a Apple ni cuenta con su respaldo.
Errores frecuentes
- Recolección incompleta. Sin acceso total al disco, la copia falla o sale vacía. La falta de TCC.db en un paquete de triaje suele ser un problema de recolección.
- Olvidar el WAL. Varios recolectores copian solo
TCC.db. Los cambios recientes pueden seguir enTCC.db-wal. - Proceso responsable. Los permisos suelen atribuirse a la app que lanzó una herramienta (Terminal) y no al script que los usó. Una concesión a Terminal cubre todo lo que se ejecuta desde ella.
- Bundle ID frente a binario. Una fila por bundle ID se aplica a cualquier código que cumpla el requisito almacenado. Compare el requisito con el binario en disco.
- Sobreinterpretar los códigos de motivo. Los significados de
auth_reasonestán documentados por la comunidad, no son oficiales.
Preguntas frecuentes
¿TCC.db registra cada vez que una app usó la cámara o leyó mis archivos?
No. TCC.db guarda decisiones vigentes: a qué cliente se le permitió o denegó qué servicio, y cuándo cambió esa decisión por última vez. Los usos individuales no se registran ahí. La evidencia de cada solicitud está en el registro unificado, en el subsistema com.apple.TCC, y el historial de uso, en otros artefactos.
¿La ausencia de una fila prueba que un permiso nunca se concedió?
No. tccutil reset, un restablecimiento en Ajustes del Sistema o la eliminación de la app borran filas. Versiones anteriores de una fila pueden sobrevivir un tiempo en TCC.db-wal o en páginas liberadas, y pueden existir copias más antiguas de la base de datos en snapshots de APFS o en copias de seguridad de Time Machine.
¿Qué base de datos TCC debo revisar, la del sistema o la del usuario?
Las dos, siempre. Los servicios de alto impacto, como el acceso total al disco, Accesibilidad y grabación de pantalla, suelen estar en la base de datos del sistema, mientras que cámara, micrófono, Automatización y acceso a carpetas suelen estar en la base de datos de cada usuario. El reparto depende del servicio y ha cambiado entre versiones, así que consulte todas las copias.
¿En qué zona horaria está last_modified?
last_modified está en segundos de época Unix, es decir, en UTC. No es Mac absolute time. Lo mismo vale para last_reminded (Sonoma y posteriores) y para expired_at en la tabla expired.