Research · android · privilege-boundary · responsible-disclosure

Cuando una vista previa alcanza un proceso privilegiado

Una vista previa solo debería mirar. En un Galaxy S22 Ultra, SoundPicker de Samsung puede generar el "highlight" de un ringtone a partir de un archivo de audio normal, y ese trabajo corre un decodificador FLAC nativo dentro de un proceso privilegiado del sistema, no dentro de la app que entregó el archivo. El decodificador se apoyaba en una clase de bug de memoria que Samsung ya corrigió como CVE-2026-21042 / SVE-2026-0716. El hallazgo que reportamos es el cruce: una entrada sin privilegios que alcanza código nativo privilegiado por una ruta de baja interacción, independiente de ese bug. Reportado a Samsung bajo divulgación coordinada. Esto es exploit research sobre un límite, escrito para ser verificable sin volverse una receta: aquí no aparecen parámetros del archivo malformado, secuencias de heap grooming ni reproducer.

La vista previa que no es pasiva

Una vista previa es fácil de descartar porque parece pasiva. Pero nada de producirla es pasivo: algún componente igual tiene que abrir el archivo, parsear el contenedor, decodificar el stream, reservar objetos nativos e interpretar metadatos. Si esa tubería corre dentro de un proceso privilegiado, la vista previa pasa a ser parte de la superficie de ataque privilegiada.

En dispositivos Samsung el flujo de selección de tonos hace más que mostrar metadatos. SoundPicker puede invocar una tubería nativa de análisis de audio para calcular un "highlight" corto a partir de un archivo normal. Rastreamos dónde se ejecuta ese trabajo de verdad.

La cadena de alcanzabilidad
  1. Archivo no confiable (MediaStore)
  2. Samsung SoundPicker
  3. AudioThumbnailCompat.extractHighlight()
  4. SemAudioThumbnail.extract()
  5. Frontera JNI
  6. libsmat.so — stack de medios nativo
  7. Decodificación FLAC — corre como platform_app

Modelo de amenaza

La condición inicial es deliberadamente ordinaria. Cualquier fuente no confiable —un archivo descargado, una app de mensajería, un servicio de sincronización, una descarga del navegador— puede hacer que un archivo de audio quede disponible por la infraestructura de medios de Android. Nada del archivo otorga privilegio.

Un bug de parser dentro de un sandbox de medios aislado y el mismo bug dentro de un proceso platform privilegiado no son el mismo evento de seguridad. El parser puede ser idéntico; el contexto de seguridad no. Esa transición —de una fuente con UID de aplicación a un proceso platform_app— es lo que quisimos caracterizar.

Dispositivo de prueba
DispositivoSamsung Galaxy S22 Ultra
ModeloSM-S908U
SoCSnapdragon SM8450
Android16
BuildS908USQSAGZF3
Parche de seguridad2026-06-05
Verified Bootbloqueado / verde
Knox warranty bit0

Mapear la superficie privilegiada

El primer paso no es explotar, es mapear la superficie. Para una app de sistema que consume archivos controlados por el usuario, las preguntas que importan son: qué app recibe el contenido, qué componentes están exportados, qué proceso hace el parsing, qué UID es dueño de ese proceso, qué dominio SELinux lo contiene, y si el parsing ocurre antes de interacción explícita del usuario.

En el dispositivo de prueba lo que importó fue que la función de highlight entra a la implementación nativa de análisis de audio de Samsung, y que eso corre dentro de SoundPicker en sí —un proceso platform_app (UID observado 10236)— no un extractor de medios aislado y genérico.

Mapeo de superficie

Inspección de solo lectura sobre un dispositivo de serie. Nada aquí parsea un archivo malicioso.

# qué exporta el paquete y quién puede alcanzarlo$ adb shell dumpsys package com.samsung.android.app.soundpicker# qué UID y dominio SELinux son dueños del proceso$ adb shell ps -AZ | grep soundpicker

Seguir de Java al código nativo

Revisar componentes exportados no basta: la actividad exportada es solo la entrada. La pregunta interesante es qué código nativo privilegiado queda alcanzable después de esa entrada. Tratamos las fronteras JNI como fronteras de seguridad que vale la pena mapear explícitamente —decompilando la app, encontrando las APIs de medios del fabricante que llama, y correlacionando esos métodos nativos de Java con los exports de la librería nativa detrás.

Backtraces reales de crashes en el dispositivo confirmaron que SemAudioThumbnail entra al stack de medios de Samsung por JNI hacia libsmat.so, y que el proceso dueño en el crash era SoundPicker, no un extractor sandboxeado.

Correlacionar la frontera JNI

# decompila y busca la API de medios del fabricante$ jadx -d out SoundPicker.apk$ rg -n "SemAudioThumbnail|extractHighlight" out/# empareja el método nativo de Java con un export de la librería$ nm -D libsmat.so | grep -i thumbnail

Causa raíz: el bug del decodificador detrás del límite

El decodificador FLAC nativo del firmware probado estaba afectado por el problema de memoria que Samsung después corrigió como CVE-2026-21042 / SVE-2026-0716. En términos simplificados, el decodificador de subframes LPC (predicción lineal) escribe una muestra de calentamiento por cada orden de predicción en un búfer por canal dimensionado para el tamaño de bloque.

La forma vulnerable (simplificada)

allocate_channel_buffer(block_size);

