Trusts GET API leaks existence information to unauthorized users

Bug #1840288 reported by Colleen Murphy
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
OpenStack Identity (keystone)
Won't Fix
High
Colleen Murphy
OpenStack Security Advisory
Won't Fix
Undecided
Unassigned

Bug Description

The current implementation of the GET /v3/OS-TRUST/trusts/{trust_id} API leaks information about the existence of a trust to unauthorized users.

If an authenticated user requests a trust that either does not exist or has no remaining uses, the returned response is a 404 regardless of whether the user is an admin or a trustor/trustee of the hypothetical (e.g. soft-deleted or used-up) trust. If the trust does exist but the user has no access to it, the returned response is a 403. If an attacker had some reasonable way of guessing or brute-forcing the UUID of a trust, they could use this leak to confirm its existence. A valid trust ID can then be used as part of a token request in combination with the trustee's credentials.

The issue is here:

https://opendev.org/openstack/keystone/src/commit/5beddfaddbb4c59d7a24fa1d7ff534da4c69ddc5/keystone/api/trusts.py#L149-L150

The current "identity:get_trust" default policy rule is "" which is all-permissive, and authorization is hardcoded in the trust controller code. To enforce the "only the trustor or trustee can GET this" rule, it does a lookup of the trust and doesn't catch a NotFound, thereby leaking it directly back to the requester.

Colleen Murphy (krinkle)
tags: added: security trusts
removed: trus
Revision history for this message
Gage Hugo (gagehugo) wrote :

Since this report concerns a possible security risk, an incomplete security advisory task has been added while the core security reviewers for the affected project or projects confirm the bug and discuss the scope of any vulnerability along with potential solutions.

Changed in ossa:
status: New → Incomplete
Revision history for this message
Morgan Fainberg (mdrnstm) wrote :

I want to note that this only impacts authenticated users. Unauthenticated users are still presented with a 403. This is probably a Class C1 [0], it requires guessing UUIDs.

[0] https://security.openstack.org/vmt-process.html#incident-report-taxonomy

Revision history for this message
Guang Yee (guang-yee) wrote :

I agree with Morgan, Class C1 sound appropriate. I think we should be able to craft a policy that authorize on trustee and trustor only. Merely changing the return code to 403 may not be the right fix. That's like security by obscurity.

Changed in keystone:
assignee: nobody → Colleen Murphy (krinkle)
status: Triaged → In Progress
Revision history for this message
Colleen Murphy (krinkle) wrote :

I think changing the return code is the first step, done in https://review.opendev.org/676528 (we need to change tempest too). The rest of the fix is to move all of the authorization logic into policies (https://review.opendev.org/#/q/topic:trust-policies) and then to implement system scope and default roles for the trust policies (https://launchpad.net/bugs/1818850 https://launchpad.net/bugs/1818846).

Revision history for this message
Jeremy Stanley (fungi) wrote :

I concur with the class C1 suggestion here. Generally OpenStack's VMT has considered any theoretical vulnerability which depends on direct brute-forcing or guessing the UUID space as impractical, but still possibly a security hardening opportunity.

information type: Public Security → Public
Changed in ossa:
status: Incomplete → Won't Fix
Revision history for this message
Adam Young (ayoung) wrote : Re: [Bug 1840288] Re: Trusts GET API leaks existence information to unauthorized users

This is not a bug. Trust ids are not secrets. They can and are public
info. They are no more secret than a role assignment ID. Argh!

On Thu, Aug 15, 2019, 1:15 PM Colleen Murphy <email address hidden> wrote:

