Looking into Cox Panoramic Wifi:s backend

Some brief follow up on the looking-into-things this hearing about a few new router vulns caused over here..

The “main” Cox modem (Panoramic Wifi Gateway, rentable only) is actually a poorly white-labeled Technicolor CGM4140, same as Xfinity Xfi. Those run Broadcom BCM3390 processors (inĀ all it’s MIPSy glory), just like the vulnerable ones (https://fccid.io/G95CGM414X/Internal-Photos/Internal-Photos-Part-1-3423780).
The FW seems a little different, in part because it’s been revamped to handle all the network config via Cox:es main server rather than via a normal web interface (though that’s partly still there too). However, the image is pretty clearly based on XFinitiy Xfi. The actual direct interface on the lan ( self-identifies as such:

HTTP/1.1 200 OK
X-Frame-Options: deny
X-XSS-Protection: 1; mode=block
Date: Mon, 13 Jan 2020 00:42:28 GMT
Server: Xfinity Broadband Router Server

There are several more places where they forgot to change to Cox. But that’s not all – the backend of the whole control-your-router-from-your-cable-login *runs at comcast*:

Request URL: https://siorc.xfinity.com/account/**number**/gateway/7C*******82/group/cpeConnectedDevices/?signature=<244_byte_base64_blob>

When entering wifi.cox.com (aka MyWifi), it goes through a cox auth-sequence (or verifies your prior from cookies). Then a pile of js (https://wifi.cox.com/bundles/critical-path.d47e6d08c4c59a64ef86.js) writes up a nice Authorization Bearer header, and calls https://siorc.xfinity.com/ with it:

“name”: “Authorization”,
“value”: “Bearer <base64 dot-separated blob>”
.. decodes into ..
— Part 1 —
{ “kid”:”sat-prod-k1-1024″, “alg”:”RS256″}
— Part 2 —
{ “jti”:”65cd1d65-6449-466b-a9af-3e71843901e5″, “iss”:”sats-production”,
“iat”:1578849026, “nbf”:1578849026, “exp”:1578852629,
“allowedPartners”: [ “cox” ],
“allowedServiceAccountIds”: [ “******number*******” ]
“capabilities”: [
— Part 3 —
<128 byte blob>

So, a fairly typical signed JWT letting Comcast know that Cox ok:ed this, what we’re down for, expiration, etc. After, siorc.xfinity.com starts including a singature chunk in it’s URLs:

https://siorc.xfinity.com/accountX/?accountUri=*******************&signature=<112 byte urlenc base64>




Together with a number of selected JS loads from cox, it dumps over most of the front page definitions, to be handled by React. It also gives values, defaults, labels, URLs to activate to change them, etc – basically relaying a normal modem front end but in json.

Much of the definitions are given types via “_type”:”https://github.comcast.com/pages/CPE/SmartInet/NetworkConfig”
Apparently comcast has a github. I doesn’t answer to customer connections though. I think there’s a relay baked into this, but I haven’t dug it up.

Haven’t found the specfic endpoints they found to be vulnerable, but it’s big enough and has so much awkward interop I have a hard time thinking all this is airtight (especially since there’s rarely a reason to look at it). I’d be slightly surprised if everything enforced XSS to the point of needing DNS Rebinding (lots of responses sprinkle in hapazard Origin allows) but I’d be even more shocked if it balked at being called by a non-IP name (like Host: some.other.host instead of Host: Not sure how vulnerable they might otherwise be. They seem to be removing options bit by bit, like no longer allowing setting your own DNS, forwarding dangerous ports, and so on. Perhaps I look again when I’m less facinated by the strange Cox/Xfinity gangbang going on here..

Oh and they also throw in xerxessecure (https://xerxes-sub.xerxessecure.com/xerxes-ctrl/keys/jwks for instance) for putting out keys for the signatures and similar auth:y things. Whois says it’s comcasts. There’s also a “diagnostic signaler” (hyperactive snitch-logger on a 3-5s timeout) sending stuff to “https://melee.sed.dh.comcast.net/v2/event/sic”. Seemingly just to be nosy, but there might be other reasons.

I poked a little at the JWTs to see if they accepted other algos (some implementations take your word for what it’s supposed to be validated with, so you can swap out RS256 for, say, MD5). No immediate success, but I probably messed it up.

Leave a Reply