Логотип exploitDog
Консоль
Логотип exploitDog

exploitDog

github логотип

GHSA-8mpg-qw9r-m5cr

Опубликовано: 23 июл. 2026
Источник: github
Github: Не прошло ревью
CVSS4: 5.9

Описание

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:

rabbitmq_management rabbitmq_shovel rabbitmq_shovel_management

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 management and policymaker tags.
  • Permission to set Shovel runtime parameters on at least one vhost.
  • rabbitmq_shovel and rabbitmq_shovel_management enabled.

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:

src_protocol(Def) when is_list(Def) -> case pget(<<"src-protocol">>, Def, <<"amqp091">>) of SrcProtocol when is_binary(SrcProtocol) -> rabbit_data_coercion:to_atom(SrcProtocol); SrcProtocol -> SrcProtocol end. dest_protocol(Def) when is_list(Def) -> case pget(<<"dest-protocol">>, Def, <<"amqp091">>) of DstProtocol when is_binary(DstProtocol) -> rabbit_data_coercion:to_atom(DstProtocol); DstProtocol -> DstProtocol end.

In deps/rabbitmq_shovel/src/rabbit_amqp10_shovel.erl, AMQP 1.0 destination properties are converted to atoms:

Converted = maps:from_list([{rabbit_data_coercion:to_atom(K), V} || {K, V} <- maps:to_list(Properties)])

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:

{ok, Mod} = rabbit_registry:lookup_module(runtime_parameter, shovel), {ok, Conf} = Mod:parse(Name, ClusterName, Config0)

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

poc_shovel_atom_exhaustion.py

Lab:

Container: rabbitmq431-lab Management API: http://127.0.0.1:35673 Admin: admin / RabbitLab123! Delegated user: pol_user / Low123! Delegated user tags: policymaker, management RabbitMQ source: v4.3.1, commit 49decca35e59d2cb774e5abd76412cee721308a5

Safe verification was performed with the attached PoC using only three Shovel parameters:

python .\poc_shovel_atom_exhaustion.py --url http://127.0.0.1:35673 --user pol_user --password 'Low123!' --container rabbitmq431-lab --count 3

Observed result:

atom_count_before=77668 0: status=201 1: status=201 2: status=201 atom_count_after=77671 atom_count_delta=3 atom_count_after_cleanup=77672 cleanup_delta_from_before=4

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:

[ 3.7s reqs=6 ] atoms=2,945,814 ping_ok=True [ 17.8s reqs=33 ] atoms=3,505,822 ping_ok=True [ 32.1s reqs=59 ] atoms=4,005,829 ping_ok=True [ 50.5s reqs=91 ] atoms=4,619,963 ping_ok=True [ 60.5s reqs=108] atoms=4,965,840 ping_ok=True [ 63.8s reqs=110] atoms=None ping_ok=False

The broker log ended with:

no more index entries in atom_tab (max=5000000)

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:

baseline atoms = 37,000 push 3 params x 5,000 dest-properties keys atoms immediately after attack = 77,675 delete nothing; restart rabbitmq431-lab broker boots; freshly-loaded atom count = 26,116 +5 seconds after shovel workers start reparsing = 76,513 +60 seconds steady state = 76,574

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:

python .\poc_shovel_atom_exhaustion.py --url http://127.0.0.1:35673 --user pol_user --password 'Low123!' --container rabbitmq431-lab --count 10

The script also contains a destructive mode for controlled lab use:

python .\poc_shovel_atom_exhaustion.py --url http://127.0.0.1:35673 --user pol_user --password 'Low123!' --container rabbitmq431-lab --count 250 --keys-per-param 20000 --no-cleanup --destructive

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, and binary_to_atom/1 on user-controlled values with allowlist validation followed by existing atoms only.
  • For src-protocol and dest-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 policymaker can affect node-wide resources when plugins parse runtime parameters.

Responsible Disclosure By

Trung Nguyen (@everping) of CyStack.

Пакеты

Наименование

rabbitmq

vmware
Затронутые версииВерсия исправления

>= 4.3.0, < 4.3.3

4.3.3

Наименование

rabbitmq

vmware
Затронутые версииВерсия исправления

>= 4.2.0, < 4.2.9

4.2.9

5.9 Medium

CVSS4

Дефекты

CWE-400

5.9 Medium

CVSS4

Дефекты

CWE-400