Com entra Pegasus al teu mòbil sense que cliquis res: tres portes a Android, WhatsApp i iOS
Arran del reconeixement que el CNI espanyol ha espiat exdiputats catalans, un fil tècnic desgrana pas a pas com un programari espia com Pegasus s'infiltra en un telèfon sense clicar cap enllaç ni instal·lar res: un error del binder a Android, una trucada de WhatsApp manipulada i un fals GIF a iOS.
Arran d'una conversa sobre com ho fa Pegasus per entrar en telèfons mòbils, i arran de la notícia que el CNI espanyol ha estat espiant exdiputats catalans, com han reconegut ells mateixos, val la pena explicar amb detall com un programari espia com Pegasus acaba dins d'un telèfon sense que la víctima cliqui res ni instal·li res. Aquí van tres portes d'entrada reals: una a Android, una via WhatsApp i una a iOS.
Comencem per Android. Android té lògicament un sistema de comunicació entre processos (IPC) dins el nucli. Hi actua com un controlador, s'hi fa referència com a binder ("lligador"). Cada procés existent com a resultat del que l'usuari fa al telèfon té una frontera que separa la seva memòria (userland) de la memòria del nucli. La víctima visita una pàgina web infectada. Infectada com? No se sap del cert. Era òbviament algun tipus de codi executable, segurament JavaScript, però els que van investigar això no tenen el detall exacte de què passava a la part de la web que l'iniciava. El que sí que se sap és què passava a partir d'aquí, quan el codi maliciós s'executava al telèfon.
Un cop el codi maliciós s'executa al navegador, es troba atrapat en un contenidor (no en pla Docker, vull dir un sandbox) de manera que s'aïllen processos com els del navegador web dins d'una capsa molt restrictiva. Es fa així precisament perquè el codi no pugui sortir de l'espai d'usuari (userland) cap a la resta del telèfon. Però fins i tot dins un contenidor, el navegador necessita comunicar-se amb el sistema operatiu. Com que aquesta comunicació és necessària perquè tot funcioni, el codi maliciós aprofita aquesta via de comunicació permesa per atacar directament el nucli.
Quan el navegador demana comunicar-se amb el sistema, el binder li assigna un fil d'execució (binder_thread) a la memòria del nucli i el posa en una cua d'espera. Per saber quan hi ha activitat en aquesta cua d'espera que calgui processar, el sistema empra un mecanisme de monitoratge: epoll. El codi maliciós des del navegador envia una ordre (BINDER_THREAD_EXIT) per forçar la destrucció d'aquest thread de cop. El nucli, fent el que "creu" que ha de fer, allibera aquella porció de memòria perquè pugui ser utilitzada per altres coses.
Per un error de programació del controlador del binder, quan s'alliberava la memòria d'aquell fil d'aquesta manera, no s'avisava l'epoll que deixés de mirar, així que continuava mirant si allà hi havia alguna cosa a processar. Ocorria així un dangling pointer: l'epoll anava a buscar a una adreça de memòria que el sistema considera buida i lliure per ser reescrita, i això permetia a l'atacant omplir la memòria que el sistema creia lliure amb les seves pròpies dades manipulades. És el que es coneix com a vulnerabilitat use-after-free.
L'atacant utilitza aquest dangling pointer per buscar i modificar una variable dins de l'estructura del seu propi procés al nucli d'Android: l'addr_limit, la frontera que li diu a Android a quines adreces de memòria pot accedir el navegador. Mitjançant l'error del binder, l'atacant pot sobreescriure aquest valor i posar-lo al màxim possible, de manera que ara el navegador pot accedir a un munt de llocs als quals no hauria de poder accedir prèviament. Ara ja té camí per recórrer per desactivar el sistema de confinament de SELinux i autodonar-se a si mateix els privilegis d'administrador màxim del sistema que pugui aconseguir.
I ara que ja no hi ha defenses pràcticament de cap mena, pot instal·lar el RAT, és a dir, l'eina per a control remot que formi part de l'ecosistema de Pegasus, des de la qual es pot dur a terme l'espionatge. Com que actua amb privilegis elevats a causa de totes les accions fetes en les passes anteriors, pot obtenir directament la base de dades de WhatsApp de la partició /data, interceptar trucades, activar el micròfon o la càmera, o el que sigui. Això sabem que va passar i que estava vinculat amb Pegasus perquè Google Project Zero ho va publicar. Avui això ja no és un dia zero: és CVE-2019-2215, és coneguda des del 3 d'octubre de 2019 i ja està resolta. Però explica, crec, un cas de com, sense clicar res ni instal·lar res, acaba dins el telèfon Pegasus.
Anem ara per un exemple en què s'usava WhatsApp com a base per a l'atac. Primer hi havia una trucada de veu de WhatsApp al número de l'objectiu. Aquesta trucada no es feia des d'un WhatsApp "normal", sinó manipulat de la banda del client. Un escenari plausible seria: els operadors de Pegasus feien servir un programari que es connectava als servidors de WhatsApp imitant el comportament d'un telèfon real per fer la trucada cap al número de la víctima, i controlaven ells el "WhatsApp" (aplicació) que ho feia.
Un cop el servidor de WhatsApp obria el canal de comunicació VoIP (veu sobre IP, les trucades per Internet), el programari de l'atacant injectava paquets SRTCP (Secure Real-time Transport Control Protocol) manipulats. Com que el servidor de WhatsApp actua com a intermediari i els paquets SRTCP serveixen originalment per controlar paràmetres com la qualitat o el retard de la trucada, el servidor no inspeccionava els paquets manipulats i els reenviava directament a l'aplicació de la víctima. Quan el WhatsApp de la víctima, aquest sí un WhatsApp normal descarregat de Google Play Store o Apple App Store, intentava processar aquests paquets anòmals, això era el que obria les portes del seu telèfon a la infecció.
Tècnicament, la porta s'obria per un error de programació en el WhatsApp "normal" (el de l'emissor estava manipulat, però el del receptor no) de desbordament de memòria intermèdia, o heap buffer overflow. Tot això passava automàticament durant el processament en segon pla del trànsit entrant. El desbordament s'activava mentre la trucada sonava, sense necessitat de respondre-la activament ni tocar cap botó de la pantalla. A partir d'aquest punt el procés és anàleg al ja explicat per a Android: s'obre la porta a instal·lar programari, i instal·laven programari espia i n'elevaven els privilegis. Ho va explicar el Financial Times. L'escalada de privilegis es feia amb altres vulnerabilitats diferents, que no són aquesta de WhatsApp en concret, perquè Pegasus fa això: combina vulnerabilitats diverses per al seu objectiu.
Per a iOS també tenen maneres d'entrar als mòbils. Una d'aquestes maneres es va batejar com a FORCEDENTRY. Anava així: primer, l'atacant enviava un missatge d'iMessage al telèfon de la víctima. I no calia que la víctima l'obrís. Sense que l'usuari l'obrís, l'aplicació intentava generar automàticament una previsualització del missatge en segon pla per mostrar-la a la pantalla. Aquest missatge tenia un GIF amb aparença inofensiva. En realitat, no era un GIF, sinó un document PDF (o PSD) camuflat que utilitzava un format de compressió d'imatges molt antic i obsolet, dels anys 90: JBIG2.
Quan el processador d'imatges que Apple usa en aquest context, CoreGraphics, intentava llegir aquest fitxer per mostrar la previsualització del GIF, es topava amb que en realitat era un JBIG2. JBIG2 funciona buscant formes que es repeteixen i desant-les en una llista per no haver-les de dibuixar cada cop. El processador d'imatges d'Apple havia de saber quanta memòria reservar per a la llista. Per estimar-ho, intentava llegir un nombre al fitxer que deia "hi ha X formes". L'atacant manipulava el fitxer en aquest aspecte per posar-hi un nombre molt alt, desmesuradament alt.
Quan l'iPhone multiplicava aquest nombre immens per calcular la memòria total, el resultat superava el límit màxim que podia comptar el sistema informàtic i es provocava un desbordament de nombre enter (integer overflow). Això feia que pensés que l'estimació era "virtualment zero" i reservava una memòria molt petita. Llavors l'atacant hi enviava moltes dades (desbordament de pila, o buffer overflow) i les dades de l'atacant desbordaven i sobreescrivien la memòria adjacent.
El format JBIG2 inclou operacions lògiques (AND, OR, XOR) que serveixen per dibuixar i superposar imatges; sempre és un problema que un format teòricament d'imatge contingui l'opció d'executar lògiques. Com que es desbordava la memòria, l'atacant podia fer que aquestes operacions s'apliquessin directament sobre la memòria de l'iPhone. Amb les opcions de lògiques que JBIG2 els permetia, muntaven un petit ordinador simulat, una "màquina virtual", que feia càlculs, cercava dades a la memòria i desactivava les defenses de l'iPhone des de dins.
Ho sabem, i tenim la vinculació amb Pegasus, també gràcies a Google Project Zero, un equip d'analistes de seguretat de Google que passa el dia intentant trobar i corregir vulnerabilitats de dia zero a tot Internet per protegir els usuaris. Les vulnerabilitats del dia zero són les que s'exploten quan encara ningú sabia que existien. Cap d'aquests tres casos requereix que la víctima cliqui un enllaç, obri un fitxer ni instal·li res: és la definició mateixa d'un atac zero-click, i és exactament el tipus d'eina amb què s'ha espiat gent aquí.