[OSSA 2012-010] Following a password compromise and subsequent password change, tokens remain valid.

Bug #996595 reported by Derek Higgins on 2012-05-08
266
This bug affects 2 people
Affects Status Importance Assigned to Milestone
OpenStack Identity (keystone)
High
Derek Higgins
Essex
Undecided
Alan Pevec
OpenStack Security Advisory
Undecided
Thierry Carrez
keystone (Ubuntu)
Undecided
Unassigned
Precise
Undecided
Unassigned

Bug Description

If a password is comprimised and a user changes their password(or has it changed),
tokens that were issued previous to the password change remain valid. This
not only allows an attacker to keep access to the account for the lifetime of the
token but they can also create new tokens before the origional token is expired
allowing them to hold onto access indefinatly.

Of course knowing this an administrator could DELETE tokens individually via the API if
they knew the id of each one.

To reproduce :

Create an user test user (in this case id = ebae56e4d2114b9a994b69ac682a8d26)

# get a token
curl -X POST http://127.0.0.1:5000/v2.0/tokens -d '{"auth": {"tenantName":"testuser", "passwordCredentials":{"username":"testuser", "password":"password1"}}}' -H 'Content-Type: application/json'

{"access": {"token": {"expires": "2012-05-09T14:16:39Z", "id": "00de15a6f8884e9ab3e518f4e416a484", "tenant": {"description": "testuser", "enabled": true, "id": "t18", "name": "testuser"}}, "serviceCatalog": [{"endpoints": [{"adminURL": "http://localhost:8080/v1/AUTH_t18", "region": "regionOne", "internalURL": "http://localhost:8080/v1/AUTH_t18", "publicURL": "http://localhost:8080/v1/AUTH_t18"}], "endpoints_links": [], "type": "object-store", "name": "swift"}, {"endpoints": [{"adminURL": "http://localhost:9292/v1", "region": "regionOne", "internalURL": "http://localhost:9292/v1", "publicURL": "http://localhost:9292/v1"}], "endpoints_links": [], "type": "image", "name": "glance"}], "user": {"username": "testuser", "roles_links": [], "id": "ebae56e4d2114b9a994b69ac682a8d26", "roles": [{"id": "65f7b0195e5c401680017b263e095e16", "name": "swiftoperator"}, {"id": "ae1ea19f90fc46908117548d5babe6c9", "name": "admin"}], "name": "testuser"}}}

# change password because of a compromise
keystone user-password-update --pass password2 ebae56e4d2114b9a994b69ac682a8d26

# try to get a token with old credentials
curl -X POST http://127.0.0.1:5000/v2.0/tokens -d '{"auth": {"tenantName":"testuser", "passwordCredentials":{"username":"testuser", "password":"password1"}}}' -H 'Content-Type: application/json'

{"error": {"message": "Invalid user / password", "code": 401, "title": "Not Authorized"}}

# but we still have an old token that can be used with endpoints
curl -X POST http://127.0.0.1:5000/v2.0/tokens -d '{"auth": {"tenantName":"testuser", "token":{"id":"00de15a6f8884e9ab3e518f4e416a484"}}}' -H 'Content-Type: application/json'

{"access": {"token": {"expires": "2012-05-09T14:19:13Z", "id": "c5a5ebfe6b3245eba3a4f609e1526fbd", "tenant": {"description": "testuser", "enabled": true, "id": "t18", "name": "testuser"}}, "serviceCatalog": [{"endpoints": [{"adminURL": "http://localhost:8080/v1/AUTH_t18", "region": "regionOne", "internalURL": "http://localhost:8080/v1/AUTH_t18", "publicURL": "http://localhost:8080/v1/AUTH_t18"}], "endpoints_links": [], "type": "object-store", "name": "swift"}, {"endpoints": [{"adminURL": "http://localhost:9292/v1", "region": "regionOne", "internalURL": "http://localhost:9292/v1", "publicURL": "http://localhost:9292/v1"}], "endpoints_links": [], "type": "image", "name": "glance"}], "user": {"username": "testuser", "roles_links": [], "id": "ebae56e4d2114b9a994b69ac682a8d26", "roles": [{"id": "65f7b0195e5c401680017b263e095e16", "name": "swiftoperator"}, {"id": "ae1ea19f90fc46908117548d5babe6c9", "name": "admin"}], "name": "testuser"}}}

# disabling the user doesn't prevent the token from working either, it only appears to disable password authentication

# NOTE : this should probably be a seperate issue i.e. disabling a user doesn't disable/delete tokens

curl -X POST http://127.0.0.1:5000/v2.0/tokens -d '{"auth": {"tenantName":"testuser", "passwordCredentials":{"username":"testuser", "password":"password2"}}}' -H 'Content-Type: application/json'

