Описание
Cross-vhost Stream consumer virtual-host existence disclosure
Advisory Details
Title: Cross-vhost Stream consumer virtual-host existence disclosure
Description:
Summary
The Stream management endpoint GET /api/stream/consumers/:vhost allows an authenticated management user with no permissions for a target virtual host to distinguish whether that vhost exists. The endpoint performs only general management authentication before checking vhost existence, returning 200 OK for an existing inaccessible vhost and 404 Not Found for an absent one. This is a low-severity cross-tenant information disclosure.
Details
The affected handler is deps/rabbitmq_stream_management/src/rabbit_stream_consumers_mgmt.erl. It registers a vhost-scoped route but uses rabbit_mgmt_util:is_authorized/2, which verifies general management API access and does not enforce access to the vhost supplied in the URL.
rabbit_mgmt_util:vhost/1 resolves the attacker-controlled :vhost path value through rabbit_vhost:exists/1. Therefore, the REST resource-existence callback exposes the result of the existence check before a vhost authorization decision is made. Later filtering of consumer records does not remove the response-status oracle.
The vhost-aware helper, rabbit_mgmt_util:is_authorized_vhost/2, delegates to user_matches_vhost/2 and check_vhost_access/4; this endpoint should use that helper instead.
PoC
Prerequisites
- RabbitMQ Management, Stream, and Stream Management plugins enabled
- A management-tagged user able to authenticate to the management HTTP API
- An existing target vhost to which that user has no permissions
- Docker and Docker Compose for the supplied isolated environment
The following secret Gists contain the minimal PoC and environment files:
- docker-compose.yml
- enabled_plugins
- start_environment.sh
- verification_test.py
- control-missing-vhost.py
- run_experiment.sh
- stop_environment.sh
Reproduction Steps
- Download the seven PoC files listed above into one directory and preserve their filenames
- Make the shell and Python files executable, then run
./run_experiment.sh - The runner starts an isolated RabbitMQ container, enables the required plugins, creates
hidden-vhost, and creates thelimitedmanagement user with no vhost permissions - The verification script requests
/api/stream/consumers/hidden-vhostand/api/stream/consumers/missing-vhostwith the samelimitedcredentials - Confirm that the existing inaccessible vhost returns
200 [], while the missing-vhost control returns404
For manual execution, run ./start_environment.sh, send the two requests from the verification script with the limited credentials, and run ./stop_environment.sh afterward.
Log of Evidence
The end-to-end verification produced:
Independent observations confirmed that the limited user had an empty permissions list, and the required rabbitmq_management, rabbitmq_stream, and rabbitmq_stream_management plugins were running.
Impact
An authenticated management user can enumerate known or guessable vhost names belonging to other tenants or business environments. The PoC does not read Stream consumer details, messages, credentials, or perform unauthorized vhost operations. The demonstrated impact is limited to vhost-name existence disclosure, which can reveal tenant, project, regional, or production-environment naming information.
Affected products
- Ecosystem: Other
- Package name: rabbitmq-server
- Affected versions: >= 3.8.10, <= 4.3.2
- Patched versions:
v4.3.2 is the highest affected GitHub release verified for this report. The endpoint was also verified in v3.8.10, where the same route, general authorization call, and vhost-existence callback are present.
Severity
- Severity: Low
- Vector string: CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
Weaknesses
- CWE: CWE-200: Exposure of Sensitive Information to an Unauthorized Actor
Occurrences
| Permalink | Description |
|---|---|
| https://github.com/rabbitmq/rabbitmq-server/blob/a509158b1b1e21c892a7f1dacbe0d158076dc7b8/deps/rabbitmq_stream_management/src/rabbit_stream_consumers_mgmt.erl#L38-L47 | resource_exists/2 converts the attacker-controlled path vhost into an observable exists versus not-found REST decision |
| https://github.com/rabbitmq/rabbitmq-server/blob/a509158b1b1e21c892a7f1dacbe0d158076dc7b8/deps/rabbitmq_stream_management/src/rabbit_stream_consumers_mgmt.erl#L71-L72 | is_authorized/2 invokes general management authorization instead of the vhost-aware authorization helper |
Пакеты
rabbitmq
>= 4.3.0, < 4.3.6
4.3.6
rabbitmq
>= 4.2.0, < 4.2.11
4.2.11
2.3 Low
CVSS4
Дефекты
2.3 Low
CVSS4