Back when Teams initially launched, most of us were quite happy with its compliance story – unlike many of the new apps that appeared over the last few years, Teams actually had a good coverage from the get go. This was largely thanks to the investments Microsoft has made in compliance features for the underlying workloads on which Teams is built. Even back then however, a few gaps were apparent, such as the inability to capture Bot interactions or messages ingested by connectors.
Additional issues arose around the handling of Hybrid users with mailboxes hosted on-premises, as a copy of the IM conversations cannot be stored for those. Even in cases where all the data was properly stored, retrieving it provides issues on its own, as each individual contribution is stored as separate message, greatly complicating the task for any legal officer. Moreover, the existence of the “chat service” that stores copies of the messages somewhere in Azure remains an unknown factor and a wildcard, with little to no public information provided on its workings and compliance status.
Fast forward few months and another round of compliance related issues became apparent with the introduction of support for Guest users. As Guest users do not have a mailbox homed in the tenant, they are represented by mail user objects and their contributions to Teams conversations are not captured in some cases. Even when contributions are actually captured, the method used can cause some trouble.
The thing is, conversation items are stored inside the Team (or user) mailbox by using the Primary SMTP address of each participant as identifier. For users with mailboxes in Exchange Online this approach works flawlessly, as the Primary SMTP address is a unique identifier. However, if the user does not have a mailbox in Exchange Online, or has it in another organization’s tenant, things are different. Such user is represented by a “mail user” object, and being a mail user, it can have *any* email address associated with it. Any!
Exchange Online does not enforce any restrictions as to what the email address(es) associated with a mail user look like, as by definition those objects can represent external users. Thus, it’s perfectly acceptable for a mail user to have an email address matching a domain that is not verified in your Office 365 tenant. For example, every Office 365 tenant out there can create a mail user with firstname.lastname@example.org for an email! However, that user cannot actually send messages via Exchange Online and in general has to use a UserPrincipalName associated with one of the domains you have verified in Office 365 if he is to access any Office 365 service, Teams included.
And therein lies the issue. While a mail user or a guest user has to login with the corresponding UPN in order to participate in Teams activities, any conversations he is part of are being stored using his Primary SMTP Address as the identifier. It’s much easier to understand the problem when an example is given, so let’s assume that some naughty person in my tenant decided to abuse this and created a mail user with email@example.com as the email address. The below example illustrates how easy is to create such mail user:
Now of course that’s just a simple example, so I didn’t bother to configure a proper display name, title and so on. Thus, it will be easy enough to spot that this user is not the actual Microsoft CEO. Technically, all of this is doable though, including adding the “(Guest)” suffix. So bear with me for a minute, and focus on the email address only.
Once this user is created and added to any Team, he can participate in the conversations in any of the Channels. Even without being member of a Team, he can still message users directly. For example, he can message an unsuspecting user and make them a job offer:
As mentioned above, in this simple example it’s easy enough to notice the discrepancy in user’s information, even without looking into the contact card. However, the topic at hand here is compliance, so let’s see what happens once an eDiscovery officer stumbles into the above example. Let’s assume a query has been run to return all Teams chats for my user (“Vasil” in the above example). This is what the legal officer will actually see:
Note the From address in the above dialog – an unsuspecting person will not be able to tell whether this is an actual Guest user or a Mail user with “spoofed” address. All he can see here is that the user is represented as firstname.lastname@example.org. A better solution would be to use the UserPrincipalName to populate the From field instead, as it is unique across all Office 365 tenants and can only be used in the tenant that “owns” the domain. Thus a mail user would have been represented via the email@example.com UPN in this particular tenant, and if Satya visited the tenant as a Guest user, his UPN would be satya_microsoft.com#EXTfirstname.lastname@example.org. Easily distinguishable.
Here’s another view of the same content search, presented this time as the CSV report file:
Again, the From and/or To fields use the Primary SMTP Address of the user, which can lead to confusion. Of course, looking at the actual IM item stored in the mailbox will produce the same results. Unless you know where to look, but more on this later.
Now, it’s important to understand that the method described above can only be exploited by users with permissions to manage mail user objects in your tenant. While you can certainly create a new tenant and provision any number of mail users with random addresses within them, to access the “target” tenant you still need to be invited (the invite doesn’t have to be received/accepted actually, but that’s a topic for another post). And even if you manage to get into the “target” tenant, the Guest (mail) user will automatically be created with an email address matching the UPN, thus mitigating the issue.
However, the user can still be edited after the process. For example, the below illustrates how the external mail user (the one with primary SMTP address email@example.com) will be provisioned when added to another tenant. As expected, the service creates the Guest user account with SMTP address matching the UPN (top of the screenshot), which leaves no room for impersonation. The corresponding mail user object can later be edited to have it’s primary SMTP address updated to any value, which in turn not only updates the object properties but the actual From/To fields in the compliance trail:
Back to the eDiscovery results, it seems that the issue stems from the fact that Exchange resolves the recipient object (based on the LegacyExchangeDN attribute) and replaces its properties dynamically. In the above example, this will result in updating the primary SMTP address to reflect the changes made by the nefarious admin. The issue is thus “internal” to Exchange, but as mail users have not been able to generate items until the advent of Teams, everything was working in an acceptable manner. Nowadays, in order to get the correct information about the sender you will have to take a deeper look into the item properties, instead of relying on the information surfaced in the eDiscovery UI.
Technically, the last statement isn’t completely true. The same issue can be observed with Skype for Business IMs, when the underlying user does not have a mailbox (or Exchange Online license). Just like with the Teams example above, changing the SMTP address of the user will result in Exchange automatically resolving to the new value when displaying any messages in the eDiscovery UI. However, even for a mail user without Exchange license, the corresponding IM items related to Skype for Business conversations contain the information about the SIP address of the user, which similarly to the Primary SMTP address cannot be spoofed.
Overall, the issue described above is not so much a spoofing/phishing vector, as it can only be (ab)used by privileged users and an attack cannot be carried out by externals. However, the way the compliance record is kept for mail users can lead to confusion and ideally a change on how Microsoft stores those items should be examined. Otherwise, you will have to download the full IM item or fetch it from the mailbox via MFCMAPI, then examine some of the more obscure properties such as SkypeMessagePropertyBag (or ptagRecipientSipUri for SfB messages) in order to get a unique identifier for the user. Simply looking at the From/To fields in the UI or the related message properties might play a joke on you, so remember that the next time you are running an eDiscovery for any conversation data!
Apart from the issue detailed in this article, we will surely benefit from an improved method of storing threads and conversations, instead of the current “each reply is a separate item” situation. Whether Microsoft will address these shortcomings remains to be seen.