Delivery Receipt Side-Channel Attacks in E2EE Messengers

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Квитанції про доставку (delivery receipts) є обов’язковими в сучасних end-to-end encrypted (E2EE) месенджерах, оскільки клієнтам потрібно знати, коли ciphertext було розшифровано, щоб вони могли видаляти ratcheting state та ephemeral keys. Сервер пересилає непрозорі блоґи, тож підтвердження на пристрої отримувача (double checkmarks) відправляються після успішної дешифрації. Вимірювання round-trip time (RTT) між дією, ініційованою атакуючим, і відповідною квитанцією про доставку відкриває високоточний таймінг-канал, який leaks стан пристрою, online presence і може бути використаний для covert DoS. Розгортання з кількома пристроями (“client-fanout”) підсилюють витік, тому що кожен зареєстрований пристрій дешифрує probe і повертає власну квитанцію.

Delivery receipt sources vs. user-visible signals

Вибирайте типи повідомлень, які завжди генерують квитанцію про доставку, але не створюють UI-артефактів у жертви. Наведена нижче таблиця узагальнює експериментально підтверджену поведінку:

MessengerActionDelivery receiptVictim notificationNotes
WhatsAppText messageAlways noisy → only useful to bootstrap state.
Reaction◐ (only if reacting to victim message)Self-reactions and removals stay silent.
EditPlatform-dependent silent pushEdit window ≈20 min; still ack’d after expiry.
Delete for everyoneUI allows ~60 h, but later packets still ack’d.
SignalText messageSame limitations as WhatsApp.
ReactionSelf-reactions invisible to victim.
Edit/DeleteServer enforces ~48 h window, allows up to 10 edits, but late packets still ack’d.
ThreemaText messageMulti-device receipts are aggregated, so only one RTT per probe becomes visible.

Legend: ● = always, ◐ = conditional, ○ = never. Platform-dependent UI behaviour is noted inline. Disable read receipts if needed, but delivery receipts cannot be turned off in WhatsApp or Signal.

Attacker goals and models

  • G1 – Device fingerprinting: Рахувати, скільки квитанцій приходить на один probe, кластеризувати RTT, щоб визначити OS/client (Android vs iOS vs desktop), і відстежувати переходи online/offline.
  • G2 – Behavioural monitoring: Розглядати високочастотну послідовність RTT (≈1 Hz є стабільною) як time-series і виводити screen on/off, app foreground/background, години поїздок vs роботи тощо.
  • G3 – Resource exhaustion: Тримати радіо/CPU кожного пристрою жертви активними, надсилаючи нескінченні silent probes, виснажуючи батарею/дані і погіршуючи якість VoIP/RTC.

Двох threat actors достатньо, щоб описати площу зловживання:

  1. Creepy companion: вже знаходиться в одному чаті з жертвою і зловживає self-reactions, reaction removals або повторюваними edits/deletes, прив’язаними до існуючих message ID.
  2. Spooky stranger: реєструє одноразовий акаунт і надсилає reactions, що посилаються на message ID, які ніколи не існували в локальній бесіді; WhatsApp і Signal все одно дешифрують і підтверджують їх, навіть якщо UI відкидає зміну стану, тож попередня розмова не потрібна.

Tooling for raw protocol access

Спирайтеся на клієнти, що відкривають underlying E2EE protocol, щоб можна було створювати пакети поза UI-обмеженнями, задавати довільні message_id і логувати точні timestamps:

  • WhatsApp: whatsmeow (Go, WhatsApp Web protocol) або Cobalt (орієнтований на mobile) дозволяють відправляти raw ReactionMessage, ProtocolMessage (edit/delete) та Receipt frames, зберігаючи double-ratchet state в синхроні.
  • Signal: signal-cli у поєднанні з libsignal-service-java відкривають усі типи повідомлень через CLI/API. Приклад перемикання self-reaction:
signal-cli -u +12025550100 sendReaction --target +12025550123 \
--message-timestamp 1712345678901 --emoji "👍"
signal-cli -u +12025550100 sendReaction --target +12025550123 \
--message-timestamp 1712345678901 --remove  # encodes empty emoji
  • Threema: Вихідний код Android-клієнта документує, як delivery receipts агрегуються перед виходом із пристрою, пояснюючи, чому side channel там має незначну пропускну здатність.

Коли кастомні інструменти недоступні, можна також запускати silent actions з WhatsApp Web або Signal Desktop і сніффити зашифрований websocket/WebRTC канал, але raw APIs прибирають UI-затримки і дозволяють виконувати некоректні операції.

