CVE-2012-4456 (published 2012-10-09T15:55Z)

The (1) OS-KSADM/services and (2) tenant APIs in OpenStack Keystone Essex before 2012.1.2 and Folsom before folsom-2 do not properly validate X-Auth-Token, which allow remote attackers to read the roles for an arbitrary user or get, create, or delete arbitrary services.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)

Weakness information:
cwe_id: CWE-287
cwe_name: Improper Authentication
description: When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.
extended_description: 
            
			
         
         

Fix information:
repo_url: https://github.com/openstack/keystone
commit_details: repo_url: https://github.com/openstack/keystone
author: Dolph Mathews
author_date: 2012-06-03 12:24:07-05:00
msg: Require authz for user role list (bug 1006815)

Change-Id: I65f25dcca3e265f44746930917434b45e64de15e
repository: repo_url: https://github.com/openstack/keystone
repo_name: openstack/keystone
description: OpenStack Identity (Keystone). Mirror of code maintained at opendev.org.
repo_language: Python
owner: openstack
file_changes: filename: core.py
change_type: ModificationType.MODIFY
diff: @@ -467,6 +467,7 @@ class RoleController(wsgi.Application):
         not implementing them in hopes that the idea will die off.
 
         """
+        self.assert_admin(context)
         if tenant_id is None:
             raise exception.NotImplemented(message='User roles not supported: '
                                                    'tenant ID required')

programming_language: Python
filename: test_content_types.py
change_type: ModificationType.MODIFY
diff: @@ -587,6 +587,17 @@ class JsonTestCase(RestfulTestCase, CoreApiTests):
                                expected_status=401)
         self.assertValidErrorResponse(r)
 
+    def test_user_role_list_requires_auth(self):
+        """User role list should 401 without an X-Auth-Token (bug 1006815)."""
+        # values here don't matter because we should 401 before they're checked
+        path = '/v2.0/tenants/%(tenant_id)s/users/%(user_id)s/roles' % {
+                'tenant_id': uuid.uuid4().hex,
+                'user_id': uuid.uuid4().hex,
+        }
+
+        r = self.admin_request(path=path, expected_status=401)
+        self.assertValidErrorResponse(r)
+
 
 class XmlTestCase(RestfulTestCase, CoreApiTests):
     xmlns = 'http://docs.openstack.org/identity/api/v2.0'

programming_language: Python
repo_url: https://github.com/openstack/keystone
commit_details: repo_url: https://github.com/openstack/keystone
author: Dolph Mathews
author_date: 2012-06-03 11:00:54-05:00
msg: Require authz for service CRUD (bug 1006822)

Change-Id: Ia90f0aa2b856b9a9874d4865fb92ee913e8125c5
repository: repo_url: https://github.com/openstack/keystone
repo_name: openstack/keystone
description: OpenStack Identity (Keystone). Mirror of code maintained at opendev.org.
repo_language: Python
owner: openstack
file_changes: filename: core.py
change_type: ModificationType.MODIFY
diff: @@ -116,29 +116,36 @@ class Driver(object):
 class ServiceController(wsgi.Application):
     def __init__(self):
         self.catalog_api = Manager()
+        self.identity_api = identity.Manager()
+        self.policy_api = policy.Manager()
+        self.token_api = token.Manager()
         super(ServiceController, self).__init__()
 
     # CRUD extensions
     # NOTE(termie): this OS-KSADM stuff is not very consistent
     def get_services(self, context):
+        self.assert_admin(context)
         service_list = self.catalog_api.list_services(context)
         service_refs = [self.catalog_api.get_service(context, x)
                         for x in service_list]
         return {'OS-KSADM:services': service_refs}
 
     def get_service(self, context, service_id):
+        self.assert_admin(context)
         service_ref = self.catalog_api.get_service(context, service_id)
         if not service_ref:
             raise exception.ServiceNotFound(service_id=service_id)
         return {'OS-KSADM:service': service_ref}
 
     def delete_service(self, context, service_id):
+        self.assert_admin(context)
         service_ref = self.catalog_api.get_service(context, service_id)
         if not service_ref:
             raise exception.ServiceNotFound(service_id=service_id)
         self.catalog_api.delete_service(context, service_id)
 
     def create_service(self, context, OS_KSADM_service):
+        self.assert_admin(context)
         service_id = uuid.uuid4().hex
         service_ref = OS_KSADM_service.copy()
         service_ref['id'] = service_id

programming_language: Python
filename: test_content_types.py
change_type: ModificationType.MODIFY
diff: @@ -16,6 +16,7 @@
 
 import httplib
 import json
+import uuid
 
 from lxml import etree
 import nose.exc
@@ -554,6 +555,38 @@ class JsonTestCase(RestfulTestCase, CoreApiTests):
     def assertValidVersionResponse(self, r):
         self.assertValidVersion(r.body.get('version'))
 
+    def test_service_crud_requires_auth(self):
+        """Service CRUD should 401 without an X-Auth-Token (bug 1006822)."""
+        # values here don't matter because we should 401 before they're checked
+        service_path = '/v2.0/OS-KSADM/services/%s' % uuid.uuid4().hex
+        service_body = {
+                'OS-KSADM:service': {
+                    'name': uuid.uuid4().hex,
+                    'type': uuid.uuid4().hex,
+                    },
+                }
+
+        r = self.admin_request(method='GET',
+                               path='/v2.0/OS-KSADM/services',
+                               expected_status=401)
+        self.assertValidErrorResponse(r)
+
+        r = self.admin_request(method='POST',
+                               path='/v2.0/OS-KSADM/services',
+                               body=service_body,
+                               expected_status=401)
+        self.assertValidErrorResponse(r)
+
+        r = self.admin_request(method='GET',
+                               path=service_path,
+                               expected_status=401)
+        self.assertValidErrorResponse(r)
+
+        r = self.admin_request(method='DELETE',
+                               path=service_path,
+                               expected_status=401)
+        self.assertValidErrorResponse(r)
+
 
 class XmlTestCase(RestfulTestCase, CoreApiTests):
     xmlns = 'http://docs.openstack.org/identity/api/v2.0'

programming_language: Python