{"access": {"token": {"expires": "2012-05-09T14:47:24Z", "id": "4458c9d81d854fd098d5c799237722ba", "tenant": {"description": "testuser", "enabled": true, "id": "t18", "name": "testuser"}}, "serviceCatalog": [{"endpoints": [{"adminURL": "http://localhost:8080/v1/AUTH_t18", "region": "regionOne", "internalURL": "http://localhost:8080/v1/AUTH_t18", "publicURL": "http://localhost:8080/v1/AUTH_t18"}], "endpoints_links": [], "type": "object-store", "name": "swift"}, {"endpoints": [{"adminURL": "http://localhost:9292/v1", "region": "regionOne", "internalURL": "http://localhost:9292/v1", "publicURL": "http://localhost:9292/v1"}], "endpoints_links": [], "type": "image", "name": "glance"}], "user": {"username": "testuser", "roles_links": [], "id": "ebae56e4d2114b9a994b69ac682a8d26", "roles": [{"id": "65f7b0195e5c401680017b263e095e16", "name": "swiftoperator"}, {"id": "ae1ea19f90fc46908117548d5babe6c9", "name": "admin"}], "name": "testuser"}}}

# disable the user
keystone user-update --enabled false ebae56e4d2114b9a994b69ac682a8d26

# confirm
curl -X POST http://127.0.0.1:5000/v2.0/tokens -d '{"auth": {"tenantName":"testuser", "passwordCredentials":{"username":"testuser", "password":"password2"}}}' -H 'Content-Type: application/json'

{"error": {"message": "User has been disabled", "code": 403, "title": "Not Authorized"}}

# a token can still be used
curl -X POST http://127.0.0.1:5000/v2.0/tokens -d '{"auth": {"tenantName":"testuser", "token":{"id":"4458c9d81d854fd098d5c799237722ba"}}}' -H 'Content-Type: application/json'

{"access": {"token": {"expires": "2012-05-09T14:47:40Z", "id": "935f78d7457d4e22be3b6f0ed1fe17fb", "tenant": {"description": "testuser", "enabled": true, "id": "t18", "name": "testuser"}}, "serviceCatalog": [{"endpoints": [{"adminURL": "http://localhost:8080/v1/AUTH_t18", "region": "regionOne", "internalURL": "http://localhost:8080/v1/AUTH_t18", "publicURL": "http://localhost:8080/v1/AUTH_t18"}], "endpoints_links": [], "type": "object-store", "name": "swift"}, {"endpoints": [{"adminURL": "http://localhost:9292/v1", "region": "regionOne", "internalURL": "http://localhost:9292/v1", "publicURL": "http://localhost:9292/v1"}], "endpoints_links": [], "type": "image", "name": "glance"}], "user": {"username": "testuser", "roles_links": [], "id": "ebae56e4d2114b9a994b69ac682a8d26", "roles": [{"id": "65f7b0195e5c401680017b263e095e16", "name": "swiftoperator"}, {"id": "ae1ea19f90fc46908117548d5babe6c9", "name": "admin"}], "name": "testuser"}}}

Russell Bryant (russellb) wrote :

Thanks for the report, Derek. I went ahead and added the Keystone PTL.

Regarding the security status of this bug, I'm leaning toward treating this as a 'security hardening' issue as opposed to a vulnerability. That basically means that we acknowledge that this issue has important security related implications, but we won't put it under embargo and treat it with the vulnerability process. Instead, we'll work on this in the open like other bugs.

So, the suggestion here is that tokens should be automatically invalidated when a password gets changed?

Derek Higgins (derekh) wrote :

yes that would solve my initial observation

in addition to this I think tokens should also be invalidated when a account is disabled currently they don't seem to be.

Joseph Heck (heckj) wrote :

Russell, I agree with your status on the bug - and it's a good one to get into place both for the password change option and the account disabled mechanism.

Derek - do you have any interest in submitting a patch for this, or are you more focused on making us aware? (i.e. would you like the bug assigned to you?)

Changed in keystone:
status: New → Confirmed
importance: Undecided → High
Russell Bryant (russellb) wrote :

I'm going to go ahead and open this up since we decided to not handle it as a vulnerability.

visibility: private → public
Derek Higgins (derekh) wrote :

I'll assign it to myself

Changed in keystone:
assignee: nobody → Derek Higgins (derekh)

Fix proposed to branch: master
Review: https://review.openstack.org/7276

Changed in keystone:
status: Confirmed → In Progress

Reviewed: https://review.openstack.org/7276
Committed: http://github.com/openstack/keystone/commit/a67b24878a6156eab17b9098fa649f0279256f5d
Submitter: Jenkins
Branch: master

