Описание
Shovel Management Atom Exhaustion Allows Persistent Broker-Wide Denial of Service
Summary
RabbitMQ 4.3.1 with rabbitmq_shovel and rabbitmq_shovel_management enabled accepts Shovel runtime parameter values from a management user with the policymaker tag. Several values in the Shovel parameter parser are converted to Erlang atoms with rabbit_data_coercion:to_atom/1 or equivalent atom creation functions before they are safely bounded or checked against a fixed allowlist.
Erlang atoms are global to the VM and are not garbage collected. A user who can create Shovel parameters can therefore permanently consume entries in the node-wide atom table. In the tested lab this could crash or wedge the RabbitMQ node in about 64 seconds. A stronger variant stores malicious Shovel parameters durably, so a later broker restart reparses them and recreates the atom pressure without any live attacker connection.
This is an authenticated availability issue. It is not RCE and it is not unauthenticated. The security boundary issue is that a privilege normally delegated per vhost can exhaust a global Erlang VM resource and take down the whole node, including other vhosts.
Affected Version
Tested affected version: RabbitMQ 4.3.1.
Tested image: rabbitmq:4.3.1-management.
Tested source tag: v4.3.1.
Tested source commit: 49decca35e59d2cb774e5abd76412cee721308a5.
Required plugins:
Severity
Suggested severity: High, with a Critical argument for deployments that delegate policymaker to tenant or application administrators.
Suggested CVSS 3.1 baseline: AV:N/AC:L/PR:H/UI:N/S:C/C:N/I:N/A:H, score 7.2.
If the vendor considers a vhost-scoped policymaker account to be a low-privileged delegated tenant role, the vector can be argued as AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H, score 9.6. The integrity impact in that variant comes from the durable metadata poisoning that can prevent normal restart recovery until the malicious stored runtime parameters are removed offline.
Prerequisites
The attacker needs:
- Network access to the RabbitMQ Management HTTP API.
- Valid credentials for a user with the
managementandpolicymakertags. - Permission to set Shovel runtime parameters on at least one vhost.
rabbitmq_shovelandrabbitmq_shovel_managementenabled.
The attacker does not need administrator privileges, shell access, AMQP publish permission, or access to other vhosts.
Root Cause
The vulnerable code creates Erlang atoms from Shovel runtime parameter input.
In deps/rabbitmq_shovel/src/rabbit_shovel_parameters.erl, protocol fields from the Shovel definition are converted with rabbit_data_coercion:to_atom/1:
In deps/rabbitmq_shovel/src/rabbit_amqp10_shovel.erl, AMQP 1.0 destination properties are converted to atoms:
These atom creations are reachable from the management API path that sets a Shovel runtime parameter. The dest-properties variant is especially strong because one accepted HTTP request can contain thousands of unique map keys, causing thousands of permanent atom creations in a single request.
The persistence variant is caused by the worker startup path. In deps/rabbitmq_shovel/src/rabbit_shovel_worker.erl, stored Shovel parameters are parsed when dynamic workers start:
Since Shovel runtime parameters are stored durably, malicious parameter values can be reparsed after restart. Restarting the broker resets the atom table, but the stored parameters can recreate the atom pressure during boot.
Verification
Lab:
Safe verification was performed with the attached PoC using only three Shovel parameters:
Observed result:
The important property is that deleting the runtime parameters does not reclaim the created atoms. This matches Erlang VM behavior: atoms are not garbage collected.
Destructive verification was performed separately with a high-volume probe in the lab. The probe sent Shovel parameters with 20,000 unique dest-properties keys per request using four concurrent workers.
Observed trajectory:
The broker log ended with:
After this point rabbitmq-diagnostics -q ping failed and the broker process was unavailable for all vhosts on the node.
Restart persistence was also verified. After storing Shovel parameters containing many unique dest-properties keys, restarting the broker caused the Shovel worker startup path to reparse the stored parameters and recreate the atom delta without another attacker request.
Observed restart persistence sample:
Impact
An authenticated delegated user can exhaust a node-wide, non-garbage-collected Erlang VM resource. The result is complete RabbitMQ node unavailability. The impact is not limited to the attacker's vhost because the atom table is global to the Erlang VM.
The persistent stored-parameter variant can make a normal restart insufficient. If enough malicious Shovel parameters are stored, the broker can hit atom exhaustion during startup. Recovery then requires operator intervention against the stored metadata, such as disabling Shovel offline, deleting the malicious runtime parameters, or in the worst case resetting the metadata database. A plain process restart may repeat the crash.
Proof of Concept
The attached poc_shovel_atom_exhaustion.py defaults to a safe low-count run. It records atom count before and after creating Shovel parameters and then deletes the parameters.
Example safe command:
The script also contains a destructive mode for controlled lab use:
Do not run the destructive mode against a production broker.
Remediation
Do not create new Erlang atoms from user-controlled Shovel runtime parameter input.
Recommended fixes:
- Replace
to_atom/1,list_to_atom/1, andbinary_to_atom/1on user-controlled values with allowlist validation followed by existing atoms only. - For
src-protocolanddest-protocol, compare the binary value against the fixed supported protocol set before conversion. - For AMQP 1.0
dest-properties, keep keys as binaries or validate them against a finite registry. Do not intern arbitrary property names. - Enforce a small maximum count and maximum byte size for
dest-properties. - On startup, reject or quarantine stored Shovel parameters whose map sizes exceed the new limits.
- Consider documenting that
policymakercan affect node-wide resources when plugins parse runtime parameters.
Responsible Disclosure By
Trung Nguyen (@everping) of CyStack.
Пакеты
rabbitmq
>= 4.3.0, < 4.3.3
4.3.3
rabbitmq
>= 4.2.0, < 4.2.9
4.2.9