for (i = 0; i < lpc_order; i++)
    channel_buffer[i] = read_warmup_sample();

Cuando el orden supera al bloque

La condición de overflow es simplemente lpc_order > block_size: la reserva está dimensionada para el bloque, mientras el bucle escribe según el orden de predicción. El decodificador corregido rechaza esa relación antes de escribir. La comparación binaria de la librería pre y post-fix mostró un pequeño parche de validación alrededor de exactamente esa condición.

Lo que impone el fix

if (lpc_order > block_size)
    return ERROR;

if (lpc_order > FLAC_MAX_LPC_ORDER)
    return ERROR;

Patch diffing del invariante

Una vez que un fabricante publica un fix, el diffing binario es una de las formas más útiles de recuperar el invariante de seguridad que cambió. El objetivo no es "estos binarios difieren", es "¿qué suposición sobre la entrada decidió el fabricante que ahora debe imponerse?" Aquí, la respuesta fue la relación entre el orden LPC, el tamaño de bloque y el orden máximo de FLAC.

Recuperar el invariante desde firmware público

# identifica las dos versiones de la librería$ sha256sum old/libsavsac.so new/libsavsac.so# compara símbolos exportados, luego diff en un disassembler$ readelf -Ws old/libsavsac.so > old.sym; diff -u old.sym new.sym

El límite de la explotación

Un crash de heap genérico es evidencia débil, así que la pregunta real es siempre si el atacante influye en qué se escribe, o solo en dónde el allocator nota el daño después. Con una copia instrumentada y desechable del decodificador en espacio de usuario —la librería del sistema nunca se reemplazó— confirmamos que las escrituras de calentamiento llevan influencia del atacante por palabra, y luego reprodujimos la corrupción dentro de SoundPicker, donde el allocator Scudo de Android abortó ante un chunk dañado. Bajo algunos layouts de heap, un objeto vecino corrupto llevó a una influencia acotada y dependiente del objetivo sobre el flujo de control nativo.

Ahí paramos, y somos precisos al respecto. La construcción del archivo malformado, el trabajo de layout y grooming del heap, y el reproducer se omiten a propósito mientras la divulgación siga abierta. Lo que importa para este artículo es el límite que establecen las primitivas, no las primitivas como receta.

Qué demostramos, y qué no

Demostrado

  • Ruta FLAC vulnerable identificada y alcanzada
  • Decodificador vulnerable vs corregido aislado por diff binario
  • Escritura fuera de límites en heap nativo reproducida, con influencia por palabra
  • Corrupción reproducida dentro de Samsung SoundPicker (platform_app)
  • El límite de privilegio desde entrada no confiable confirmado
  • Una influencia acotada y dependiente del objetivo sobre el flujo de control

No reclamado

  • Escritura arbitraria de dirección/valor
  • Control fiable y arbitrario del PC
  • Ejecución de código nativo arbitrario
  • Escape del sandbox más allá de SoundPicker
  • Root
  • Compromiso persistente

Por qué el privilegio de SoundPicker importa sin root

Incluso ejecución total de código dentro de SoundPicker no implicaría UID 0. SoundPicker corre como aplicación de plataforma, con privilegios como WRITE_SECURE_SETTINGS, MANAGE_USERS e INTERACT_ACROSS_USERS —significativos, pero no root. Una cadena de exploit todavía tendría que distinguir ejecución de código en SoundPicker de root; son etapas separadas.

La razón por la que SoundPicker sigue siendo sensible no es que equivalga a root. Es que alcanzarlo siquiera es una transición de privilegio lejos de la fuente no confiable que entregó el archivo.

Una regla para revisar vistas previas
  1. Confianza de la entrada
  2. ¿Quién la parsea?
  3. ¿En qué proceso?
  4. ¿Con qué privilegios?
  5. ¿Antes de qué acción del usuario?

Divulgación

Reportamos la alcanzabilidad privilegiada de la vista previa de SoundPicker a Samsung Mobile Security bajo divulgación coordinada, junto con un segundo problema de endurecimiento, distinto, en un componente nativo vecino alcanzable desde la misma ruta. La evaluación inicial de Samsung asoció el comportamiento base del decodificador con el ya corregido CVE-2026-21042 / SVE-2026-0716.

Nuestra posición es más acotada y arquitectónica: la vulnerabilidad ya corregida del decodificador y la existencia de una ruta de baja interacción desde medios no confiables hacia decodificación nativa privilegiada son preguntas de seguridad separadas. Mientras la discusión de alcanzabilidad siga abierta, retenemos los parámetros del archivo malformado, los layouts de heap orientados a explotación, las secuencias de grooming, los trigger files y el reproducer. El material público es a propósito suficiente para explicar y validar el hallazgo sin volverse una receta de explotación.

Un escáner puede marcar una librería vulnerable. El trabajo empieza cuando muestras quién puede alcanzarla, en qué proceso, con qué privilegios, y qué límite falló cuando llegó la entrada. Ese límite es el hallazgo, y nombrar exactamente dónde te detuviste es lo que lo mantiene honesto.

Más research

¿Ponemos esto a prueba?

Definimos el alcance contigo y empezamos con autorización por escrito.

Solicitar una evaluación
KNULL / DATOS
DATOS / CONTACTO

Solo lo
necesario.

Esta página no recoge nada. El formulario de la portada guarda solo lo que le envías, en el servidor que aloja este sitio, sin analítica ni modelos de IA.