Reverse Engineering the new Microsoft Teams SIP Gateway – Part 1

It here. it’s here. it’s finally here! The long-awaited SIP gateway for Microsoft Teams is here.

Note: This is a deeply technical article on how the SIP Gateway provisioning service works, if you’re just looking to get your SIP phones working, Martin Boam has a great article over here

Unfortunately, despite my begging, I didn’t get into the preview program on this one, so when this post appeared on the Microsoft Teams blog announcing the feature. The fact that everything was so neatly managed with Microsoft’s own provisioning server for each of the phones was exciting… Until I noticed there was no “open” SIP support.

The bad news – No “Open SIP”

Yep, you heard me right. No Registrar or realm details. No SIP Proxy info, nothing to get any other third-party SIP devices like PA systems, Door stations, doorbells or any other SIP compliant device working. Just some pre-packaged handsets bundles with provisioning server info to get them going.

This was supposed to be the magic bullet, the thing that made everything perfect. But there is a reason for it.

To understand why things were done this way. We need to understand that Microsoft had to cater to the masses whilst making a secure platform. It was in their better interest to push out a “basic” default “Ready to sign in” config to all phones. Thus SIP phones would behave like the old Skype Pin based authentication, rather than getting non-phone admins to understand the intricacies of SIP and batch provisioning themselves.

This has the advantage of letting the Microsoft Teams SIP Gateway manage both the SIP Account details, dynamically updating the password as well as stopping admins from creating 100 extensions with the password 1234 and getting abused for toll fraud (trust me, I’ve seen it before)

As with all things you either make it easy or you make it customisable.

Let’s figure it out ourselves then

Well, that wasn’t going to stop me from trying to register an unsupported device that’s for sure!

Understanding a “Supported” phone process.

Having worked with a lot of Polycom phones over the years, I decided to tackle that angle first. Thanks to great articles like Jeff’s and Greigs talking about how Poly phones provision themselves, we know the first thing they will do is ask for the global mac config. So that’s the first thing we are going to do.

After obtaining the Polycom provisioning server details from the Microsoft Documentation, the first thing I tried was navigating to the provisioning server to see what I’d get… aaand I got an SSL error.

No, that’s not a lot of tabs, I have 14 copies of Edge open as well.

Hmm, I doubt that’s really the issue, so I suspected I was hitting a redirect based on the fact my user agent isn’t a phone, but lo and behold. my browser was just being “smart” and trying HTTPS first.

Let’s try that again using Invoke-WebRequest for the root directory in PowerShell!

Okay, a 403 (Permission Denied) That’s more promising. What happens if we request the 000000000000.cfg file?

Ah, it seems Microsoft have played Knifey, Spoony before! The service running the provisioning server is checking user agents against a supported list. Guess I’ll have to break out the good old Packet Sniffer!

So I took to the documentation a bit more and saw this lovely chestnut.

Well, that’s not gonna stop me from trying. I am a Mad Scientist after all.

Digging Deeper into the Provisioning Process

To see what happens when we provision a phone, we need to see what the Phone and the SIP Gateway are talking about. On my Mikrotik Router, I set up a new packet capture stream with a filter of a spare test phone and sent the stream to my laptop to be captured by Wireshark.

We need to verify this is working as we may only get a single shot at “provisioning” a phone. So we jump over to my laptop and get the phone to quickly check the Polycom provisioning server for the latest firmware by navigating to Utilities > Software Upgrade and clicking Check for Updates

Sure enough, if we jump over to my Wireshark instance capturing all the traffic from the Mikrotik Pcap stream on port 37008, we can see the phone requesting the firmware details, and it’s easy enough to decipher a payload in the cleartext HTML by just copying it out.

So let’s upgrade the phone to a supported firmware version and change the provisioning URL to what Microsoft requests in the documentation and see what happens.

Whilst running the packet capture, I jumped into the phone and quickly pulled a config backup

Luckily the provisioning server doesn’t appear to override things like pre-inherited settings or local settings. This means we could potentially use 2 step provisioning to apply whatever we want to the phones before handing them off to Microsoft’s provisioning server.

Looking at the config, we can see that Microsoft sets up a bespoke provisioning instance with the devices MAC and some form of nonce and assigns a special webpage to the line key.

Thankfully, not all the URL’s are using the user agent filtering, as we can see here is the background image for the sign-in screen

