Skip to content

Commit 50e2eb8

Browse files
authored
Merge pull request #1650 from HackTricks-wiki/update_Careless_Whisper__Exploiting_Silent_Delivery_Recei_20251208_125547
Careless Whisper Exploiting Silent Delivery Receipts to Moni...
2 parents 6a3dfac + 5497ad4 commit 50e2eb8

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
- [Web Requests](generic-methodologies-and-resources/python/web-requests.md)
8686
- [Bruteforce hash (few chars)](generic-methodologies-and-resources/python/bruteforce-hash-few-chars.md)
8787
- [Basic Python](generic-methodologies-and-resources/python/basic-python.md)
88+
- [Side Channel Attacks On Messaging Protocols](generic-methodologies-and-resources/side-channel-attacks-on-messaging-protocols.md)
8889
- [Threat Modeling](generic-methodologies-and-resources/threat-modeling.md)
8990
- [Blockchain & Crypto](blockchain/blockchain-and-crypto-currencies/README.md)
9091
- [Defi/AMM Hook Precision](blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md)

src/generic-methodologies-and-resources/pentesting-methodology.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,12 @@ Check also the page about [**NTLM**](../windows-hardening/ntlm/index.html), it c
148148

149149
#### [**Basic Python**](python/index.html)
150150

