[OSSA 2013-009] Validation of PKI tokens bypasses revocation check

Bug #1129713 reported by Adam Young
268
This bug affects 2 people
Affects Status Importance Assigned to Milestone
OpenStack Identity (keystone)
Invalid
Medium
Unassigned
Folsom
Fix Released
Medium
Dolph Mathews
OpenStack Security Advisory
Fix Released
Undecided
Thierry Carrez

Bug Description

for PKI tokens, we are bypassing token.get_token() call and therefore skipping the “valid=True” check.

In Grizzly, this code is in keystone/token/controllers.py
In Folsom, this code is in keystone/service.py

The if block bypasses the backend check. It is in the backend where tokens are checked for revocation.

def _get_token_ref(self, context, token_id, belongs_to=None):
        """Returns a token if a valid one exists.

Optionally, limited to a token owned by a specific tenant.

"""
        # TODO(termie): this stuff should probably be moved to middleware
        self.assert_admin(context)

        if cms.is_ans1_token(token_id):
            data = json.loads(cms.cms_verify(cms.token_to_cms(token_id),
                                             CONF.signing.certfile,
                                             CONF.signing.ca_certs))
            data['access']['token']['user'] = data['access']['user']
            data['access']['token']['metadata'] = data['access']['metadata']
            if belongs_to:
                assert data['access']['token']['tenant']['id'] == belongs_to
            token_ref = data['access']['token']
        else:
            token_ref = self.token_api.get_token(context=context,
                                                 token_id=token_id)
        return token_ref

The exposure is limited to people that are passing the whole PKI token back for validation via the web service.

This PKI tokens were supposed to be validated primarily via Crypto, but there is an option to validate them against the live server as well. It is only this last code path that is affected. It is unlikely to be triggered in Folsom, as people have to make a deliberate decision to use PKI tokens, and are unlikely to be validating them against the Keystone server.

Remote services can choose to pass a Hash of the PKI token to the validate Web API, which web services are likely to do, as the Hash is short enough to fit in a cookie. The Hash is then it looked up using the backend get_token() behavior and works correctly.

 It does not effect the keystone calls that first require validating the token. For example if a user runs tenant_list against their own account, using a PKI token, they do

 token_ref = self.token_api.get_token(context=context,
                                      token_id=context['token_id'])

This was discovered by Guang Yee.

Related branches

CVE References

Revision history for this message
Adam Young (ayoung) wrote :
Revision history for this message
Adam Young (ayoung) wrote :
description: updated
Revision history for this message
Thierry Carrez (ttx) wrote :

Isn't the benefit of PKI tokens that you don't have to validate them against the Keystone server directly ? Is that direct check called by clients anywhere (think when Nova receives a PKI token) ? On the other hand, would the crypto validation check revocation ? I'm trying to see if this is worth an advisory, or if it's really a corner case. Opinions welcome.

Changed in keystone:
importance: Undecided → Medium
status: New → Confirmed
Revision history for this message
Adam Young (ayoung) wrote :

The default behaviour in Folsom is for Keystone to still hand out UUID tokens, so this code path is not hit by default.

The auth-token middleware has access to a configuration option which says "always verify online." which is not set by default, so even if the user switched over to PKI tokens, they would not get that option, and this path would no be hit.

It would require setting both the keystone server to hand out PKI tokens, and the servives that consume auth_token middleware to verify online in order to execute this path.

Revision history for this message
Russell Bryant (russellb) wrote :

Ok, so if it's technically possible to set it up in this manner, I suppose we need to do an advisory for this, even if it's very unlikely that anyone has set up this particular configuration.

Need keystone-core reviews on the patches

Revision history for this message
Dolph Mathews (dolph) wrote :

PKI tokens in Grizzly are enabled by default, so if a grizzly deployment is issuing PKI tokens to an older client, that client will attempt to perform online validation and hit this code path. Correct?

Adam: your patch appears to be completely removing support for belongsTo. Apparently we don't have test coverage on this particular feature, and I'm not aware that this feature is used within OpenStack, but it's definitely part of the v2.0 API that should be tested by suites like tempest. This is used to perform server-side validation that a token has authorization on a specific tenant in one of the following two calls:

  GET /v2.0/tokens/{token_id}?belongsTo={tenant_id}
  HEAD /v2.0/tokens/{token_id}?belongsTo={tenant_id}

