The Cloud has a serious and fragile vulnerability: Access TokensRobert Levine
The October 2023 OKTA support system attack that so far has publicly involved Cloudflare, 1Password and BeyondTrust informs us just how fragile and vulnerable our cloud applications are because they are built using access tokens to authenticate counterparties.
If a valid access token is stolen by a threat actor, most systems don’t have the internal defenses built-in to detect that a valid token is now being used by a threat actor, leaving them completely vulnerable. To be clear, reliance on access tokens to authenticate counter parties, is NOT unique to Okta and could happen to any of a myriad of cloud services to application functionality such as email, CRM, accounting/finance are just some examples.
What are access tokens and why do they make our cloud infrastructure and applications so vulnerable? Simple, they are what is known as a bearer token, which means that if you possess the token you have the access rights granted to the original possessor of the token. By design the recipient is required to check if the token is still valid and if so, grants access.
Because of their power, access tokens must be protected at all costs from theft. There are four key aspects to protecting tokens:
- Always keep them in memory, secured (no persistent storage);
- Always transport them over a secure channel (should be mutually authenticated)
- Keep their lifetimes as short as possible (minutes for sensitive access rights)
- Ensure they are only accepted from known and expected sources (security groups, privacy groups, segmentation)
Deviate from these simple rules and applications (cloud, hybrid and classical) that rely on access tokens are extremely vulnerable.
Looping back to the recent Okta breach, it boils down to stolen access tokens due to 3 out of the 4 rules being breached. The only rule that wasn’t fully breached was number 2, which by public reporting does not appear to have been a mutually authenticated connection.
What is an access token?
Think of an access token being similar to a ticket used to get into a sporting event with some notable differences Presenting a valid sporting ticket to a stadium gate agent allows you to enter the venue (authentication). Once inside the stadium gate, you go to your section, row and seat for that ticket (scope/authorization).
Access tokens, technically called OAUTH tokens, work like tickets with two notable differences: reuse and copy protection.
- Reuse: Sporting tickets can only be used once for a specific event. Access tokens are reusable until they expire or are revoked.
- Copy protection: Sporting tickets have copy protection controls such as holograms on physical tickets or cryptographic tying of electronic tickets to a specific phone. Access tokens have no copy controls built into them and instead rely on the rules defined above.
How are access tokens generated and used?
Without getting down into the weeds of how modern Identity Providers (IDPs) and protocols work, the answer is fairly simple in that an Agent (human or system) presents credentials to an IDP and requests access tokens to a resource (e.g. system, application, database, etc,..). The credentials presented to the IDP can be a username/password augmented with multi-factor authentication, a certificate or other types of secrets. If successfully authenticated, the IDP sends the Agent an access token. To protect access tokens, they should only be sent over properly encrypted channels with the valid time period set as short as possible, though the downside to short time durations means the Agent has to re-authenticate to the IDP more often..
Once an Agent has their access tokens, they present them to resources to gain access. The resource validates the tokens with the IDP to see if they have been revoked or expired and if not, grants access based on the authorization rights associated with the Agent.
How do you protect access tokens?
Given how powerful access tokens are, they must be protected at all costs.
Going back to the four methods of protection listed earlier, the first order of business is to never persistently store access tokens. Avoiding persistent storage greatly reduces the attack surface of a threat actor to get a copy of a token. As a side note, ensuring that the original credentials presented to the IDP get the access tokens in the first place should also not be persisted as well. Instead, applications should make use of Key Management Services or Vaults.
The second task is to ensure that tokens are always sent over secure channels which in the majority of cases means using Transport Layer Security (TLS), Using TLS versions older than V1.2 should be avoided as these are no longer considered secure and have been deprecated.
TLS has two modes of operation: One-way (most common) and mutual.
With one-way TLS the channel has only data privacy and data integrity but misses out on authentication due to the fact that only the server providing the resource has a certificate. While many human based use cases can be sufficiently secured using one-way-TLS due to the fact that a human can be asked for additional authentication factors by the IDP as a part of the initial IDP login, it usually leaves open vulnerabilities for machine-to-machine connections where mutual TLS should be used as it serves as a critical second factor for authentication.
Ideally mutual TLS (mTLS) connections should be used, whereby both sides of the connection mutually authenticate each other at the transport layer using certificates or even pre-shared-keys which acts as an additional authentication factor. The use of mTLS ensures the Agent is authenticated with the server to validate that connections are only coming from valid and known sources as opposed to a threat actor’s machine armed with a stolen access token.
The third task is to ensure access tokens have as short a lifetime as possible such that if they are stolen, their useful lifetime is limited. For human Agents, this translates to having to re-authenticate with the IDP, so many of these use cases tend to have lifetimes set in hours or days. For machine based Agents, the lifetime should be set as short as possible without putting unnecessary burden on the IDP. Often this translates to 15 to 60 minutes.
The four task is to ensure that some means of restricting who can connect to servers (defense-in-depth) is vital in that this serves a very significant hurdle to overcome should an access token be stolen. Servers that require all connections to be mTLS based protects itself with a critical second factor ensuring that only authenticated connections can be used to send access tokens. This second factor significantly reduces the attack surface in which access tokens can be abused. Using mTLS combined with cloud privacy or network security groups or layer 3 segmentation solutions go even further with their defense-in-depth attack surface reductions.
Applications and infrastructure must ensure they adhere to solid code and implementation practices such as the ones described in this blog when access tokens are used as the center of the authentication strategy. Best practice of short expirations, never persisting tokens and using mTLS for all connections combined with network capabilities such as network or privacy groups or segmentation are all required to ensure sufficient defense-in-depth protective controls are in place.