But unfortunately, the URL assigned to the Sign In soft key appears to have the filtering applied

Drat, okay. What can we glean from the packet capture?

Well, Microsoft themselves are using a 2step auth system and the first thing they do is switch to HTTPS provisioning. Meaning without the phone’s private key, or a man in the middle proxy attack. We aren’t decoding those packets.

And that config file injects a certificate and points to another provisioning file.

There has to be an easier way

Pulling these files this way is difficult. Luckily, now that we have a few packet captures, we can see the user agent the provisioning server is expecting and provide it.

The PowerShell Cmdlet Invoke-WebRequest supports the -UserAgent attribute and by passing the following UserAgent we can impersonate a phone and download its config file

UserAgent FileTransport PolycomVVX-VVX_500-UA/ Type/Application

So now it’s just a case of running a few cmdlets to grab all the files

Invoke-WebRequest -UserAgent "USerAgent FileTransport PolycomVVX-VVX_500-UA/ Type/Application" -OutFile ./poly-http2https.cfg

Using this method, we can see the bespoke provisioning file is actually… here[PHONE_MAC_ADDRESS]-olive.cfg

So with a quick bit of PowerShell, we can download everything relevant to the phone.

#Set Phones MAC Address

$MacAddress = "0004f2b3fa48"
$UserAgent = "UserAgent FileTransport PolycomVVX-VVX_500-UA/ Type/Application"

#Pulls files from Microsoft

#global MAC config
Invoke-WebRequest -UserAgent $UserAgent -OutFile ./000000000000.cfg

Invoke-WebRequest -UserAgent $UserAgent -OutFile ./poly-http2https.cfg

#Mac Address
Invoke-WebRequest "$MacAddress-olive.cfg" -UserAgent $UserAgent -OutFile "./$MacAddress-olive.cfg"

Now, because the phone hasn’t actually been provisioned yet. The SIP Gateway returns a generic “Onboarding” configuration that registers the phone with a generic address and password and importantly, a web application to sign the phone in.

Additionally, the SIP Gateway changes the provisioning URL AGAIN for when you sign the phone in when there is hopefully a valid config.

It’s also worth noting that Microsoft sets the checksync.alwaysReboot flag which means when the Phones Config is updated on the SIP Gateway and the phone notices this, it will reboot immediately to apply the changes.

Also whilst we’re here it’s great to see the SIP gateway using G722 and OPUS and SIREN

So what happens when we try to grab the pairing code from the listed URL using PowerShell…


A quick look at the useragent field of the built in browser shows us why… it’s completely different from the file transfer one from before, and despite passing this to the softkey.php url I still get an error.

Of interesting note, both the provisioning URL and the SignIn page share a unique code as part of the provisioning process. However, this code updates every time a new provisioning request is made.

That’s all the time I had to investigate this time around, so join me in part 2 when I setup a proxy for some SSL inspection.

Hope this helps.

5 thoughts on “Reverse Engineering the new Microsoft Teams SIP Gateway – Part 1

  1. GeekEvangelist

    Great Article. Good hunting, and cant wait for Open SIP for things like Door Bells, Gate Openers, PA Systems etc.
    Fingers Crossed Operator Connect will provide the flexibility for this capability

  2. Myles

    I’ve had a bit of a crack trying to reverse engineer the Yealink T53w provisioning. The user agent I’m using is “Yealink SIP-T53w”. I’ve found when reaching the<mac.cfg> endpoint it does validate the MAC comes from the Yealink range. A quick search reveals that would be 001565. When using a MAC beginning with that, you instead receive a new error which says “can not find template for YEALINK MAC:001565 YEALINK YEALINK IP::56608 UserAgent:Yealink SIP-T53”. However, even after uploading that MAC into the Teams Admin center, I still receive the same error. Feel like I’m missing something painfully obvious (and already put the two phones I provisioned into service, so can’t reset them to run a wireshark capture!)

    ** Update: **

    A quick look at the Yealink support site – and the user agent I believe should be along the lines of “Yealink SIP – “. So I gave that a try, and… new error!: “Forbbiden URL /device/ob/3b252f80553b84eef01a4464b272c1b543473116/lang_en/001565fd3218.cfg Yealink SIP-T53w”

    No amount of toying around with the firmware seems to be getting me anywhere – but will keep trying :).

    1. Myles

      Running some captures – user agent for this model in particular should be: Yealink SIP-T53


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.