Описание
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:impersonatorplus 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
2. Generic refresh installs only the backend impl
The returned #auth_user.tags are pattern-matched away. The #user{} keeps
its old tags field.
3. Stale tag still authorizes foreign user_id
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
- Enable OAuth2 (
auth_backends = [rabbit_auth_backend_oauth2]). - Issue token A for user
alicewith write scope andrabbitmq.tag:impersonator. - Connect over AMQP 0-9-1 with token A; publish with
user_id = bob→ succeeds. - Issue token B for the same mapped username with write scope but no impersonator tag.
- Call
connection.update_secretwith token B →update_secret_ok. - On the same channel (and on a newly opened channel on the same connection),
publish again with
user_id = bob. - 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
impersonatorand 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_idpublishing after privilege revocation.
Recommended remediation
- In
rabbit_access_control:update_state/2, rebuild#user.tagsfrom 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_idrefusal.
Пакеты
rabbitmq
>= 3.13.0, < 3.13.19
3.13.19
rabbitmq
>= 4.0.0, < 4.0.24
4.0.24
rabbitmq
>= 4.1.0, < 4.1.15
4.1.15
rabbitmq
>= 4.2.0, < 4.2.10
4.2.10
rabbitmq
>= 4.3.0, < 4.3.5
4.3.5
Связанные уязвимости
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...
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...
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
RabbitMQ is a messaging and streaming broker. From 3.13.0 until 3.13.1 ...