Comment 20 for bug 1618615

Revision history for this message
Robert Clark (robert-clark) wrote : Re: [Bug 1618615] Re: Potential information disclosure in EC2 "credentials"

Replying by email because my 2FA has broken and I can't log into LP.

I agree that documentation enhancements would be useful. Luke we could
consider rolling this enhanced guidance into an OSSN but I share your
concerns about posting something without a clear fix/workaround.

-Rob

On Wed, May 24, 2017 at 3:58 PM, Charles Neill <email address hidden>
wrote:

> The main thing that I think would help is updating the documentation to
> include more reasonable examples. As stated above, I think the examples
> provided in the docs increase the risk of someone storing
> sensitive/easily guessed information where it could be exposed by this
> vector.
>
> --
> You received this bug notification because you are a member of OSSG
> CoreSec, which is subscribed to the bug report.
> 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:
> New
>
> 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\":\"<script>alert(
> 2)</script>\",\"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/141ce7a938b5973dd71c90bcdd7e40
> 97317ee7374259cf6d8774fdfd86c1f8ea"},
> "blob":
> "{\"access\":\"<script>alert(2)</script>\",\"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 "<script>alert(2)</script>"
> (you can test this with `echo -n "<script>alert(2)</script>" | 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 - 999999
>
> 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/141ce7a938b5973dd71c90bcdd7e40
> 97317ee7374259cf6d8774fdfd86c1f8ea 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\":\"\uffff\",\"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 prevented the server
> from fulfilling your request.", "code": 500, "title": "Internal Server
> Error"}}
>
> ===== /EXAMPLE =====
>
> I'm unsure what the security impact would be here, mainly because of
> the ambiguous examples provided in the Keystone API documentation
> (linked above). If either of the 2 scenarios I outlined is a
> reasonable use case (i.e. MD5 of a guessable value, or tenant IDs),
> there may be a risk of information leakage by brute-force. It would
> also be possible to prevent others from creating credentials with a
> given access key by simply creating lots of credentials in Keystone
> with predictable access keys. This would cause a collision whenever
> attempting to create a credential set with an access key that has
> already been used.
>
> If, on the other hand, the credentials are always in the format
> described by AWS here ( link:
> https://docs.aws.amazon.com/AWSSimpleQueueService/latest/
> SQSGettingStartedGuide/AWSCredentials.html
> ), it would require a huge number of requests to bruteforce the access
> key (though it would not be impossible). However, it would be
> possible, using the approach described above with a regular user
> token, to determine whether a known EC2 access key was in place as a
> credential in a given Keystone database.
>
> I'm unclear on the utility of using SHA256 for the identifier at all
> here, since random UUIDs would make this potential issue moot.
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/keystone/+bug/1618615/+subscriptions
>