151+
#### Side-Channel Attacks on Messaging Protocols
152+
153+
{{#ref}}
154+
side-channel-attacks-on-messaging-protocols.md
155+
{{#endref}}
156+
151157
#### **Crypto tricks**
152158

153159
- [**ECB**](../crypto/symmetric/README.md#electronic-code-book-ecb)
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Delivery Receipt Side-Channel Attacks in E2EE Messengers
2+
3+
{{#include ../banners/hacktricks-training.md}}
4+
5+
Delivery receipts are mandatory in modern end-to-end encrypted (E2EE) messengers because clients need to know when a ciphertext was decrypted so they can discard ratcheting state and ephemeral keys. The server forwards opaque blobs, so device acknowledgements (double checkmarks) are emitted by the recipient after successful decryption. Measuring the round-trip time (RTT) between an attacker-triggered action and the corresponding delivery receipt exposes a high-resolution timing channel that leaks device state, online presence, and can be abused for covert DoS. Multi-device "client-fanout" deployments amplify the leakage because every registered device decrypts the probe and returns its own receipt.
6+
7+
## Delivery receipt sources vs. user-visible signals
8+
9+
Choose message types that always emit a delivery receipt but do not surface UI artifacts on the victim. The table below summarises the empirically confirmed behaviour:
10+
11+
| Messenger | Action | Delivery receipt | Victim notification | Notes |
12+
|-----------|--------|------------------|---------------------|-------|
13+
| **WhatsApp** | Text message ||| Always noisy → only useful to bootstrap state. |
14+
| | Reaction || ◐ (only if reacting to victim message) | Self-reactions and removals stay silent. |
15+
| | Edit || Platform-dependent silent push | Edit window ≈20 min; still ack’d after expiry. |
16+
| | Delete for everyone ||| UI allows ~60 h, but later packets still ack’d. |
17+
| **Signal** | Text message ||| Same limitations as WhatsApp. |
18+
| | Reaction ||| Self-reactions invisible to victim. |
19+
| | Edit/Delete ||| Server enforces ~48 h window, allows up to 10 edits, but late packets still ack’d. |
20+
| **Threema** | Text message ||| Multi-device receipts are aggregated, so only one RTT per probe becomes visible. |
21+
22+
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.
23+
24+
## Attacker goals and models
25+
26+
* **G1 – Device fingerprinting:** Count how many receipts arrive per probe, cluster RTTs to infer OS/client (Android vs iOS vs desktop), and watch online/offline transitions.
27+
* **G2 – Behavioural monitoring:** Treat the high-frequency RTT series (≈1 Hz is stable) as a time-series and infer screen on/off, app foreground/background, commuting vs working hours, etc.
28+
* **G3 – Resource exhaustion:** Keep radios/CPUs of every victim device awake by sending never-ending silent probes, draining battery/data and degrading VoIP/RTC quality.
29+
30+
Two threat actors are sufficient to describe the abuse surface:
31+
32+
1. **Creepy companion:** already shares a chat with the victim and abuses self-reactions, reaction removals, or repeated edits/deletes tied to existing message IDs.
33+
2. **Spooky stranger:** registers a burner account and sends reactions referencing message IDs that never existed in the local conversation; WhatsApp and Signal still decrypt and acknowledge them even though the UI discards the state change, so no prior conversation is required.
34+
35+
## Tooling for raw protocol access
36+
37+
Rely on clients that expose the underlying E2EE protocol so you can craft packets outside UI constraints, specify arbitrary `message_id`s, and log precise timestamps:
38+
39+
* **WhatsApp:** [whatsmeow](https://github.com/tulir/whatsmeow) (Go, WhatsApp Web protocol) or [Cobalt](https://github.com/Auties00/Cobalt) (mobile-oriented) let you emit raw `ReactionMessage`, `ProtocolMessage` (edit/delete), and `Receipt` frames while keeping the double-ratchet state in sync.
40+
* **Signal:** [signal-cli](https://github.com/AsamK/signal-cli) combined with [libsignal-service-java](https://github.com/signalapp/libsignal-service-java) exposes every message type via CLI/API. Example self-reaction toggle:
41+
```bash
42+
signal-cli -u +12025550100 sendReaction --target +12025550123 \
43+
--message-timestamp 1712345678901 --emoji "👍"
44+
signal-cli -u +12025550100 sendReaction --target +12025550123 \
45+
--message-timestamp 1712345678901 --remove # encodes empty emoji
46+
```
47+
* **Threema:** Source of the Android client documents how delivery receipts are consolidated before they leave the device, explaining why the side channel has negligible bandwidth there.
48+
49+
When custom tooling is unavailable, you can still trigger silent actions from WhatsApp Web or Signal Desktop and sniff the encrypted websocket/WebRTC channel, but raw APIs remove UI delays and allow invalid operations.
50+
51+
## Creepy companion: silent sampling loop
52+
53+
1. Pick any historical message you authored in the chat so the victim never sees "reaction" balloons change.
54+
2. Alternate between a visible emoji and an empty reaction payload (encoded as `""` in WhatsApp protobufs or `--remove` in signal-cli). Each transmission yields a device ack despite no UI delta for the victim.
55+
3. Timestamp the send time and every delivery receipt arrival. A 1 Hz loop such as the following gives per-device RTT traces indefinitely:
56+
```python
57+
while True:
58+
send_reaction(msg_id, "👍")
59+
log_receipts()
60+
send_reaction(msg_id, "") # removal
61+
log_receipts()
62+
time.sleep(0.5)
63+
```
64+
4. Because WhatsApp/Signal accept unlimited reaction updates, the attacker never needs to post new chat content or worry about edit windows.
65+
66+
## Spooky stranger: probing arbitrary phone numbers
67+
68+
1. Register a fresh WhatsApp/Signal account and fetch the public identity keys for the target number (done automatically during session setup).
69+
2. Craft a reaction/edit/delete packet that references a random `message_id` never seen by either party (WhatsApp accepts arbitrary `key.id` GUIDs; Signal uses millisecond timestamps).
70+
3. Send the packet even though no thread exists. The victim devices decrypt it, fail to match the base message, discard the state change, but still acknowledge the incoming ciphertext, sending device receipts back to the attacker.
71+
4. Repeat continuously to build RTT series without ever appearing in the victim’s chat list.
72+
73+
## Recycling edits and deletes as covert triggers
74+
75+
* **Repeated deletes:** After a message is deleted-for-everyone once, further delete packets referencing the same `message_id` have no UI effect but every device still decrypts and acknowledges them.
76+
* **Out-of-window operations:** WhatsApp enforces ~60 h delete / ~20 min edit windows in the UI; Signal enforces ~48 h. Crafted protocol messages outside these windows are silently ignored on the victim device yet receipts are transmitted, so attackers can probe indefinitely long after the conversation ended.
77+
* **Invalid payloads:** Malformed edit bodies or deletes referencing already purged messages elicit the same behaviour—decryption plus receipt, zero user-visible artefacts.
78+
79+
## Multi-device amplification & fingerprinting
80+
81+
* Each associated device (phone, desktop app, browser companion) decrypts the probe independently and returns its own ack. Counting receipts per probe reveals the exact device count.
82+
* If a device is offline, its receipt is queued and emitted upon reconnection. Gaps therefore leak online/offline cycles and even commuting schedules (e.g., desktop receipts stop during travel).
83+
* RTT distributions differ by platform due to OS power management and push wakeups. Cluster RTTs (e.g., k-means on median/variance features) to label “Android handset", “iOS handset", “Electron desktop", etc.
84+
* Because the sender must retrieve the recipient’s key inventory before encrypting, the attacker can also watch when new devices are paired; a sudden increase in device count or new RTT cluster is a strong indicator.
85+
86+
## Behaviour inference from RTT traces
87+
88+
1. Sample at ≥1 Hz to capture OS scheduling effects. With WhatsApp on iOS, <1 s RTTs strongly correlate with screen-on/foreground, >1 s with screen-off/background throttling.
89+
2. Build simple classifiers (thresholding or two-cluster k-means) that label each RTT as "active" or "idle". Aggregate labels into streaks to derive bedtimes, commutes, work hours, or when the desktop companion is active.
90+
3. Correlate simultaneous probes towards every device to see when users switch from mobile to desktop, when companions go offline, and whether the app is rate limited by push vs persistent socket.
91+
92+
## Stealthy resource exhaustion
93+
94+
Because every silent probe must be decrypted and acknowledged, continuously sending reaction toggles, invalid edits, or delete-for-everyone packets creates an application-layer DoS:
95+
96+
* Forces the radio/modem to transmit/receive every second → noticeable battery drain, especially on idle handsets.
97+
* Generates unmetered upstream/downstream traffic that consumes mobile data plans while blending into TLS/WebSocket noise.
98+
* Occupies crypto threads and introduces jitter in latency-sensitive features (VoIP, video calls) even though the user never sees notifications.
99+
100+
## References
101+
102+
- [Careless Whisper: Exploiting Silent Delivery Receipts to Monitor Users on Mobile Instant Messengers](https://arxiv.org/html/2411.11194v4)
103+
- [whatsmeow](https://github.com/tulir/whatsmeow)
104+
- [Cobalt](https://github.com/Auties00/Cobalt)
105+
- [signal-cli](https://github.com/AsamK/signal-cli)
106+
- [libsignal-service-java](https://github.com/signalapp/libsignal-service-java)
107+
108+
{{#include ../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)