Executive Summary

As more and more business is conducted from remote locations, attackers are focusing their efforts on exploiting the key technologies – like Zoom and Microsoft Teams – that companies and their employees depend on to stay connected.

We found that by leveraging a subdomain takeover vulnerability in Microsoft Teams, attackers could have used a malicious GIF to scrape user’s data and ultimately take over an organization’s entire roster of Teams accounts.

Since users wouldn’t have to share the GIF – just see it – to be impacted, vulnerabilities like this have the ability to spread automatically.

This vulnerability would have affected every user who uses the Teams desktop or web browser version.

CyberArk worked with Microsoft Security Research Center under Coordinated Vulnerability Disclosure after finding the account takeover vulnerability and a fix was quickly issued.

Introduction

Teams, Slack or maybe Zoom? Which applications do you use? All are extremely popular with business users normally, but have been nothing short of essential during this “new norm” where businesses are working hard to stay connected to employees, customers and partners.

These days everything is being done remotely – from job interviews to business meetings and even social gatherings. Now, more than ever, these platforms are our “go-to” for almost everything from a simple chat with a team member to a company-wide all-hands meeting. The amount of data that goes into these applications is enormous and often includes confidential information from user names and passwords to top-secret business information – making them prime targets for attackers.

Imagine the following scenario. An attacker sends a GIF or an image to a victim and gets control over their account. This vulnerability worked just that way and had the potential to take over an organization’s entire roster of Microsoft Teams accounts.

Teams Background

For those of you who are unfamiliar with Microsoft Teams, it’s a leading communication and collaboration platform combining persistent workplace chat, video meetings, file storage, collaboration on files and integration with applications.

One of the main benefits of Teams is that it provides first-party integration with a company’s Office 365 subscription and also features extensions that can integrate with non-Microsoft products.

Figure 1: Microsoft Teams.

Given the prevalence of Teams in organizations of all sizes and the rise of its use (and that of other communications platforms like it), we wanted to dig in a bit deeper.

Fortune Cookie

During the research, we noticed something very interesting in the way Teams passes the authentication access token to image resources.

Without getting into too many technical details, every time you open Teams, your client creates a new temporary token or access token. This access token, in the form of JWT, is created by Microsoft’s authorization and the authentication server – “login.microsoftonline.com.“

Besides the initial access token, there are many others created for Teams, some of which are used to access different services like SharePoint, Outlook and many more.

The Teams client uses one of these created tokens to allow a user to see images shared with them or by them, as those images are stored on Microsoft’s servers, which applies authorization control. This token, called “skype token,” can also be seen as a cookie named “skypetoken_asm.” While this token has more usages more than just giving access to images, that’s what we’ll focus on here.

Rest API is today’s common approach to exposing a set of operations and commands for applications, especially web applications like Teams. Complex applications like Teams mostly use more than one API endpoint, because they need to communicate with more than one service.

Eventually the Teams client needs to send the user’s action (like sending a message) to the relevant API’s endpoint, but how does the API endpoint know to associate the incoming action to the right user? Authentication is key to answering this question.

There are many ways to authenticate users in front of APIs — one of the most common techniques is to send an access token through an authorization header. Teams uses this method to authenticate the user in front of its API interface, but this causes a significant problem when it comes to images.

Here’s why:

Loading images is a bit more complicated authentication-wise if you don’t base your user authentication method on cookies.

Teams manages most, if not all, the authentication tokens (JWT tokens) in the browser’s local storage – and cookies are only a small part of its authentication process.

In some cases, like loading images, you might encounter a problem accessing those images, because you need somehow to pass the authentication token to the server that holds the images.

To solve this problem, there is a way to fetch image content with JavaScript code as a blob and then set the src attribute of the IMG tag to the created blob.

Another way to solve this is by creating an access token to the resource in the form of a hash or similar. We can see this approach used by Facebook in its platform for accessing images, which are formatted like the following link:

https://scontent.fsdv2-1.fna.fbcdn.net/v/t1.0-9/r270/10101010_10101010_10101010_o.jpg?_nc_cat=102&_nc_sid=111111&_nc_ohc=ABC&_nc_ht=scontent.fsdv2-1.fna&oh=9e2a890f5f05001e01c16d9731983d3e&oe=2AB1FCCC.

Teams developers decided to go with a combination of different solutions.

In some cases, Teams uses the browser’s regular resource loading, which means that Teams just sets a “src” attribute of a URI to an HTML IMG tag (Figure 2.)

<img ng-show= "!giphyCtrl.playVideo" ng-src= "https://media2.giphy.com/media/gB4KWtd3uSsJq/giphy.gif" height= "240" width= "480" load-image-handler src= "https://media2.giphy.com/media/gB4KWtd3uSsJq/giphy.gif" >

