Description
## Summary
SSH challenge tokens are mistakenly accepted as valid credentials during the authentication token validation process.
While an SSH challenge token is intended as a short-lived nonce for use in a subsequent SSH key exchange, the function to validate authentication tokens does not differentiate between these and actual authentication tokens. Because challenge tokens are generated based on an account name provided via headers without requiring prior authentication, an unauthenticated attacker can request a valid "challenge" token for any account (including administrative ones) and use it to authenticate against other API endpoints.
## Proof of Concept
The vulnerability exists because SSH challenge tokens are stored in the same database table as regular authentication tokens and `validate_auth_token` in `lib/rucio/core/authentication.py` accepts these "challenge" tokens. An attacker can obtain a challenge token for an account such as “root” via the REST API and then present it as a valid authentication bearer token:
1. Request a challenge token for an arbitrary account (e.g., "root"):
`curl -i -H "X-Rucio-Account: root" https://rucio/auth/ssh_challenge_token`
2. The server returns a `200 OK` with the header `X-Rucio-SSH-Challenge-Token`.
3. The attacker can then use this specific token within the ten-second challenge lifetime as an authentication credential in subsequent requests to the Rucio API:
`curl -H "X-Rucio-Auth-Token: $CHALLENGE_TOKEN" https://rucio/accounts/whoami`
Affected packages
| Ecosystem | Package | Affected | Fixed | Record |
|---|---|---|---|---|
| PyPI | rucio | >= 1.14.0.post1, < 35.9.1 | 35.9.1 | GHSA-x585-4vv8-2mh2 |
| PyPI | rucio | >= 36.0.0rc1, < 38.6.1 | 38.6.1 | GHSA-x585-4vv8-2mh2 |
| PyPI | rucio | >= 39.0.0rc1, < 40.4.2 | 40.4.2 | GHSA-x585-4vv8-2mh2 |
| PyPI | rucio | >= 41.0.0rc1, < 41.1.1 | 41.1.1 | GHSA-x585-4vv8-2mh2 |
References
- https://github.com/rucio/rucio/security/advisories/GHSA-x585-4vv8-2mh2 web
- https://github.com/rucio/rucio/commit/f5db3546d9c0de4642dc9aa52e6a6e447911d680 web
- https://github.com/rucio/rucio/commit/e6525523e3bbe8ae34cbfc9b043ae52bda209b87 web
- https://github.com/rucio/rucio/commit/d7a3c2c2f933dce8edbcad07d8d076b9b782da35 web
- https://github.com/rucio/rucio/commit/b1725ee5477b683202174f0ec77ae00921bc3bd0 web
- https://github.com/rucio/rucio/commit/883d526c2f3c315cd775fb142038007053e3882b web
- https://github.com/rucio/rucio/commit/8295d72a9e2d76abf9e98eb6f9a4ed5cb3bb1869 web
- https://github.com/rucio/rucio/commit/4df924feb539ef789b3e78cbc00712ef8cdf606e web
- https://github.com/rucio/rucio/commit/4d4a58571ba853f3a55aef16ad9eb0944fce7483 web
- https://github.com/rucio/rucio/releases/tag/35.9.1 web
- https://github.com/rucio/rucio/releases/tag/35.9.1.post1 web
- https://github.com/rucio/rucio/releases/tag/38.6.1 web
- https://github.com/rucio/rucio/releases/tag/38.6.2 web
- https://github.com/rucio/rucio/releases/tag/40.4.2 web
- https://github.com/rucio/rucio/releases/tag/41.1.1 web
- https://github.com/rucio/rucio/releases/tag/41.2.0 web
- https://github.com/rucio/rucio package