Supply Chain Attacks: How to Mitigate OAuth Token Theft
Being responsible for system integrations is not an easy task. The security perimeter has tilted from the network to trust. With the rising dependency on SaaS services and token-based access comes great flexibility, often with a high degree of security. However, there are pitfalls and dangers that need to be taken seriously.
These days, system administrators aren’t the only ones who can sign up and connect company systems to other systems. Signing in with your company Google account to a service, accepting the delegated access allowing the service to send emails on your behalf, adding documents to the drive or updating the calendar might open up entry points into the organization that is completely hidden from the IT department’s sight.
When shifting the view to things that affect the supply chain for software companies, the picture gets darker. Many companies use SaaS services for source code control, CI/CD pipelines, test frameworks, artifact dependencies, etc. Most often, the focus for keeping the supply chain safe lies within the realm of dependency management: controlling the external libraries that are pulled into the software build. This is of course a very important area to keep under control, but it is far from the only one.
In recent years we have seen a growing number of supply chain attacks targeting downstream services that are less critical to the infrastructure but that have OAuth access tokens to integrate with the upstream service.
Think of it this way: It is often possible to generate keys or tokens for a service that an employee would like to connect to. Sometimes these are personal access tokens, sometimes API keys or similar. Let’s assume system A is a CI system, and system B is a reporting tool. Then an employee generates a token in system A and enters it in system B. This means that even if the user has multifactor access enabled for system A, the tokens generated for the integration are not protected by it.
Later a malicious actor gains access to system B, which, didn’t have as stringent security as system A, and steals the tokens. These stolen tokens can then be used to gain access without multifactor authentication or even user interaction.
Focus often lies on scrutinizing the main systems an organization uses. These are often vetted for security, but it’s easy to overlook the integration possibilities possible with employees’ accounts.
How can we enable the multifactor concept for tokens? Let’s begin by looking at the most common token out there — the OAuth access token. It is the token that a system gets when it requests access to an API. The most common type of access token is called bearer tokens. These can be thought of as cash. If you find a dollar bill on the street, you can pick it up and use it. You don’t need to prove ownership of that bill.
A credit card, on the other hand, requires you to enter a PIN code when using it (for the most part at least), so it essentially represents two factors: something you have and something you know. A bearer token is cash; any system that has it can use it.
Luckily there are other types of access tokens in OAuth: proof of possession tokens, more formally called sender-constrained tokens. These require the service that uses them to also prove that they are the legitimate owner of the token.
There are different methods of doing this, but all of them involve the sender to prove that it is in possession of a private key. The token contains information about the corresponding public key, allowing the receiver of the token to verify that the token was sent by a system that is entitled to send it. Similar to something you have (the token) and something you know (the private key). Sounds familiar.
So why are we not using these types of tokens everywhere? The answer is, unfortunately, that it adds complexity. If system A used sender-constrained tokens, it wouldn’t be enough to steal the tokens to gain access to system B. You would also need to get hold of the private key that B possesses.
Cash is easier to use since you don’t need to sign up for a credit card. But once you’ve signed up, the card is simple. Tokens are the same. The process of setting this up and writing the code needed is a bit more involved, but once it’s in place, it will have minimal impact on the integrations.
There are different ways to go about sender-constrained tokens: tokens bound to mutual TLS certificates and tokens using Demonstration Proof of Possession at the application layer (DPoP) are the two current methods. There’s interesting work happening at the Internet Engineering Task Force (IETF) with the new HTTP message signatures specification, but it is still early for general adoption.
The integrations between SaaS services will continue to grow and will continue to be hard to outline. But if we can get SaaS vendors to shift from API keys or OAuth bearer access tokens to OAuth sender constrained tokens, hackers’ lives will become much more challenging.