> I think changing the return code is the first step, done in
> https://review.opendev.org/676528 (we need to change tempest too). The
> rest of the fix is to move all of the authorization logic into policies
> (https://review.opendev.org/#/q/topic:trust-policies) and then to
> implement system scope and default roles for the trust policies
> (https://launchpad.net/bugs/1818850 https://launchpad.net/bugs/1818846).
>
> --
> You received this bug notification because you are subscribed to
> OpenStack Identity (keystone).
> Matching subscriptions: keystone-bugs
> https://bugs.launchpad.net/bugs/1840288
>
> Title:
> Trusts GET API leaks existence information to unauthorized users
>
> Status in OpenStack Identity (keystone):
> In Progress
> Status in OpenStack Security Advisory:
> Incomplete
>
> Bug description:
> The current implementation of the GET /v3/OS-TRUST/trusts/{trust_id}
> API leaks information about the existence of a trust to unauthorized
> users.
>
> If an authenticated user requests a trust that either does not exist
> or has no remaining uses, the returned response is a 404 regardless of
> whether the user is an admin or a trustor/trustee of the hypothetical
> (e.g. soft-deleted or used-up) trust. If the trust does exist but the
> user has no access to it, the returned response is a 403. If an
> attacker had some reasonable way of guessing or brute-forcing the UUID
> of a trust, they could use this leak to confirm its existence. A valid
> trust ID can then be used as part of a token request in combination
> with the trustee's credentials.
>
> The issue is here:
>
>
> https://opendev.org/openstack/keystone/src/commit/5beddfaddbb4c59d7a24fa1d7ff534da4c69ddc5/keystone/api/trusts.py#L149-L150
>
> The current "identity:get_trust" default policy rule is "" which is
> all-permissive, and authorization is hardcoded in the trust controller
> code. To enforce the "only the trustor or trustee can GET this" rule,
> it does a lookup of the trust and doesn't catch a NotFound, thereby
> leaking it directly back to the requester.
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/keystone/+bug/1840288/+subscriptions
>

Revision history for this message
Colleen Murphy (krinkle) wrote :

I don't see how a trust ID can be considered public information. A trust ID can be used as a component of an authentication request. It should be protected on the same level as a user ID or an application credential ID. A role ID cannot be used as part of an authentication request, knowing a role ID does not bring you any closer to getting a token.

Revision history for this message
Adam Young (ayoung) wrote :

There is nothing in the trust ID itself that indicates anything about the users, the roles, or the projects in the trust. As such, they are exactly the equivalent to a role-assignment ID: You know that something exists, but you do not know anything about it.

Trusts are supposed to be public in much the same way that a role assignment is public: if you know the trustor and trustee users, and the project involved, and the role, all the trust ID tells you is the pointer to the record that links that information together. It must be used in conjunction with an actual secret in order to get a token. The only information that should be considered secret is the credential used by the user to confirm their identity.

This bug is invalid.

Revision history for this message
Adam Young (ayoung) wrote :

An App Cred ID is different in that it is more analogous to a User ID than to a Trust ID. An App Cred is more comparable to the union of the trustee user and the trust together.

Revision history for this message
Guang Yee (guang-yee) wrote :

I think Adam's correct. Doesn't appear user can obtain a trust token if he's not a trustee. i.e.

{
    "auth": {
        "identity": {
            "methods": [
                "token"
            ],
            "token": {
                "id": "trustee_token"
            }
        },
        "scope": {
            "OS-TRUST:trust": {
                "id": "254e874294354f7288160b6a23c174d2"
            }
        }
    }
}

If the token is not a trustee token, Keystone will reject the request with 403.

Revision history for this message
Morgan Fainberg (mdrnstm) wrote :

The trust could be utilized as a vector of attack, knowing the existence of a trust (and trustor/trustee) gives an additional target to utilize for social engineering and otherwise. While this is a minimal security concern overall, generally speaking information about a given grant is not available to an unknown party (within Keystone). Trusts are not intended to be public similarly they are not really intended to be privileged information. I expect this should be consistency within keystone where possible minimizing security exposure where possible.

If we grant that anyone should be able to see roles that someone has on any project (provided they are logged in), I could see current behavior with trusts to be the expected behavior.

This is not a critical security hole, but a chance to minimize information that can be utilized by outside (but still valid keystone users) parties not explicitly part of the delegation (Cloud Admin, Domain/Project Admin*, Trustor, Trustee)

* Depending on policy configuration

Revision history for this message
Morgan Fainberg (mdrnstm) wrote :

Discussed in IRC[0] - conclusion is this is a Valid bug but there is no reasonable attack vector (the data could be used in determining whom to attempt to gain access to, but does not provide any means of direct attack). The data is *NOT* intended to be public but is not really explicitly private/privileged either. The API Contract and current behavior is an acceptable (as long as it is documented in this bug) behavior to leave.

This may still warrant an OSSN outlining that the data is available but there is minimal or no risk.

[0] http://eavesdrop.openstack.org/irclogs/%23openstack-keystone/%23openstack-keystone.2019-08-16.log.html#t2019-08-16T21:36:28

Changed in keystone:
status: In Progress → Won't Fix
Revision history for this message
Morgan Fainberg (mdrnstm) wrote :

Marking as "Wont Fix"

Revision history for this message
Colleen Murphy (krinkle) wrote :

I grant that a trust ID on its own is not enough to get a token, and that moreover if someone had a trustee's credentials or intercepted token then that would already be enough to look up the trust, so the trust UUID itself is not especially sensitive information. I would not go as far as to say it is "public" information, and ideally we would make this API consistent with our other APIs by enforcing RBAC first before revealing the existence or nonexistence of a record in the database. But it is not a severe enough leak to warrant changing the API error response and so I agree with marking this Won't Fix.

Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Change abandoned on keystone (master)

Change abandoned by Colleen Murphy (<email address hidden>) on branch: master
Review: https://review.opendev.org/676528
Reason: As discussed in the bug report, the information leak is not severe enough to warrant changing the API behavior, so abandoning this.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.