Figure 2: IMG element in Teams.

But, again, there is a big problem here. How does Teams make sure that we will be able to see the content? After all, the media shared between users should be restricted so that only they can see it. That means Teams must have restrictions on access permissions for the content.

The way that Microsoft decided to solve this challenge was by establishing a cookie called “authtoken” and “skypetoken_asm.” Here’s why this could present a problem.

Figure 3: “authtoken” cookie.

As seen above, those cookies are very interesting. Let’s look at what they contain exactly, starting with the “authtoken” cookie.

The ”authtoken” cookie contains an access token in the form of a JWT and is set to be sent to *.teams.microsoft.com.

The JWT audience for this access token is api.spaces.skype.com, meaning that only this specific domain will accept this token. This endpoint doesn’t handle action requests that an attacker might find interesting like reading or sending messages, so the obvious question is what endpoint does expose those actions? Well, we need to find it and the token required to make those calls.

We looked into the Teams client’s network traffic to find the requests that contain chat messages so that we could find out which token they use to perform those actions.

GET https://amer.ng.msg.teams.microsoft.com/v1/users/ME/conversations/19%3A...%40unq.gbl.spaces/messages?view=msnp24Equivalent|supportsMessageProperties&pageSize=200&startTime=1 HTTP/1.1 Host : amer.ng.msg.teams.microsoft.com Connection : keep-alive Pragma : no -cache Cache - Control : no -cache x-ms-session-id: 00000000000 - 0000 - 0000 - 0000 - 00000000000 BehaviorOverride : redirectAs404 x-ms-scenario-id: 00 x-ms-client-cpm: ApplicationLaunch x-ms-client-env: x-ms-client-type: User - Agent : Mozilla / 5.0 ( Windows NT 10.0 ; Win64 ; x64) AppleWebKit / 537.36 (KHTML, like Gecko ) Chrome / 80.0 . 3987.132 Safari / 537.36 ClientInfo : Accept : json Sec - Fetch - Dest : empty x-ms-client-version: x-ms-user-type: user Authentication : skypetoken=eyJhbGciOiJSUzI1NiIsImtpZCI6IkVhc3RlckVnZyA6KSIsInR5cCI6IkpXVCJ9.eyJ... Origin : https://teams.microsoft.com Sec - Fetch - Site : same-site Sec - Fetch - Mode : cors Referer : https://teams.microsoft.com/_ Accept - Encoding : gzip, deflate, br Accept - Language : en-US,en;q= 0.9

Figure 4: Teams client fetching messages request.

In Figure 4, we can see that, to make the fetching messages request, the client sent only one authentication token, which can be found in the “Authentication” header.

The name of the token looks very familiar – “skypetoken.”

So, now we know that for making “valuable” requests, we need to get a skype token. So how can we get one? We looked further into the network traffic, and in the end, we hit the jackpot.

Apparently, the request for creating the skype token and authentication token required for creating this skype token is none other than the authtoken we mentioned before.

