fairplay-decrypt: descifrado de IPA FairPlay sin conexión
Una herramienta pública recupera una credencial FairPlay de cuenta de 16 bytes de un iPhone con jailbreak y descifra sin conexión los IPA correspondientes.
Resumen
fairplay-decryptes una herramienta GPLv3 que descifra IPA de App Store cifrados con FairPlay sin lanzar la app. Usa una credencial de 16 bytes para la cuenta de Apple que posee el IPA.- El recuperador necesita un iPhone con jailbreak en iOS 10 o posterior, SSH root y una app instalada desde esa cuenta. El descifrado se ejecuta después sin conexión en macOS o Linux con Python 3.9 o posterior.
- La debilidad es una credencial de cuenta reutilizable que desenvuelve la clave de cada app. Una captura descifra los IPA de esa cuenta. No se asigna ninguna CVE, y el KEV de CISA 2026.11.10 no tiene ninguna entrada FairPlay.
- Trate el IPA como público cuando se pueda capturar la credencial de la cuenta. Mantenga los secretos en el servidor, detecte versiones reempaquetadas e instale apps solo desde el App Store. Vea «¿Cómo lo corrijo?».
¿Estoy afectado?
Está expuesto si su app se distribuye como un IPA arm64 cifrado con FairPlay y un atacante puede obtener una credencial de una cuenta de Apple que la posea. Todas estas condiciones deben cumplirse:
- Su versión de App Store está cifrada con FairPlay. La herramienta solo procesa segmentos Mach-O arm64 con
LC_ENCRYPTION_INFO_64y uncryptiddistinto de cero. - El atacante tiene la credencial de 16 bytes del tipo correspondiente para una cuenta de Apple que posee la app, o un modelo reutilizable recuperado de una inscripción de Mac vinculada a ella.
- El atacante tiene el IPA. Puede comprarlo con esa cuenta, recibirlo de un socio o robarlo.
- Puede ejecutar la herramienta en macOS o Linux. El descifrado no necesita acceso de red a Apple ni a sus servidores.
Esto no es una vulnerabilidad remota en la app. Es una propiedad del envoltorio FairPlay alrededor del IPA, y el paso de captura necesita un dispositivo comprometido o un Mac inscrito. Una credencial de una cuenta no descifra una app de otra cuenta. La herramienta no procesa el vídeo FairPlay Streaming, los binarios de 32 bits ni los IPA sin cifrar.
Una credencial normal cubre las apps normales del App Store. El README del recuperador indica que las apps de Apple Arcade necesitan una credencial Arcade distinta, así que una captura no cubre ambos tipos.
| Vía de captura | Qué necesita el atacante | Qué produce |
|---|---|---|
iPhone con jailbreak (fairplay-decrypt) |
iOS 10 o posterior, SSH root, una app instalada desde la cuenta objetivo y un Mac con Xcode y ldid para compilar el recuperador |
Una credencial de cuenta de 16 bytes; el descifrado sin conexión de los IPA correspondientes que posee la cuenta |
Mac inscrito (UnfairPlay) |
Un Mac con sesión en el Mac App Store, una app de iPhone instalada y abierta, y un IPA correspondiente | Un modelo de inscripción reutilizable; el descifrado de otros IPA de la misma inscripción |
| Credencial filtrada | Una credencial de 16 bytes de cualquiera de las dos vías y un IPA que posea la cuenta | Descifrado sin conexión sin dispositivo |
Compruebe si un IPA está cifrado. En macOS, extraiga el binario principal y lea su comando de carga de cifrado:
unzip -p App.ipa Payload/App.app/App > /tmp/App
otool -l /tmp/App | grep -A4 LC_ENCRYPTION_INFO_64
codesign -dv --verbose=4 /tmp/App
Un cryptid de 1 significa que las páginas están cifradas. Un valor de 0 significa que el binario ya está en claro. Sustituya Payload/App.app/App por la ruta del ejecutable del IPA. El comando codesign muestra el TeamIdentifier de la firma, que debe comparar con el suyo.
¿Cómo lo corrijo?
El repositorio no publica ninguna versión corregida, porque es la herramienta de descifrado y no un producto con una versión parcheada. Estos pasos reducen la exposición y limitan lo que revela una copia descifrada:
- Trate el IPA descifrado como público. Elimine las claves de API, los secretos de firma y los algoritmos propietarios que deban seguir siendo confidenciales. Un secreto en el cliente es legible cuando las páginas están en claro.
- Mueva las decisiones sensibles a su servidor. Autorice las acciones en el servidor con tokens de corta duración y no confíe en un valor que viaje en el binario.
- Añada detección de reempaquetado y atestación en el servidor. App Attest y DeviceCheck de Apple pueden señalar un cliente modificado, pero no impiden el descifrado.
- Para los usuarios, instale apps solo desde el App Store o TestFlight. En flotas gestionadas, bloquee la instalación fuera del catálogo gestionado.
- Si cree que se capturó una credencial de cuenta, deje de usar esa cuenta para distribuir y trate cada IPA que provenga de ella como expuesto. Revise su historial de compras.
Estos pasos no impiden el descifrado de un IPA que posea la cuenta. Limitan lo que revela la copia descifrada y cómo se puede reutilizar.
¿Cuál es la causa raíz?
FairPlay cifra cada página de 4 KB con una clave derivada de dos archivos de SC_Info, y la cadena empieza en una credencial de cuenta de 16 bytes. El cifrado es AES-128. La debilidad está en dónde se guarda el secreto raíz, no en un cifrado roto.
Los tres archivos que importan
<Name>.sinfes un árbol de átomos con elnamede la cuenta, univivde 16 bytes y un registroprivde 440 o 448 bytes.<Name>.supfo<Name>.v5.supfcontiene un registro de 32 bytes por página cifrada: una clave envuelta de 16 bytes y un IV AES-CBC de 16 bytes.- La cabecera Mach-O arm64 lleva
LC_ENCRYPTION_INFO_64concryptoff,cryptsizeycryptid, que localizan las páginas cifradas.
derive_work16() convierte la credencial de cuenta y el registro priv en una clave de trabajo de 16 bytes propia de la app. En el fragmento, name, iviv, credential y raw_priv son los campos SINF y la credencial de 16 bytes que lee el analizador. La clave es la credencial combinada con XOR con el byte 0x30, no la credencial sola.
El IV es el MD5 del nombre de la cuenta y iviv:
iv = hashlib.md5(name + iviv).digest()
op = Cipher(algorithms.AES(_xor(credential, b"0" * 16)), modes.CBC(iv)).decryptor()
clear = op.update(raw_priv) + op.finalize()
if clear[:4] != b"itun" or clear[20:24] != b"key " or clear[44:48] != b"iviv":
raise ValueError("credential does not decode this SINF priv record")
return clear[24:40]
derive_page_key() toma el registro envuelto de 16 bytes, el índice de página y la clave de trabajo. Cifra tres bloques de origen de 16 bytes con AES-128-ECB bajo la clave de trabajo y luego los mezcla con una transformación propia llamada finish():
a, b, c = (
struct.unpack(">8H", block_transform(s, work))
for s in source_blocks(wrapped, absolute_index)
)
return struct.pack(">8H", *finish(_xor_int(finish(_xor_int(finish(a), b)), c)))
finish() ejecuta cuatro rondas de 16 bits y cuatro rondas de 32 bits de sumas, cuadrados y XOR. Los comentarios del código indican que un acarreo se conserva y el otro se descarta. Esa transformación es ofuscación sobre AES, no un segundo secreto. El resultado de 16 bytes es la clave AES-CBC de la página, y los 16 bytes siguientes del registro SUPF son su IV.
La clave propia de la app está cifrada bajo un secreto de cuenta, así que una credencial desenvuelve el registro priv de cada app correspondiente que posee la cuenta. El recuperador obtiene esa credencial en el dispositivo. Coloca puntos de interrupción de hardware en la función de selección de fairplayd y desencadena una operación de licencia mediante una app instalada.
El recuperador captura la salida del selector y el estado del keybag. Después combina ese estado con el UDID del dispositivo y las tablas de la herramienta para producir el archivo de 16 bytes.
El diseño supone que el sistema operativo del dispositivo mantiene privado el estado de fairplayd. Un dispositivo con jailbreak y acceso root no ofrece esa frontera de confianza. Esa es la debilidad de diseño: la credencial es de toda la cuenta, reutilizable y recuperable desde el espacio de usuario en un dispositivo comprometido.
¿Cómo se explota?
Un atacante que controla un iPhone con jailbreak y una cuenta de Apple que posee la app objetivo recupera una credencial y descifra sin conexión los IPA correspondientes. La herramienta pública sigue este camino:
- Prepare un iPhone con jailbreak en iOS 10 o posterior con acceso SSH root e instale al menos una app del App Store desde la cuenta objetivo.
- Compile el recuperador en un Mac con Xcode,
ldid,idevice_ideiproxy, y ejecutecredential-retrieval/retrieve.pycontra el dispositivo. - El recuperador coloca puntos de interrupción en
fairplayd, lanza una app instalada para desencadenar una operación de licencia, captura la salida del selector y el estado del keybag, y escribecredential.bin. - Obtenga el IPA objetivo de la misma cuenta de Apple.
- Ejecute
decrypt.pycon el IPA y la credencial. Analiza el comando de cifrado Mach-O, el registro SINF y la tabla SUPF, deriva la clave de trabajo y cada clave de página, descifra las páginas, borracryptidy escribe un IPA nuevo. - Vuelva a firmar la salida si debe instalarse. El descifrado borra el marcador de cifrado pero no crea una firma de código válida.
Nada en la ruta de descifrado contacta con Apple. La única interacción con el dispositivo es el paso de captura. El descifrador es Python puro y se ejecuta en macOS o Linux.
¿Cómo se desarrolla el ataque?
Un dispositivo con jailbreak observa fairplayd para recuperar la credencial de la cuenta, y la credencial desenvuelve la clave de cada app para que las páginas se descifren sin conexión.
reutilizada para cada app poseída"] D --> E["Desenvolvimiento de SINF priv a la clave de trabajo de la app"] E --> F["Derivación de claves de página desde los registros SUPF"] F --> G["Descifrado de páginas arm64 y borrado de cryptid"]
¿Qué puede hacer un atacante?
Un atacante con la credencial puede descifrar los IPA correspondientes que posee la cuenta de Apple, sin conexión y de forma repetida. Después puede leer o reempaquetar su código y sus recursos. El impacto es de confidencialidad y reempaquetado, no de ejecución remota de código.
Las condiciones forman parte del impacto:
- La app debe pertenecer a la cuenta de la credencial y coincidir con su tipo. El README dice que cada credencial funciona con las apps de la cuenta de Apple de la que proviene, y que una app Arcade necesita la credencial Arcade distinta.
- El IPA debe contener segmentos arm64 cifrados con un par SINF y SUPF compatible.
- El atacante necesita una copia del IPA.
- El reempaquetado para instalar necesita una identidad de firma. La herramienta no firma.
- El descifrado no elude la autenticación del servidor, la lógica de negocio ni App Attest. Esos controles siguen ejecutándose cuando la app reempaquetada llama a sus servidores.
Un IPA descifrado expone el código Swift y Objective-C, las cadenas, la configuración incrustada, los endpoints de API y cualquier clave o token que viajara en el binario. Eso acelera la investigación de vulnerabilidades y facilita el reempaquetado. Un atacante puede inyectar un framework o cambiar recursos, volver a firmar el bundle y distribuirlo fuera del App Store.
Un segundo proyecto público, UnfairPlay, recupera un modelo reutilizable de un Mac inscrito en lugar de un iPhone con jailbreak. Su README dice que un modelo descifra otros IPA personalizados de la misma inscripción y puede convertir un IPA de iOS en un diseño de macOS.
Eso baja la barrera de un teléfono con jailbreak a una cuenta del Mac App Store. El proyecto apareció el 25 de octubre de 2026, seis días después del primer commit de fairplay-decrypt.
UnfairPlay también advierte de que su salida conserva las licencias SC_Info y el archivo iTunesMetadata.plist de la entrada, que identifican la cuenta de la tienda. El operador debe eliminarlos de forma explícita. Un IPA descifrado compartido sin cuidado puede exponer la identidad de la cuenta además del código.
El 12 de noviembre de 2026, el repositorio fairplay-decrypt tenía más de 2,400 estrellas y 375 forks. El interés no es explotación: no se informa de ningún ataque con la herramienta en el proyecto ni en las fuentes revisadas.
Use la herramienta solo en apps que esté autorizado a analizar. El comando de descifrado describe su entrada como un IPA autorizado.
¿Por qué funciona la corrección?
No hay ninguna versión corregida que citar, así que nada en el proyecto cierra la debilidad de diseño. Una corrección tendría que cambiar la jerarquía de claves, no una función de análisis. Tres cambios elevarían el coste:
- Vincular la clave propia de la app a un secreto de hardware que el sistema operativo no pueda leer, como el Secure Enclave, y atestiguar el sistema antes de liberarla.
- Entregar una clave propia de la app y de la sesión desde un servidor que compruebe el dispositivo y la cuenta, en lugar de derivarla de una credencial de cuenta guardada en el dispositivo.
- Rotar el esquema de credenciales e invalidar las credenciales capturadas cuando se detecte abuso.
Ninguno de estos cambios es un parche de una línea, y cada uno sigue confiando en el dispositivo hasta cierto punto. Un sistema con jailbreak puede observar un demonio del espacio de usuario incluso cuando una clave está envuelta. En este caso, el DRM del lado del cliente no mantuvo el código confidencial frente a un propietario del dispositivo con acceso al kernel.
El proyecto sigue los cambios de Apple. Añadió la recuperación para iOS 10 a 12, la compatibilidad con páginas de 16 KB, SUPF versión 5, varios segmentos arm64 y credenciales de Apple Arcade. No se asigna ninguna CVE a fairplay-decrypt, y el proyecto no tiene ninguna versión que elimine la dependencia de la credencial de cuenta.
¿Cómo compruebo si estuve comprometido?
Una copia descifrada no deja rastro en sus servidores, así que busque versiones reempaquetadas y exposición de credenciales de cuenta. Para cada versión distribuida, busque estas pistas:
- Un
cryptidde 0 en una versión que debería estar cifrada. - Una firma de código cuyo TeamIdentifier no sea el suyo.
- Un identificador de bundle, un
Info.plisto unembedded.mobileprovisiondistinto del de su versión. - Frameworks inyectados o archivos
SC_Infoadicionales. - Distribución fuera del App Store o TestFlight.
Extraiga el binario principal y revíselo:
unzip -p Suspicious.ipa Payload/App.app/App > /tmp/App
otool -l /tmp/App | grep -A4 LC_ENCRYPTION_INFO_64
codesign -dv --verbose=4 /tmp/App
Un binario en claro con una firma de otro equipo es una pista sólida, no una prueba de descifrado. Un binario sin cifrar no prueba que la copia se haya descifrado.
En el servidor, revise los fallos de App Attest y DeviceCheck, las señales de dispositivo con jailbreak y los clientes de API con versiones inesperadas o cabeceras de integridad ausentes. También son pistas, no pruebas. El proyecto no publica indicadores de compromiso. El descifrado es una operación de archivo sin conexión que no llama a casa, así que un intento fallido puede no dejar rastro.
Cronología
- 2026-10-19: El repositorio
EthanArbuckle/fairplay-decryptrecibe su primer commit público. - 2026-10-22: El README confirma la compatibilidad con iOS 15.
- 2026-10-23: Un commit añade la recuperación de credenciales para iOS 10 a 12.
- 2026-10-25: Se crea el proyecto macOS
UnfairPlay. - 2026-10-30: El proyecto añade una licencia GPLv3 y la recuperación de credenciales de Apple Arcade.
- 2026-11-08: El último commit sustituye la captura de Arcade por la observación IOKit de FairPlay.
Preguntas frecuentes
¿Hay una CVE para fairplay-decrypt?
No. El proyecto es una herramienta de investigación, no una vulnerabilidad de producto con una versión corregida. NVD no devuelve ningún registro de FairPlay para el proyecto al 12 de noviembre de 2026, y el catálogo KEV de CISA 2026.11.10 no tiene ninguna entrada de FairPlay.
¿Necesita jailbreak?
Para fairplay-decrypt, sí en el momento de la captura. El recuperador necesita un iPhone con jailbreak y SSH root. El descifrado en sí se ejecuta en macOS o Linux sin el teléfono. El proyecto separado UnfairPlay usa un Mac inscrito en lugar de un iPhone con jailbreak.
¿Una credencial descifra todas las apps?
Descifra los IPA correspondientes de la cuenta de Apple de la credencial. Una credencial normal cubre las apps normales, y el README indica que las apps Arcade necesitan una credencial Arcade distinta. No descifra apps de otras cuentas ni el vídeo FairPlay Streaming.
¿La salida es instalable?
No tal cual. La herramienta borra cryptid pero no vuelve a firmar el binario. iOS exige una firma válida, así que la salida debe volver a firmarse con un perfil de aprovisionamiento antes de instalarla.
¿Qué apps y versiones de iOS cubre?
El recuperador indica iOS 10 o posterior. El descifrador admite segmentos Mach-O arm64, SUPF versiones 3 y 5, y registros SINF priv de 440 o 448 bytes. No procesa apps de solo 32 bits ni binarios sin cifrar.
¿Se explota en la naturaleza?
No. No se informa de ningún ataque con la herramienta en el proyecto ni en las fuentes revisadas al 12 de noviembre de 2026. No está en el catálogo KEV de CISA. Las cifras de estrellas y forks muestran interés, no explotación.
Referencias
- Repositorio
EthanArbuckle/fairplay-decrypt, README, con la credencial de 16 bytes, los formatos compatibles y el descifrado sin conexión: https://github.com/EthanArbuckle/fairplay-decrypt/blob/main/README.md (verificado el 12 de noviembre de 2026) core.pyen el commit d81d98b13656c9dbb340f04dd0838137278f44a5, la derivación SINF, SUPF y de claves de página: https://github.com/EthanArbuckle/fairplay-decrypt/blob/d81d98b13656c9dbb340f04dd0838137278f44a5/core.py (verificado el 12 de noviembre de 2026)decrypt.pyen el mismo commit, la entrada IPA y la ruta de salida: https://github.com/EthanArbuckle/fairplay-decrypt/blob/d81d98b13656c9dbb340f04dd0838137278f44a5/decrypt.py (verificado el 12 de noviembre de 2026)credential-retrieval/README.md, los requisitos del dispositivo con jailbreak, iOS 10 o posterior y la credencial de cuenta reutilizable: https://github.com/EthanArbuckle/fairplay-decrypt/blob/main/credential-retrieval/README.md (verificado el 12 de noviembre de 2026)credential-retrieval/credential/observer.c, los puntos de interrupción de hardware y el observador de FairPlay: https://github.com/EthanArbuckle/fairplay-decrypt/blob/main/credential-retrieval/credential/observer.c (verificado el 12 de noviembre de 2026)credential-retrieval/credential/credential.c, el selector, el keybag y la derivación de la credencial: https://github.com/EthanArbuckle/fairplay-decrypt/blob/main/credential-retrieval/credential/credential.c (verificado el 12 de noviembre de 2026)- Commit 5fdf16b48ea4a2a32950641aba23dd3063c34856, el primer commit público el 19 de octubre de 2026: https://github.com/EthanArbuckle/fairplay-decrypt/commit/5fdf16b48ea4a2a32950641aba23dd3063c34856 (verificado el 12 de noviembre de 2026)
- Commit 9e5aa3ea290d79c3320190004dc512e034d99484, la licencia GPLv3 el 30 de octubre de 2026: https://github.com/EthanArbuckle/fairplay-decrypt/commit/9e5aa3ea290d79c3320190004dc512e034d99484 (verificado el 12 de noviembre de 2026)
- Commit 8350383e2e9050f7a77197bf32545ddbef90b57c, la recuperación de credenciales de Apple Arcade el 30 de octubre de 2026: https://github.com/EthanArbuckle/fairplay-decrypt/commit/8350383e2e9050f7a77197bf32545ddbef90b57c (verificado el 12 de noviembre de 2026)
- Commit 5e35c7a, la compatibilidad con iOS 10 a 12 el 23 de octubre de 2026: https://github.com/EthanArbuckle/fairplay-decrypt/commit/5e35c7a (verificado el 12 de noviembre de 2026)
- Historial de commits de
EthanArbuckle/fairplay-decrypt, con los cambios para iOS 10 a 12, páginas de 16 KB, SUPF v5, varios segmentos y Arcade: https://github.com/EthanArbuckle/fairplay-decrypt/commits/main (verificado el 12 de noviembre de 2026) - Repositorio
DrWhax/unfairplay, README, la vía del Mac inscrito y el modelo reutilizable: https://github.com/DrWhax/unfairplay/blob/main/README.md (verificado el 12 de noviembre de 2026) - Página del repositorio
DrWhax/unfairplay, creada el 25 de octubre de 2026: https://github.com/DrWhax/unfairplay (verificado el 12 de noviembre de 2026) vnc0/fairplay-scinfo, documentación de los formatos SINF y SUPF y de las claves de página envueltas: https://github.com/vnc0/fairplay-scinfo (verificado el 12 de noviembre de 2026)- Apple,
loader.h, la estructuraLC_ENCRYPTION_INFO_64y el campocryptid: https://github.com/apple-oss-distributions/xnu/blob/main/EXTERNAL_HEADERS/mach-o/loader.h (verificado el 12 de noviembre de 2026) - CISA, catálogo Known Exploited Vulnerabilities en JSON, versión 2026.11.10, sin ninguna entrada de FairPlay: https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (verificado el 12 de noviembre de 2026)
- Búsqueda en NVD de FairPlay, sin ningún registro del proyecto al 12 de noviembre de 2026: https://nvd.nist.gov/vuln/search/results?query=fairplay&search_type=all (verificado el 12 de noviembre de 2026)
- Página del repositorio
EthanArbuckle/fairplay-decrypt, más de 2,400 estrellas y 375 forks el 12 de noviembre de 2026: https://github.com/EthanArbuckle/fairplay-decrypt (verificado el 12 de noviembre de 2026)