[Yahoo-eng-team] [Bug 1618615] Re: Potential information disclosure in EC2 "credentials"

2017-07-13 Thread Luke Hinds
will add a docs bug for this issue.

** Changed in: ossn
   Status: New => Won't Fix

-- 
You received this bug notification because you are a member of Yahoo!
Engineering Team, which is subscribed to OpenStack Identity (keystone).
https://bugs.launchpad.net/bugs/1618615

Title:
  Potential information disclosure in EC2 "credentials"

Status in OpenStack Identity (keystone):
  New
Status in OpenStack Security Advisory:
  Won't Fix
Status in OpenStack Security Notes:
  Won't Fix

Bug description:
  When creating a "credential" in Keystone, instead of using
  uuid.uuid4() like in most places to generate a unique identifier, the
  id is created from the SHA256 hash value of whatever is passed in as
  the "access" key in the POST request (Code here:
  
https://github.com/openstack/keystone/blob/master/keystone/credential/controllers.py#L36-L60)

  = EXAMPLE REQUEST =

  POST /v3/credentials HTTP/1.1
  Host: [ENDPOINT]
  X-Auth-Token: [ADMIN TOKEN]
  Content-Length: 231
  Content-Type: application/json

  {
  "credential": {
  "blob": 
"{\"access\":\"alert(2)\",\"secret\":\"secretKey\"}",
  "project_id": "12345",
  "type": "ec2",
  "user_id": "12345"
  }
  }

  HTTP/1.1 201 Created
  Date: Tue, 30 Aug 2016 19:14:54 GMT
  Server: Apache/2.4.7 (Ubuntu)
  Vary: X-Auth-Token
  Content-Length: 383
  Content-Type: application/json

  {"credential": {"user_id": "12345", "links": {"self":
  
"[ENDPOINT]/v3/credentials/141ce7a938b5973dd71c90bcdd7e4097317ee7374259cf6d8774fdfd86c1f8ea"},
  "blob":
  "{\"access\":\"alert(2)\",\"secret\":\"secretKey\"}",
  "project_id": "12345", "type": "ec2", "id":
  "141ce7a938b5973dd71c90bcdd7e4097317ee7374259cf6d8774fdfd86c1f8ea"}}

  = /EXAMPLE =

  The id from the example above is
  "141ce7a938b5973dd71c90bcdd7e4097317ee7374259cf6d8774fdfd86c1f8ea",
  which is the same as the SHA256 value of "alert(2)"
  (you can test this with `echo -n "alert(2)" | openssl
  dgst -sha256` on *nix)

  The documentation here seems to show MD5s and possibly tenant IDs used
  as "access" values: http://developer.openstack.org/api-
  ref/identity/v3/?expanded=assign-role-to-user-on-projects-owned-by-
  domain-detail,create-policy-detail,show-credential-details-detail
  ,list-credentials-detail,create-credential-detail#list-credentials

  Bruteforcing an actual MD5 isn't a huge security risk (i.e. trying to
  predict all 32 characters from thin air), but if the MD5 is a hash of
  a known value (i.e. the string "admin"), it would be trivial to test
  for common values:

  md5(admin) = 21232f297a57a5a743894a0e4a801fc3
  sha256(21232f297a57a5a743894a0e4a801fc3) = 
465c194afb65670f38322df087f0a9bb225cc257e43eb4ac5a0c98ef5b3173ac

  If tenant IDs are used, this task becomes even easier: just generate
  SHA256 hashes for 0 - 99

  A non-admin user can determine whether there are credentials using a
  given access key by attempting to access the resource from its sha256
  url identifier:

  = EXAMPLE REQUESTS =

  Existing credential

  GET 