commit a67b24878a6156eab17b9098fa649f0279256f5d
Author: Derek Higgins <email address hidden>
Date: Wed May 9 15:55:46 2012 +0100

    Invalidate user tokens when password is changed

    Fixes bug 996595

    This commit will cause all valid tokens to be deleted for a user
    who's password is changed (implemented for the sql and kvs backends)

    Change-Id: I6ad7da8957b7041983a3fc91d9ba9368667d06ac

Changed in keystone:
status: In Progress → Fix Committed
Joseph Heck (heckj) on 2012-05-20
Changed in keystone:
milestone: none → folsom-1
Thierry Carrez (ttx) on 2012-05-23
Changed in keystone:
status: Fix Committed → Fix Released
Alan Pevec (apevec) on 2012-06-11
tags: added: essex-backport

Reviewed: https://review.openstack.org/8454
Committed: http://github.com/openstack/keystone/commit/ea03d05ed5de0c015042876100d37a6a14bf56de
Submitter: Jenkins
Branch: stable/essex

commit ea03d05ed5de0c015042876100d37a6a14bf56de
Author: Derek Higgins <email address hidden>
Date: Wed May 9 15:55:46 2012 +0100

    Invalidate user tokens when password is changed

    Fixes bug 996595

    This commit will cause all valid tokens to be deleted for a user
    who's password is changed (implemented for the sql and kvs backends)

    Change-Id: I6ad7da8957b7041983a3fc91d9ba9368667d06ac

@Russell: Retrospectively looks like something we should communicate about too too :) How about an OSSA together with bug 998185 and bug 997194 (all Derek's findings) ?

Russell Bryant (russellb) wrote :

@ttx: ACK, agreed.

Dave Walker (davewalker) on 2012-08-24
Changed in keystone (Ubuntu):
status: New → Fix Released
Changed in keystone (Ubuntu Precise):
status: New → Confirmed

Please find the attached test log from the Ubuntu Server Team's CI infrastructure. As part of the verification process for this bug, Keystone has been deployed and configured across multiple nodes using precise-proposed as an installation source. After successful bring-up and configuration of the cluster, a number of exercises and smoke tests have be invoked to ensure the updated package did not introduce any regressions. A number of test iterations were carried out to catch any possible transient errors.

Please Note the list of installed packages at the top and bottom of the report.

For records of upstream test coverage of this update, please see the Jenkins links in the comments of the relevant upstream code-review(s):

Trunk review: https://review.openstack.org/7276
Stable review: https://review.openstack.org/8454

As per the provisional Micro Release Exception granted to this package by the Technical Board, we hope this contributes toward verification of this update.

The verification of this Stable Release Update has completed successfully and the package has now been released to -updates. Subsequently, the Ubuntu Stable Release Updates Team is being unsubscribed and will not receive messages about this bug report. In the event that you encounter a regression using the package from -updates please report a new bug using ubuntu-bug and tag the bug report regression-update so we can easily find any regresssions.

This bug was fixed in the package keystone - 2012.1+stable~20120824-a16a0ab9-0ubuntu2

---------------
keystone (2012.1+stable~20120824-a16a0ab9-0ubuntu2) precise-proposed; urgency=low

  * New upstream release (LP: #1041120):
    - debian/patches/0013-Flush-tenant-membership-deletion-before-user.patch:
      Dropped.
  * Resynchronize with stable/essex:
    - authenticate in ldap backend doesn't return a list of roles
      (LP: #1035428)
    - LDAP should not check username on "sn" field (LP: #997700)
    - Admin API doesn't valid token. (LP: #1006815, #1006822)
    - Memcache token backend eventually stops working. (LP: #1012381)
    - EC2 credentials not migrated from legacy (diablo) database. (LP: #1016056)
    - Deleting tenants or users does not cleanup metadata. (LP: #973243)
    - Deleting tenants does not cleanup its user associations. (LP: #974199)
    - TokenNotFound not raised in testsuite beacuse of timezone issues. (LP: #983800)
    - Token authentication for a user in a disabled tenant does not raise
      Unauthorized error. (LP: #988920)
    - export_legacy_catalog doesn't convert url names correctly. (LP: #994936)
    - Following a password compromise and subsequent password change,
      tokens remain valid. (LP: #996595)
    - Tokens remain valid after a user account is disabled. (LP: #997194)
 -- Adam Gandelman <email address hidden> Fri, 24 Aug 2012 03:34:59 -0400

Changed in keystone (Ubuntu Precise):
status: Confirmed → Fix Released
Thierry Carrez (ttx) on 2012-09-27
Changed in keystone:
milestone: folsom-1 → 2012.2
Thierry Carrez (ttx) on 2013-06-07
summary: - Following a password compromise and subsequent password change, tokens
- remain valid.
+ [OSSA 2012-010] Following a password compromise and subsequent password
+ change, tokens remain valid.
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  Edit
Everyone can see this security related information.

Other bug subscribers