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

exploitDog

github логотип

GHSA-j6hc-926v-qwq2

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

Описание

RabbitMQ STOMP consumers retain OAuth queue access after JWT expiration

Advisory Details

Title: RabbitMQ STOMP consumers retain OAuth queue access after JWT expiration

Description:

Summary

RabbitMQ's native STOMP adapter does not terminate an authenticated consumer when the OAuth JWT used for CONNECT expires. A client that subscribes while the token is valid can continue receiving new queue messages after the same token is rejected for a fresh connection. This defeats token-lifetime enforcement and can expose post-expiry message payloads.

Details

The highest affected GitHub release is v4.3.2, published on June 15, 2026. Its canonical upstream commit is a509158b1b1e21c892a7f1dacbe0d158076dc7b8.

In v4.3.2, rabbit_stomp_processor:process_connect/3 takes the STOMP CONNECT login and passcode and passes them to do_login/7. do_login/7 opens and stores a direct AMQP connection/channel for the STOMP session. It starts STOMP heartbeat handling, but it does not obtain rabbit_access_control:expiry_timestamp/1 and does not schedule a credential-expiry event.

The STOMP reader schedules only login_timeout. Once rabbit_stomp_processor:info(channel, ProcState) is no longer none, that timeout handler returns without installing any follow-up expiry timer. Existing subscriptions are then created with amqp_channel:subscribe/3, and send_delivery/5 serializes deliveries as STOMP MESSAGE frames without a post-expiry authorization barrier.

%% rabbit_stomp_reader.erl in v4.3.2 LoginTimeout = application:get_env(rabbitmq_stomp, login_timeout, 10_000), erlang:send_after(LoginTimeout, self(), login_timeout). handle_info(login_timeout, State) -> case rabbit_stomp_processor:info(channel, ProcState) of none -> {stop, {shutdown, login_timeout}, State}; _ -> {noreply, State, hibernate} end.

This is inconsistent with AMQP 0-9-1, where rabbit_reader calls rabbit_access_control:expiry_timestamp/1, schedules credential_expired, and closes the connection when the timer fires.

The issue was reproduced end-to-end against the current upstream main checkout at 5341617a24a53ea1702294cb549448bcaa270d20. The highest released version v4.3.2 contains the same missing STOMP expiry scheduling and delivery flow at the occurrence locations below.

PoC

Prerequisites

  • Docker with the elixir:1.18-otp-27 image available
  • RabbitMQ source checkout and GNU Make
  • A local OAuth signing key and a JWT with a short exp plus rabbitmq.configure and rabbitmq.read scopes for one test queue
  • rabbitmq_management, rabbitmq_stomp, and rabbitmq_auth_backend_oauth2 enabled
  • Local ports 5678, 61618, and 15678 available

The provided environment is localhost-only. The management account is used only to create the isolated virtual host/queue and publish test messages. The attack path itself is a normal STOMP client holding an already issued, short-lived JWT.

Reproduction Steps

  1. From a RabbitMQ source checkout, create llm-enhance/cve-finding/Info_Leak/CVE-2026-57218-stomp-token-expiry-exp/. Download the shell/Python scripts below into that directory and place the three runtime files under its runtime/ subdirectory: rabbitmq.conf, advanced.config, and enabled_plugins

  2. Download start_environment.sh, stop_environment.sh, and run_experiment.sh. Mark them executable and run the starter from that exploit directory:

chmod +x start_environment.sh stop_environment.sh run_experiment.sh ./start_environment.sh
  1. Download verification_test.py and control-expired-token-rejected.py into the same exploit directory. Run:
python3 verification_test.py
  1. Run the matching control:
python3 control-expired-token-rejected.py
  1. The convenience wrapper run_experiment.sh performs startup, liveness checks, the verification, the control, and log collection. Use stop_environment.sh to remove the isolated container afterward

Log of Evidence

[End-to-End] raw STOMP credential-expiry verification {"fresh_connection_rejected": true, "post_expiry_message_body": "after-expiry-secret", "post_expiry_message_command": "MESSAGE"} [DEFECT-CONFIRMED] [End-to-End] control for expired STOMP token {"expired_token_connection_rejected": true} [CONTROL-PASSED]

The broker log independently recorded successful OAuth authentication for attacker before expiry. After expiry, it recorded that the identical JWT had expired and sent Bad CONNECT for a new STOMP connection. The original pre-expiry consumer nevertheless received after-expiry-secret.

Impact

This is an information disclosure caused by insufficient session expiration. A principal with a legitimate but short-lived STOMP JWT can retain access to future messages after the credential expires. The risk is most relevant where short token lifetimes are used for service-to-service access, temporary integrations, device access, or rapid revocation following token compromise.

The issue does not let an attacker forge JWTs, obtain administrator privileges, or access queues for which the JWT never had read permission. It extends authorized access beyond the intended credential lifetime until the STOMP connection is otherwise terminated.

Affected products

  • Ecosystem: RabbitMQ Server
  • Package name: rabbitmq-server
  • Affected versions: <= 4.3.2
  • Patched versions:

Severity

  • Severity: Medium
  • Vector string: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N

Weaknesses

  • CWE: CWE-613: Insufficient Session Expiration

Occurrences

PermalinkDescription
https://github.com/rabbitmq/rabbitmq-server/blob/a509158b1b1e21c892a7f1dacbe0d158076dc7b8/deps/rabbitmq_stomp/src/rabbit_stomp_processor.erl#L261-L284process_connect/3 extracts the STOMP login/passcode and transfers the authenticated session setup to do_login/7
https://github.com/rabbitmq/rabbitmq-server/blob/a509158b1b1e21c892a7f1dacbe0d158076dc7b8/deps/rabbitmq_stomp/src/rabbit_stomp_processor.erl#L583-L615do_login/7 starts and stores the direct connection/channel and configures heartbeats, but does not schedule credential expiry
https://github.com/rabbitmq/rabbitmq-server/blob/a509158b1b1e21c892a7f1dacbe0d158076dc7b8/deps/rabbitmq_stomp/src/rabbit_stomp_reader.erl#L88-L90The reader schedules only pre-authentication login_timeout; no OAuth credential-expiry timer is created
https://github.com/rabbitmq/rabbitmq-server/blob/a509158b1b1e21c892a7f1dacbe0d158076dc7b8/deps/rabbitmq_stomp/src/rabbit_stomp_reader.erl#L169-L175Once authentication created a channel, login_timeout returns without any replacement session-expiry enforcement
https://github.com/rabbitmq/rabbitmq-server/blob/a509158b1b1e21c892a7f1dacbe0d158076dc7b8/deps/rabbitmq_stomp/src/rabbit_stomp_processor.erl#L846-L859send_delivery/5 emits a STOMP MESSAGE for an existing subscription without an expiry-time reauthorization check

Пакеты

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

rabbitmq

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

>= 4.3.0, < 4.3.6

4.3.6

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

rabbitmq

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

>= 4.2.0, < 4.2.11

4.2.11

4.9 Medium

CVSS4

Дефекты

CWE-613

4.9 Medium

CVSS4

Дефекты

CWE-613