POST /api/authsvc/v1. 0 /authz HTTP/ 1.1 Host : teams.microsoft.com Connection : close Content - Length : 0 Pragma : no -cache Cache - Control : no -cache x-ms-session-id: 00000000000 - 0000 - 0000 - 0000 - 00000000000 x-ms-scenario-id: 00 x-ms-user-type: user x-ms-client-env: x-ms-client-type: Authorization : Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IktleXMiLCJraWQiOiJLZXlzRXZlcnlXaGVyZSJ9.eyJ... Accept : application/json, text/plain, */* X-Client-UI-Language: en-us Sec-Fetch-Dest: empty ms-teams-authz-type: TokenRefresh x-ms-client-version: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36 Origin: https://teams.microsoft.com Sec-Fetch-Site: same-origin Sec-Fetch-Mode: cors Referer: https://teams.microsoft.com/_ Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 Cookie: {redacted}

Figure 5: Teams client creates skypetoken request.

Now with both tokens, the access token (authtoken) and the skype token,

we’re able to make APIs calls/actions through Teams API interfaces, which lets you send messages, read messages, create groups, add new users or remove users from groups, change permissions in groups, etc.

So, to summarize, if you can get your hands on this authtoken, you can easily create a skype token – and that’s a really interesting thing for an attacker to take advantage of.

You’re probably now asking yourself, “how would the attacker take advantage of that?” After all, this cookie is only sent to teams.microsoft.com or any sub-domain under teams.microsoft.com.

You might already have guessed where we are heading.

We found that the two following subdomains were vulnerable to a subdomain takeover:

If an attacker can somehow force a user to visit the sub-domains that have been taken over, the victim’s browser will send this cookie to the attacker’s server and the attacker (after receiving the authtoken) can create a skype token. After doing all of this, the attacker can steal the victim’s Teams account data.

In terms of exploiting this vulnerability, there are a few steps that the attacker needs to go through.

First, the attacker needs to issue a certificate for the compromised sub-domains. The reason for this is that the “authtoken” cookie is flagged as secure, which means that the browser will only send this cookie via a secure channel – HTTPS.

But, that shouldn’t be a problem, because the certificate issuers will issue a valid certificate if you can prove that you are the owner of this domain or, in our case, the subdomain.

One of the ways to prove that you are the rightful owner is by uploading a file to a specific path and, because the compromised subdomain points to the attacker’s server, they can pass this challenge very easily.

Up to this point, we’ve covered the main issue of letting a potential attacker take over Teams’s accounts, and we also said that this attack could be exploited by sending a simple link to the victim.

It’s pretty well understood that sending a link is a bit old fashioned and many people know that clicking on unknown links can lead is a good way to become a victim of phishing campaigns, malware, ad-ware, ransomware, etc. Because of this, we tried a different approach.

Enter the Evil GIF

As we mentioned before, the reason that Teams sets the “authtoken” cookie is to authenticate the user to load images in domains across Teams and Skype.

We considered this approach as well, sending an image to our victim with an “src” attribute set to the compromised sub-domain via Teams chat. When the victim opens this message, the victim’s browser will try to load the image and this will send the authtoken cookie to the compromised sub-domain.

This means the attacker will get their hands on the victim’s authtoken, allowing the attacker to create a skype token and ultimately providing the attacker a pathway to scrape all the victim’s data.

Figure 6: Evil GIF.

Now you might be wondering what this looks like. It is actually pretty simple. The victim sees a regular GIF sent to them –- that’s it! In Figure 7, you can see what the user sees.

The victim will never know that they’ve been attacked, making the exploitation of this vulnerability stealthy and dangerous.

While limiting your organization to internal communication will reduce your exposure, we found that it is still possible to communicate with an outsider and any interaction that includes a chat interface with an outsider is enough to be affected by this vulnerability. A good example of this would be an invitation to a conference call with an outsider for a job interview.

Worm-like Vulnerability

One of the biggest and the scariest things about this vulnerability is that it can be spread automatically, similar to a worm virus.

The fact that the victim only needs to see the crafted message to be impacted is a nightmare from a security perspective. Every account that could have been impacted by this vulnerability could also be a spreading point to all other company accounts. The GIF could also be sent to groups (a.k.a Teams), which makes it even easier for an attacker to get control over users faster and with fewer steps.

POC

To illustrate this further, we made a video showing a POC exploit of this vulnerability.

Figure 8: POC video.

In addition, we also wrote a script that scrapes the victim’s conversation and threads and saves that to a local file, which you can see in the previous video and in Figure 9.

Figure 9: Stolen messages.

Who Could It Affect?

Every user who uses the Teams for desktop or web browser.

Mitigation & Response

We worked with Microsoft Security Research Center under Coordinated Vulnerability Disclosure after finding the account takeover vulnerability. Microsoft quickly deleted the misconfigured DNS records of the two subdomains, that were exposed and could be taken over. In addition, Microsoft has pushed more mitigations during the course of time and are continuing to develop more security features to prevent similar flaws in the future.

Conclusion

COVID-19 has forced many companies to move to full-time remote work – leading to a significant uptick in the number of users that use Teams or platforms like it. In an effort to maintain business as usual, companies are using video chats, instant messaging and file-sharing at a higher frequency. As we continue to lean on these platforms as a lifeline to normalcy, we can’t forget about security.

Even if an attacker doesn’t gather much information from a Teams’ account, they could still use the account to traverse throughout an organization (just like a worm). Eventually, the attacker could access all the data from your organization’s Teams accounts – gathering confidential information, meetings and calenders information, competitive data, secrets, passwords, private information, business plans, etc.

Maybe even more disturbing, they could also exploit this vulnerability to send false information to employees – impersonating a company’s most trusted leadership – leading to financial damage, confusion, direct data leakage, and more.

In this post, we aimed to demonstrate what could have happened if an attacker had managed to exploit this vulnerability. Treat your internal communication platforms like they contain your most top-secret and privileged information – because they actually might.

Thanks for reading,

@OmerTsarfati

Disclosure Timeline

23/03/20 — Vulnerability reported to Microsoft.

23/03/20 – Microsoft corrected misconfigured DNS records.

20/04/20 — Microsoft issued a patch.