The auth_token middleware does this same validation client-side, rather than asking keystone to do it server-side.

These two lines need to be restored:

- if belongs_to:
- assert data['access']['token']['tenant']['id'] == belongs_to

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

Keystone-core: please +2 patches on this bug.

Revision history for this message
Henry Nash (henry-nash) wrote : Re: [Bug 1129713] Validation of PKI tokens bypasses revocation check
Download full text (3.3 KiB)

+2 on the functionality (minor nit in that I think the assert statement for checking belongs_to is incorrectly indented)

Henry
On 20 Feb 2013, at 05:06, Adam Young wrote:

> ** Patch added: "validate-from-backend-grizzly-20130218-2.patch"
> https://bugs.launchpad.net/keystone/+bug/1129713/+attachment/3537581/+files/validate-from-backend-grizzly-20130218-2.patch
>
> --
> You received this bug notification because you are a member of Keystone
> Core Developers, which is subscribed to the bug report.
> https://bugs.launchpad.net/bugs/1129713
>
> Title:
> Validation of PKI tokens bypasses revocation check
>
> Status in OpenStack Identity (Keystone):
> Confirmed
>
> Bug description:
> for PKI tokens, we are bypassing token.get_token() call and therefore
> skipping the “valid=True” check.
>
> In Grizzly, this code is in keystone/token/controllers.py
> In Folsom, this code is in keystone/service.py
>
> The if block bypasses the backend check. It is in the backend where
> tokens are checked for revocation.
>
> def _get_token_ref(self, context, token_id, belongs_to=None):
> """Returns a token if a valid one exists.
>
> Optionally, limited to a token owned by a specific tenant.
>
> """
> # TODO(termie): this stuff should probably be moved to middleware
> self.assert_admin(context)
>
> if cms.is_ans1_token(token_id):
> data = json.loads(cms.cms_verify(cms.token_to_cms(token_id),
> CONF.signing.certfile,
> CONF.signing.ca_certs))
> data['access']['token']['user'] = data['access']['user']
> data['access']['token']['metadata'] = data['access']['metadata']
> if belongs_to:
> assert data['access']['token']['tenant']['id'] == belongs_to
> token_ref = data['access']['token']
> else:
> token_ref = self.token_api.get_token(context=context,
> token_id=token_id)
> return token_ref
>
> The exposure is limited to people that are passing the whole PKI token
> back for validation via the web service.
>
> This PKI tokens were supposed to be validated primarily via Crypto,
> but there is an option to validate them against the live server as
> well. It is only this last code path that is affected. It is
> unlikely to be triggered in Folsom, as people have to make a
> deliberate decision to use PKI tokens, and are unlikely to be
> validating them against the Keystone server.
>
> Remote services can choose to pass a Hash of the PKI token to the
> validate Web API, which web services are likely to do, as the Hash is
> short enough to fit in a cookie. The Hash is then it looked up using
> the backend get_token() behavior and works correctly.
>
> It does not effect the keystone calls that first require validating
> the token. For example if a user runs tenant_list against their own
> account, using a PKI token, they do
>
> token_ref = self.token_api.get_token(context=context,
> token_id=context[...

Read more...

Revision history for this message
Dolph Mathews (dolph) wrote : Re: Validation of PKI tokens bypasses revocation check

Eek, I didn't consider that it was a regular old assert -- use of the assert keyword should be removed in favor of a condition:

  if belongs_to and data['tenant']['id'] != belongs_to:
    raise exceptions.Unauthorized('Token does not belong to specified tenant.')

(asserts are removed with compile-time optimization and wouldn't raise a useful error to the API)

Revision history for this message
Thierry Carrez (ttx) wrote :

Adam: could you rework your patch based on Dolph's remarks ?

Revision history for this message
Dolph Mathews (dolph) wrote :

Some of the issues being fixed here were reported in bug 1081943 -- specifically points 2 and 3 in that bug. The first point is not and should not be addressed here.

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

Grizzly already has the fix applied as part of other work.

Updating patch for folsom

Revision history for this message
Thierry Carrez (ttx) wrote :

Marking grizzly as unaffected.
Please confirm Essex is not impacted. I'll draft an advisory text.

Changed in keystone:
status: Confirmed → Invalid
Revision history for this message
Thierry Carrez (ttx) wrote :

Also keystone-core please formally confirm that the lastest version of the folsom patch is good for you.

Revision history for this message
Dolph Mathews (dolph) wrote :

Adam: the argument to exception.Unauthorized() should only be provided in Grizzly

Revision history for this message
Thierry Carrez (ttx) wrote :

Proposed impact description. Please check that only Folsom is affected. What's the name of the config option that does enable "always verify online" ? maybe I could mention it.

-----------------------
Title: Online validation of Keystone PKI tokens bypasses revocation check
Reporter: Guang Yee (HP)
Products: Keystone
Affects: Folsom

Description:
Guang Yee from HP reported a vulnerability in the revocation check for Keystone PKI tokens. Those tokens are supposed to be validated locally using cryptographic checks, but the user also has the option of asking the server to validate them. In that case, the online verification of PKI tokens would bypass the revocation check, potentially affirming revocated tokens are still valid. Only setups making use of online verification of PKI tokens are affected.
-----------------------

Revision history for this message
Michael Still (mikal) wrote :

Impact description looks good to me.

Revision history for this message
Dolph Mathews (dolph) wrote :

ttx: using UUID tokens implicitly enables online verification. A PKI token will attempt to be verified offline.

So to require online verification, you can have keystone start issuing UUID tokens:

  token_format = UUID

+1 for impact description.

Adam: in folsom, the following code exposes the specific reason for auth failure back to the client:

+ raise exceptions.Unauthorized(
+ 'Token does not belong to specified tenant.')

In grizzly, the details of the failure are suppressed unless you're running in debug mode (so this code would be fine in grizzly). For the folsom patch, this needs to be simplified a bit:

+ raise exceptions.Unauthorized()

Revision history for this message
Dolph Mathews (dolph) wrote :

I revised the folsom patch above:

 - backported 3 tests for this change from grizzly
 - handled the corner case tested by test_belongs_to_no_tenant
 - removed the argument to exception.Unauthorized()
 - changed "exceptions" to "exception" in "raise exception.Unauthorized()"

Revision history for this message
Henry Nash (henry-nash) wrote :

+1 from mr

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

Changes look good. +1

Revision history for this message
Thierry Carrez (ttx) wrote :

Sent downstream.

Proposed public disclosure date/time:
Wednesday, March 20, 1500UTC

Revision history for this message
Thierry Carrez (ttx) wrote :

CVE-2013-1865

Thierry Carrez (ttx)
information type: Private Security → Public Security
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix proposed to keystone (stable/folsom)

Fix proposed to branch: stable/folsom
Review: https://review.openstack.org/24906

Revision history for this message
Thierry Carrez (ttx) wrote : Re: Validation of PKI tokens bypasses revocation check

OSSA 2013-009

Revision history for this message
OpenStack Infra (hudson-openstack) wrote : Fix merged to keystone (stable/folsom)

Reviewed: https://review.openstack.org/24906
Committed: http://github.com/openstack/keystone/commit/255b1d43500f5d98ec73a0056525b492b14fec05
Submitter: Jenkins
Branch: stable/folsom

commit 255b1d43500f5d98ec73a0056525b492b14fec05
Author: Adam Young <email address hidden>
Date: Wed Mar 20 09:49:32 2013 -0500

    validate from backend (bug 1129713)

    In certain cases we were depending on CMS to validate PKI tokens
    but that is not necessary, and by passes the revocation check

    Change-Id: I9d7e60b074aa8c8859971618fed20c8cde2220c4

Thierry Carrez (ttx)
summary: - Validation of PKI tokens bypasses revocation check
+ [OSSA 2013-009] Validation of PKI tokens bypasses revocation check
Changed in ossa:
assignee: nobody → Thierry Carrez (ttx)
status: New → Fix Released
To post a comment you must log in.
This report contains Public Security information  
Everyone can see this security related information.

Other bug subscribers

Remote bug watches

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