/v3/credentials/141ce7a938b5973dd71c90bcdd7e4097317ee7374259cf6d8774fdfd86c1f8ea
 HTTP/1.1
  Host: [ENDPOINT]
  X-Auth-Token: [NON-ADMIN TOKEN]
  Content-Type: application/json
  Connection: close

  HTTP/1.1 403 Forbidden
  Date: Tue, 30 Aug 2016 19:55:24 GMT
  Server: Apache/2.4.7 (Ubuntu)
  Vary: X-Auth-Token
  Content-Length: 140
  Content-Type: application/json

  {"error": {"message": "You are not authorized to perform the
  requested action: identity:get_credential", "code": 403, "title":
  "Forbidden"}}

  Non-existent credential

  GET /v3/credentials/deadbeef HTTP/1.1
  Host: [ENDPOINT]
  X-Auth-Token: [NON-ADMIN TOKEN]
  Content-Type: application/json

  HTTP/1.1 404 Not Found
  Date: Tue, 30 Aug 2016 20:03:38 GMT
  Server: Apache/2.4.7 (Ubuntu)
  Vary: X-Auth-Token
  Content-Length: 96
  Content-Type: application/json

  {"error": {"message": "Could not find credential: deadbeef",
  "code": 404, "title": "Not Found"}}

  = /EXAMPLE =

  It is also possible to get a 500 error by creating a credential with
  an invalid character in the "access" key:

  = EXAMPLE REQUEST =

  POST /v3/credentials HTTP/1.1
  Host: [ENDPOINT]
  X-Auth-Token: [ADMIN TOKEN]
  Content-Length: 212
  Content-Type: application/json

  {
  "credential": {
  "blob": "{\"access\":\"\u\",\"secret\":\"secretKey\"}",
  "project_id": "12345",
  "type": "ec2",
  "user_id": "12345"
  }
  }

  HTTP/1.1 500 Internal Server Error
  Date: Tue, 30 Aug 2016 20:06:16 GMT
  Server: Apache/2.4.7 (Ubuntu)
  Vary: X-Auth-Token
  Content-Length: 143
  Content-Type: application/json

  {"error": {"message": "An unexpected error 

[Yahoo-eng-team] [Bug 1618615] Re: Potential information disclosure in EC2 "credentials"

2017-05-23 Thread Tristan Cacqueray
Switched to public security, closed the OSSA task and added an OSSN task
based on above comments.


** Description changed:

- This issue is being treated as a potential security risk under embargo.
- Please do not make any public mention of embargoed (private) security
- vulnerabilities before their coordinated publication by the OpenStack
- Vulnerability Management Team in the form of an official OpenStack
- Security Advisory. This includes discussion of the bug or associated
- fixes in public forums such as mailing lists, code review systems and
- bug trackers. Please also avoid private disclosure to other individuals
- not already approved for access to this information, and provide this
- same reminder to those who are made aware of the issue prior to
- publication. All discussion should remain confined to this private bug
- report, and any proposed fixes should be added to the bug as
- attachments.
- 
- 
  When creating a "credential" in Keystone, instead of using uuid.uuid4()
  like in most places to generate a unique identifier, the id is created
  from the SHA256 hash value of whatever is passed in as the "access" key
  in the POST request (Code here:
  
https://github.com/openstack/keystone/blob/master/keystone/credential/controllers.py#L36-L60)
  
  = EXAMPLE REQUEST =
  
  POST /v3/credentials HTTP/1.1
  Host: [ENDPOINT]
  X-Auth-Token: [ADMIN TOKEN]
  Content-Length: 231
  Content-Type: application/json
  
  {
  "credential": {
  "blob": 
"{\"access\":\"alert(2)\",\"secret\":\"secretKey\"}",
  "project_id": "12345",
  "type": "ec2",
  "user_id": "12345"
  }
  }
  
  HTTP/1.1 201 Created
  Date: Tue, 30 Aug 2016 19:14:54 GMT
  Server: Apache/2.4.7 (Ubuntu)
  Vary: X-Auth-Token
  Content-Length: 383
  Content-Type: application/json
  
  {"credential": {"user_id": "12345", "links": {"self":
  
"[ENDPOINT]/v3/credentials/141ce7a938b5973dd71c90bcdd7e4097317ee7374259cf6d8774fdfd86c1f8ea"},
  "blob":
  "{\"access\":\"alert(2)\",\"secret\":\"secretKey\"}",
  "project_id": "12345", "type": "ec2", "id":
  "141ce7a938b5973dd71c90bcdd7e4097317ee7374259cf6d8774fdfd86c1f8ea"}}
  
  = /EXAMPLE =
  
  The id from the example above is
  "141ce7a938b5973dd71c90bcdd7e4097317ee7374259cf6d8774fdfd86c1f8ea",
  which is the same as the SHA256 value of "alert(2)"
  (you can test this with `echo -n "alert(2)" | openssl
  dgst -sha256` on *nix)
  
  The documentation here seems to show MD5s and possibly tenant IDs used
  as "access" values: http://developer.openstack.org/api-
  ref/identity/v3/?expanded=assign-role-to-user-on-projects-owned-by-
  domain-detail,create-policy-detail,show-credential-details-detail,list-
  credentials-detail,create-credential-detail#list-credentials
  
  Bruteforcing an actual MD5 isn't a huge security risk (i.e. trying to
  predict all 32 characters from thin air), but if the MD5 is a hash of a
  known value (i.e. the string "admin"), it would be trivial to test for
  common values:
  
  md5(admin) = 21232f297a57a5a743894a0e4a801fc3
  sha256(21232f297a57a5a743894a0e4a801fc3) = 
465c194afb65670f38322df087f0a9bb225cc257e43eb4ac5a0c98ef5b3173ac
  
  If tenant IDs are used, this task becomes even easier: just generate
  SHA256 hashes for 0 - 99
  
  A non-admin user can determine whether there are credentials using a
  given access key by attempting to access the resource from its sha256
  url identifier:
  
  = EXAMPLE REQUESTS =
  
  Existing credential
  
  GET 
/v3/credentials/141ce7a938b5973dd71c90bcdd7e4097317ee7374259cf6d8774fdfd86c1f8ea
 HTTP/1.1
  Host: [ENDPOINT]
  X-Auth-Token: [NON-ADMIN TOKEN]
  Content-Type: application/json
  Connection: close
  
  HTTP/1.1 403 Forbidden
  Date: Tue, 30 Aug 2016 19:55:24 GMT
  Server: Apache/2.4.7 (Ubuntu)
  Vary: X-Auth-Token
  Content-Length: 140
  Content-Type: application/json
  
  {"error": {"message": "You are not authorized to perform the
  requested action: identity:get_credential", "code": 403, "title":
  "Forbidden"}}
  
  Non-existent credential
  
  GET /v3/credentials/deadbeef HTTP/1.1
  Host: [ENDPOINT]
  X-Auth-Token: [NON-ADMIN TOKEN]
  Content-Type: application/json
  
  HTTP/1.1 404 Not Found
  Date: Tue, 30 Aug 2016 20:03:38 GMT
  Server: Apache/2.4.7 (Ubuntu)
  Vary: X-Auth-Token
  Content-Length: 96
  Content-Type: application/json
  
  {"error": {"message": "Could not find credential: deadbeef", "code":
  404, "title": "Not Found"}}
  
  = /EXAMPLE =
  
  It is also possible to get a 500 error by creating a credential with an
  invalid character in the "access" key:
  
  = EXAMPLE REQUEST =
  
  POST /v3/credentials HTTP/1.1
  Host: [ENDPOINT]
  X-Auth-Token: [ADMIN TOKEN]
  Content-Length: 212
  Content-Type: application/json
  
  {