Описание
RabbitMQ direct reply-to: forged suffix fanout causes quadratic mailbox memory
Summary
RabbitMQ direct reply-to addresses have the form:
When resolving a destination, RabbitMQ decodes and validates the PID but discards the capability-key suffix. An attacker who obtains their own valid direct reply-to address can create many distinct routing keys that preserve the encoded PID and replace only the suffix.
A single message can carry these names through the AMQP CC header. RabbitMQ
creates one volatile target per distinct name and sends one cast per target to
the same channel/session PID. Every cast retains a copy of the message's full
O(N) routing-key structure, producing N × O(N) = O(N²) mailbox memory.
The final capability-key check happens only after each cast reaches the target mailbox, too late to prevent amplification.
Preconditions
- The attacker has an authenticated AMQP account.
- The account can write to the default exchange.
- The attacker activates direct reply-to and obtains its own generated reply address. No victim address or cross-user information leak is required.
These are ordinary application permissions. No plugin or administrator role is required.
Root cause
1. The suffix is parsed but never validated
Only the encoded PID contributes to the returned target.
2. Distinct forged names become distinct targets
The default exchange resolves each CC routing key independently through
rabbit_db_queue:get_targets/1. Names are different as binaries, so they are
not deduplicated even when they decode to the same PID.
3. Every target receives the full message structure
rabbit_queue_type:deliver0/4 groups the volatile targets but retains the
message carrying all routing keys. rabbit_volatile_queue:deliver/3 then sends
one queue_event cast per target.
The target channel eventually notices the wrong capability key and drops each event, but every event has already occupied mailbox memory.
Basic Python proof of concept
Attached at the end of file: dos-poc.py
Requirements:
- Python 3 with
pika(python3 -m pip install pika). - An already-running RabbitMQ server.
- An ordinary account with configure/read/write permission in one vhost.
- No RabbitMQ plugin or non-default server configuration.
Run:
The PoC uses only the AMQP network interface. It registers a real direct
reply-to consumer, obtains the broker-expanded address through a normal RPC
request, replaces the capability suffix with 800 distinct values, and sends
them in one CC header. Monitor RabbitMQ process memory while increasing
--count or --repeats.
--count 800 --repeats 1 is the bounded validation setting. Larger values can
terminate the broker.
Successful delivery of the attack prints:
Independent Docker validation evidence
The attached network-only PoC does not require Docker or broker shell access. For deterministic measurement, the finding was separately validated on stock RabbitMQ 4.3.4 by temporarily suspending only the attacker's own broker channel while sampling its mailbox:
Doubling the number of forged suffixes increases memory by approximately four,
which directly demonstrates quadratic scaling. The N=800 message fits within
normal AMQP frame limits yet consumes approximately 118.5 MB in one target
mailbox.
Impact
- A low-privilege tenant can target its own channel/session and consume shared broker memory, so no victim PID discovery is necessary.
- Several bounded-size publishes across channels can exhaust a broker node.
- Memory alarms do not prevent a single in-progress fanout from enqueuing the complete burst.
- The issue affects a core feature and can impact other vhosts and tenants on the same node.
Recommended remediation
- Validate the complete direct reply-to capability, including the random key, before creating a volatile target or sending a cast.
- Deduplicate resolved volatile targets by validated PID and capability.
- Reject or bound the number and aggregate encoded size of CC/x-cc routing keys.
- Charge flow credit for fanout work rather than only once per source message.
- Add a regression asserting linear mailbox memory as CC count grows.
Пакеты
rabbitmq
>= 4.2.0, < 4.2.10
4.2.10
rabbitmq
>= 4.3.0, < 4.3.5
4.3.5
6 Medium
CVSS4
Дефекты
6 Medium
CVSS4