AWS security credential formats


RSS feed

This post is just some interesting things I've found when staring at AWS access keys, secret keys, and session tokens for too long.

What are security credentials?

When you use the AWS API, as opposed to logging into the console with your web browser, you use an access key and secret key, and potentially a session token as explained in Understanding and Getting Your Security Credentials. Access keys look like AKIAJSIE27KKMHXI3BJQ and secret keys looks like 5bEYu26084qjSFyclM/f2pz4gviSfoOg+mFwBH39.

When using IAM roles, or if you request a session token with the command aws sts get-session-token, you'll get an access key, secret key, and a session token. The session token looks like:


The access key and session token, if it exists, are passed in the HTTP headers sent in requests to AWS when you use the API. Most tools use TLS for making requests, so the communication is encrypted, but it is not required by AWS (although you should!), and those two values don't need to be kept secret. It is only the secret key that actually has to be kept secret, as it is used to sign requests with a SHA256 HMAC as a way of authenticating them.

You'll actually see the access keys and session token values in Cloudtrail logs, so you don't need to freak out when you see them there, as an attacker can't do anything with them if they see your logs.

The code for signing these requests can be seen in the botocore library here, and is described by AWS at Authenticating Requests (AWS Signature Version 4).

For a quick history lesson, Colin Percival identified issues in the original version of AWS's signing (v1) in his post from 2008 AWS signature version 1 is insecure. Minor improvements have been made to the specification with each new version, and it is now at version 4.

Auditing tip

If you're doing any auditing, you can still find tools today that use HTTP by default instead of HTTPS. For example, until a few months ago when I emailed the developer of the tool "S3 Browser", they were still using HTTP by default (see the write-up on that here).

You should also ensure the tools are using version 4 of the signing specification, which they should be if they use an up to date version of the boto library.

Access keys and IDs

When a session token is involved, such that the keys will all expire, the access key begins with the prefix ASIA, otherwise it beings with AKIA. All random looking ID's on AWS have their own 4 letter prefixes that identify what they are. For example, a user ID starts with AIDA and role IDs start with AROA. I don't know of any list that describes all of them.

Other than the prefix, the random looking chracters are all A-Z and 2-7 (no 0,1,8,9). This gives 32 possible characters, or the equivalent of 5 bits of information in each character. By not having a zero or one, AWS avoids confusion with the letters "O" and "L".

If you line up these random looking ID's, you'll spot another pattern:


The 5th letter is always I or J and the last letter is always A or Q, so each of those characters only gives one bit of information.

So in total each ID carries 1 + 1 + 14*5 = 72 bits of information, or 272 possible values.

Secret keys

Here is a set of 10 secret keys:


The only non-letter and non-number values are "+" and "/", so these seem to be base64 encoded. The base64 decoded values appear completely random, providing 30 bytes of random, or 2240 possible values.

This is the only value that needs to be kept secret, so having such a large random is good to see.

Session tokens

Session tokens are much longer strings and can vary slightly in length. Here is an example:


Again, these are base64 encoded, and this time when we decode them and view them in a hex editor, we can see they have some formatting.

00000000  15 0a 03 61 77 73 10 f3  ff ff ff ff ff ff ff ff  ||
00000010  01 1a 0c fb f9 18 f0 21  45 6f 29 c3 af e7 b2 22  |.......!Eo)...."|
00000020  ac 01 9b bb b1 90 c2 5c  fb 44 04 4b ab c6 6b f2  |.......\.D.K..k.|
00000030  57 5a fe 9d 6c b5 23 85  4f 6d d2 09 57 e8 83 9e  |WZ..l.#.Om..W...|
00000040  8b 70 4b 73 ca 23 28 fe  c8 39 ce 7a 28 0c 7f 6c  |.pKs.#(..9.z(..l|
00000050  a9 f7 2d 83 83 d0 fb af  9d 6f 59 4c 94 41 07 dc  |..-......oYL.A..|
00000060  79 98 bd ff c1 a1 cb 7f  11 70 e9 d6 22 68 4d 75  |y........p.."hMu|
00000070  53 f9 ce 5d 73 87 ce 45  1f 3e b2 b5 e3 e8 fa 9b  |S..]s..E.>......|
00000080  87 67 07 d3 92 e0 10 1e  3d fc 83 2e 95 17 fd 78  |.g......=......x|
00000090  19 4d 7b a8 37 0f 4d f8  e1 6c 44 c6 a8 49 a1 f1  |.M{.7.M..lD..I..|
000000a0  05 fa c5 f9 96 94 ed 19  ad 39 ac 02 8e 19 1d ab  |.........9......|
000000b0  fc cb 36 db 97 7a 18 74  22 c8 08 e8 cc 84 e3 b5  |..6..z.t".......|
000000c0  a1 8f 81 fc 38 94 46 4d  d9 2c f8 da 5f 2a 28 d8  |....8.FM.,.._*(.|
000000d0  8a a5 d9 05                                       |....|

Bytes 4-6 are the word aws, and bytes 9-16 are the value ff. I haven't identified anything else from this.

All of these patterns are undocumented by AWS and therefore subject to change.

If you're looking for help with your AWS security, reach out to me!