# Tor onion service INTRODUCE2 invalid-MAC cells permanently grow service replay cache

Tor onion service inserts unauthenticated INTRODUCE2 encrypted sections into a non-expiring replay cache before MAC verification, allowing unbounded memory growth.

- Payout: hidden
- Severity: low
- Program: Tor
- Found by: geeknik
- Disclosed: 2026-09-10
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/3709703
- Library page: https://bugbountylibrary.com/r/h1%3A3709703
- Tags: area:devices domain:network impact:dos kind:bounty platform:hackerone sev:low tech:linux technique:source-review vuln:dos

**Target:** Tor onion service INTRODUCE2 handling / intro-point replay cache
**Root cause:** hs_cell_parse_introduce2() adds the attacker-controlled encrypted section to the per-introduction-point replay cache (created with replaycache_new(0,0), no expiration) before verifying the INTRODUCE2 MAC; invalid cells also skip introduce2_count++ so rotation never triggers.
**Steps:**
1. Obtain a public v3 onion-service descriptor and its advertised introduction points.
2. Build a legitimate INTRODUCE1 payload via hs_circ_send_introduce1().
3. Mutate only the final MAC byte to preserve trunnel framing but guarantee MAC failure.
4. Send unique invalid-MAC INTRODUCE1 cells over many fresh introduction circuits.
5. Intro point forwards them as INTRODUCE2; service inserts each unique encrypted section into ip->replay_cache before MAC check.
6. Observe digest256map_size(ip->replay_cache->digests_seen) grow while ip->introduce2_count stays 0.
**How found:** Code reading of hs_cell_parse_introduce2() revealed replaycache_add_test_and_elapsed() runs before get_introduce2_keys_and_verify_mac(); noting replaycache_new(0,0) never scrubs and introduce2_count++ only happens on success, they hypothesized unauthenticated permanent cache growth and confirmed with an in-tree regression test.
**Exploitation:** Attacker creates many introduction circuits (one INTRODUCE1 per circuit) and sends unique invalid-MAC INTRODUCE1 cells; each becomes a permanent replay-cache entry on the service, accumulating ~64-96 bytes per cell until memory pressure/OOM over the 18-24h intro-point lifetime.
**Escalation:** Sustained or parallel circuit creation raises accumulation to tens-to-hundreds of MB RSS; CVSS A:H defensible if OOM is reached.
**Insight:** When auditing replay/negative caches, check whether entries are inserted before authentication and whether the cache has an expiration horizon; also verify that failed-auth paths still advance any rotation/resource counters, otherwise unauthenticated data bypasses both eviction and accounting.