Creepy companion: silent sampling loop

  1. Виберіть будь-яке історичне повідомлення, яке ви відправляли в чаті, щоб жертва ніколи не бачила зміну “reaction” балонів.
  2. Чергуйте видимий emoji і empty reaction payload (закодований як "" у WhatsApp protobufs або --remove у signal-cli). Кожна передача дає device ack, незважаючи на відсутність UI-дельти для жертви.
  3. Таймстампіть час відправки і кожне надходження delivery receipt. Цикл 1 Hz, наприклад такий, дає RTT-траси для кожного пристрою безкінечно:
while True:
send_reaction(msg_id, "👍")
log_receipts()
send_reaction(msg_id, "")  # removal
log_receipts()
time.sleep(0.5)
  1. Оскільки WhatsApp/Signal приймають необмежені оновлення реакцій, атакуючому ніколи не потрібно публікувати новий контент у чаті або турбуватися про edit windows.

Spooky stranger: probing arbitrary phone numbers

  1. Зареєструйте новий WhatsApp/Signal акаунт і отримаєте public identity keys для цільового номера (відбувається автоматично під час налаштування сесії).
  2. Сформуйте reaction/edit/delete пакет, що посилається на випадковий message_id, який ніколи не бачили обидві сторони (WhatsApp приймає довільні key.id GUID; Signal використовує millisecond timestamps).
  3. Надішліть пакет, навіть якщо thread не існує. Пристрої жертви дешифрують його, не можуть співставити з базовим повідомленням, відкидають зміну стану, але все одно acknowledge вхідний ciphertext, відправляючи device receipts назад атакуючому.
  4. Повторюйте безперервно, щоб побудувати RTT-послідовності, не з’являючись в чат-листі жертви.

Recycling edits and deletes as covert triggers

  • Повторні видалення: Після того, як повідомлення було deleted-for-everyone один раз, подальші delete packets, що посилаються на той самий message_id, не мають UI-ефекту, але кожен пристрій все одно дешифрує й підтверджує їх.
  • Операції поза вікном: WhatsApp накладає ~60 h для delete / ~20 min для edit у UI; Signal накладає ~48 h. Згенеровані protocol messages поза цими вікнами на пристрої жертви ігноруються без повідомлення, але receipts все одно передаються, тож атакувальники можуть probe безстроково після закінчення розмови.
  • Невірні payloads: Пошкоджені edit bodies або deletes, що посилаються на вже видалені повідомлення, викликають ту ж поведінку — дешифрування плюс receipt, нуль видимих артефактів для користувача.

Multi-device amplification & fingerprinting

  • Кожен пов’язаний пристрій (телефон, desktop app, browser companion) дешифрує probe незалежно і повертає власний ack. Підрахунок receipts за probe виявляє точну кількість пристроїв.
  • Якщо пристрій офлайн, його receipt ставиться в чергу і відправляється при повторному підключенні. Gaps therefore leak online/offline cycles і навіть розклад поїздок (наприклад, desktop receipts зникають під час подорожей).
  • Розподіли RTT відрізняються за платформами через OS power management і механізми push wakeups. Кластеризуйте RTT (наприклад, k-means по median/variance ознаках), щоб позначити “Android handset“, “iOS handset“, “Electron desktop“ тощо.
  • Оскільки sender повинен отримати recipient’s key inventory перед шифруванням, атакуючий також може спостерігати, коли додаються нові пристрої; раптове збільшення кількості пристроїв або новий RTT-кластер є сильним індикатором.

Behaviour inference from RTT traces

  1. Збирайте вибірки при ≥1 Hz, щоб захопити ефекти планування ОС. Для WhatsApp на iOS RTT <1 s сильно корелює з screen-on/foreground, >1 s — з screen-off/background throttling.
  2. Побудуйте прості класифікатори (thresholding або two-cluster k-means), що відмічають кожен RTT як “active” або “idle”. Агрегуйте мітки в послідовності, щоб вивести bedtimes, commutes, робочі години або коли активний desktop companion.
  3. Корелюйте одночасні probe до всіх пристроїв, щоб бачити, коли користувачі переходять з мобільного на десктоп, коли companions відключаються і чи обмежується додаток rate limiting через push vs persistent socket.

Stealthy resource exhaustion

Оскільки кожен silent probe має бути дешифрований і підтверджений, безперервне надсилання toggle реакцій, invalid edits або delete-for-everyone пакетів створює application-layer DoS:

  • Примушує радіо/модем передавати/приймати кожну секунду → помітне витрачання батареї, особливо на idle handsets.
  • Генерує немаркірований upstream/downstream трафік, що споживає мобільні data plans, маскуючись під TLS/WebSocket шум.
  • Займає crypto threads і додає jitter у latency-sensitive функції (VoIP, відеодзвінки), навіть якщо користувач ніколи не бачить повідомлень.

References

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks