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

exploitDog

github логотип

GHSA-86fm-44m9-rqjx

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

Описание

RabbitMQ OAuth credential refresh retains revoked runtime tags

Summary

When an existing AMQP connection refreshes from an OAuth token that grants the impersonator tag to a valid same-username token that no longer grants that tag, RabbitMQ updates the OAuth backend implementation (token/scopes/expiry) but leaves the connection's runtime #user.tags unchanged.

rabbit_access_control:check_user_id/2 then still honors the stale impersonator tag, so the connection (including newly opened channels) can continue publishing messages with a foreign AMQP user_id after that privilege should have been revoked.

A fresh connection using the downgraded token correctly refuses the same publish, proving the defect is stale session state rather than the token itself.

Preconditions

  • rabbit_auth_backend_oauth2 (or an equivalent refresh-capable backend that returns tags) is enabled for AMQP.
  • The attacker previously obtained a valid token granting rabbitmq.tag:impersonator plus vhost/write scope.
  • The attacker can call connection.update_secret (AMQP 0-9-1) or the AMQP 1.0 credential-update path with a new same-username token that retains write/vhost scope but omits the impersonator tag.
  • Refresh occurs before the original credential-expiry timer closes the connection.

Root cause

1. OAuth refresh recomputes tags correctly

%% deps/rabbitmq_auth_backend_oauth2/src/rabbit_auth_backend_oauth2.erl %% (update_state/2 path) Tags = tags_from(DecodedToken), {ok, AuthUser#auth_user{tags = Tags, impl = fun() -> Token1 end}};

2. Generic refresh installs only the backend impl

%% deps/rabbit/src/rabbit_access_control.erl:414-436 update_state(User = #user{authz_backends = Backends0}, NewState) -> Backends = lists:foldl( fun({Module, Impl}, {ok, Acc}) -> AuthUser = auth_user(User, Impl), case Module:expiry_timestamp(AuthUser) of never -> {ok, [{Module, Impl} | Acc]}; _ -> case Module:update_state(AuthUser, NewState) of {ok, #auth_user{impl = Impl1}} -> {ok, [{Module, Impl1} | Acc]}; Else -> Else end end; ... end, {ok, []}, Backends0), case Backends of {ok, Pairs} -> {ok, User#user{authz_backends = lists:reverse(Pairs)}}; Else -> Else end.

The returned #auth_user.tags are pattern-matched away. The #user{} keeps its old tags field.

3. Stale tag still authorizes foreign user_id

%% deps/rabbit/src/rabbit_access_control.erl:394-407 check_user_id0(ClaimedUserName, #user{username = ActualUserName, tags = Tags}) -> case lists:member(impersonator, Tags) of true -> ok; false -> {refused, ...} end.

AMQP 0-9-1 and AMQP 1.0 readers propagate the returned user to channels/sessions after refresh, so both old and new channels on that connection inherit the stale tag set. Permission caches are cleared, but the uncached user_id check reads the stale tags.

Reproduction

  1. Enable OAuth2 (auth_backends = [rabbit_auth_backend_oauth2]).
  2. Issue token A for user alice with write scope and rabbitmq.tag:impersonator.
  3. Connect over AMQP 0-9-1 with token A; publish with user_id = bob → succeeds.
  4. Issue token B for the same mapped username with write scope but no impersonator tag.
  5. Call connection.update_secret with token B → update_secret_ok.
  6. On the same channel (and on a newly opened channel on the same connection), publish again with user_id = bob.
  7. Control: fresh connection with token B publishing user_id = bob → refused.

Expected after step 5: both channels refuse foreign user_id.
Actual: refreshed connection still accepts it; fresh token-B connection refuses.

Source-level markers from the earlier oracle: refreshed_backend_new_state=true, refreshed_runtime_stale_impersonator_tag=true.

Impact

  • Limited to connections that once held impersonator and successfully refresh to a downgraded same-username token.
  • Does not by itself grant administrator, expand queue/exchange ACLs, or create new identities.
  • Integrity impact: message attribution / foreign user_id publishing after privilege revocation.

Recommended remediation

  • In rabbit_access_control:update_state/2, rebuild #user.tags from refreshed #auth_user.tags (and any still-valid non-refreshed backend contributions).
  • Propagate the rebuilt user to all channels/sessions before acknowledging refresh.
  • Add a regression: after A→B refresh, old and new channels must match a fresh token-B connection's user_id refusal.

Пакеты

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

rabbitmq

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

>= 3.13.0, < 3.13.19

3.13.19

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

rabbitmq

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

>= 4.0.0, < 4.0.24

4.0.24

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

rabbitmq

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

>= 4.1.0, < 4.1.15

4.1.15

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

rabbitmq

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

>= 4.2.0, < 4.2.10

4.2.10

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

rabbitmq

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

>= 4.3.0, < 4.3.5

4.3.5

EPSS

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

2.3 Low

CVSS4

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

ubuntu
9 дней назад

RabbitMQ is a messaging and streaming broker. From 3.13.0 until 3.13.19, 4.0.24, 4.1.15, 4.2.10, and 4.3.5, RabbitMQ OAuth credential refresh retains revoked runtime tags. when an existing AMQP connection refreshes from an OAuth token that grants the impersonator tag to a valid same-username token that no longer grants that tag, RabbitMQ updates the OAuth backend implementation (token/scopes/expiry) but leaves the connection's runtime #user.tags unchanged. rabbitaccesscontrol:checkuserid/2 then still honors the stale impersonator tag, so the connection (including newly opened channels) can continue publishing messages with a foreign AMQP userid after that privilege should have been revoked. A fresh connection using the downgraded token correctly refuses the same publish, proving the defect is stale session state rather than the token Limited to connections that once held impersonator and successfully refresh to a downgraded same-username rabbitauthbackendoauth2 (or an equivalent ref...

CVSS3: 3.1
redhat
9 дней назад

RabbitMQ is a messaging and streaming broker. From 3.13.0 until 3.13.19, 4.0.24, 4.1.15, 4.2.10, and 4.3.5, RabbitMQ OAuth credential refresh retains revoked runtime tags. when an existing AMQP connection refreshes from an OAuth token that grants the impersonator tag to a valid same-username token that no longer grants that tag, RabbitMQ updates the OAuth backend implementation (token/scopes/expiry) but leaves the connection's runtime #user.tags unchanged. rabbitaccesscontrol:checkuserid/2 then still honors the stale impersonator tag, so the connection (including newly opened channels) can continue publishing messages with a foreign AMQP userid after that privilege should have been revoked. A fresh connection using the downgraded token correctly refuses the same publish, proving the defect is stale session state rather than the token Limited to connections that once held impersonator and successfully refresh to a downgraded same-username rabbitauthbackendoauth2 (or an equivalent ref...

nvd
9 дней назад

RabbitMQ is a messaging and streaming broker. From 3.13.0 until 3.13.19, 4.0.24, 4.1.15, 4.2.10, and 4.3.5, RabbitMQ OAuth credential refresh retains revoked runtime tags. when an existing AMQP connection refreshes from an OAuth token that grants the impersonator tag to a valid same-username token that no longer grants that tag, RabbitMQ updates the OAuth backend implementation (token/scopes/expiry) but leaves the connection's runtime #user.tags unchanged. rabbitaccesscontrol:checkuserid/2 then still honors the stale impersonator tag, so the connection (including newly opened channels) can continue publishing messages with a foreign AMQP userid after that privilege should have been revoked. A fresh connection using the downgraded token correctly refuses the same publish, proving the defect is stale session state rather than the token Limited to connections that once held impersonator and successfully refresh to a downgraded same-username rabbitauthbackendoauth2 (or an equivalent refres

debian
9 дней назад

RabbitMQ is a messaging and streaming broker. From 3.13.0 until 3.13.1 ...

EPSS

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

2.3 Low

CVSS4