It here. it’s here. it’s finally here! The long-awaited SIP gateway for Microsoft Teams is 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.
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
1 UserAgent FileTransport PolycomVVX-VVX_500-UA/22.214.171.12480 Type/Application
So now it’s just a case of running a few cmdlets to grab all the files
Invoke-WebRequest http://apac.ipp.sdg.teams.microsoft.com/poly-http2https.cfg -UserAgent "USerAgent FileTransport PolycomVVX-VVX_500-UA/126.96.36.19980 Type/Application" -OutFile ./poly-http2https.cfg
Using this method, we can see the bespoke provisioning file is actually… here
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/188.8.131.5280 Type/Application" #Pulls files from Microsoft #global MAC config Invoke-WebRequest http://apac.ipp.sdg.teams.microsoft.com/000000000000.cfg -UserAgent $UserAgent -OutFile ./000000000000.cfg #Https Invoke-WebRequest http://apac.ipp.sdg.teams.microsoft.com/poly-http2https.cfg -UserAgent $UserAgent -OutFile ./poly-http2https.cfg #Mac Address Invoke-WebRequest "https://ause.dm.sdg.teams.microsoft.com/device/ob/84c5809492ab770808fd248538cd1649ea801788/lang_en/$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 @Onboarding.org 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.