Alice in Router-land: Down The MP-202 Hole

TL;DR; Yet another trivially exploitable vulnerability in residential gateway devices.

All in the golden afternoon, full leisurely we glide;

During a recent refresh of my home communication service providers, I signed up for a VoIP phone line, provided by - lets call them company A.

Company A's offer includes a device to convert the Internet facing VoIP service into the POTS (plain old telephone service) jacks deployed in most houses.

Being the technology geek that I am, one of the real appeals of a VoIP service was having a SIP endpoint at home, free to explore and hack around with. I imagined an Asterisk installation with an outbound SIP trunk, redirecting home calls to all my devices (PCs at home and work, mobile phone), managing in-house calls from the kitchen to the upstairs balcony, and other probably absolutely unrequired features.

Speak English! I don't know the meaning of half those long words, and I don't believe you do either

A nice company A technician arrived at the designated time-slot and installed the AudioCodes MP-202.

Begin at the beginning and go on till you come to the end, then stop.

He said the device 'works best' if I just hook it up straight to my WAN line as my gateway and let it route all of my home traffic outside. Having invested a considerable amount of time configuring a dd-wrt installation on my TD-1043ND, I politely declined:

"NEVER".

The technician then told me to define the device as a DMZ address. again, hell if I was going to leave an unknown who-knows-how-vulnerable device as my publicly facing gateway. He then followed to explain that the device needs to publicly listen on ports 5060 and 443 for it to work. "What if I have port 443 taken?" (I don't, but why wouldn't I); "Then we can change it, but it will confuse the help desk guys when they need to help you."

I decided not to argue for the time being, and let him finish the installation already, so I just configured it and there, it booted and a couple of minutes later ('firmware updates' as per the technician) the SIP phone 1 LED turned green. At that point I wished I had set up an opportunistic traffic capture beforehand, but what's done is done. One more level in my challenge.

Knowing that I would need my SIP credentials for my home PBX fantasies, I decided to ask for them. The technician replied that it is against company policy and that he can't give them to me ("they see it in the logs if I access it"), due to previous cases of abuse where people have (presumably falsely) argued that malware misused their credentials to call sex lines abroad. right.

He also mentioned that the password changes every once in a while.

Well, I figured they must be stored somewhere on the device, hopefully unencrypted, and all I need is some access. I started poking the device with everything nmap could offer, only to discover the expected 443 & 5060. browsing to the HTTPS interface brings up:

Alright, a generic login form, lets try some {admin,Admin,Administrator,root,user}x{admin,Admin,1234,123456,root,user} combinations. after a few attempts I got user:user authenticated, but this only lead to a very restricted interface where I could pretty much control the network interface settings. My first attempt was some command injections to web parameters, trying to spawn telnetd -p 1337 & with different encodings. after some failures I went on for more information gathering - I had my home router duplicate the device's traffic for capture on my desktop - and some interesting things started to pop up.

I immediately spotted the SIP registration, which is wonderfully unencrypted and readable, and for some reason also happened every minute or so.

I eagerly read through the authentication part of the SIP packet, to understand that SIP uses Digest authentication. Fair enough! since I have the nonce, realm, and username - I can attempt an MD5 brute force for the password. I let my overclocked Core i7 3770K crunch some MD5s for a few hours, and woke up to find that no match was found for all passwords up to 6 alphanumerics (lowercase only). I also ran an attempt for all numerics only up to 7 digits, with no luck.

I also saw ntp updates from a provider's ntp server, the usual ARPs, and some TFTP file transfers.

Score! I recognized a file being periodically downloaded from company A's TFTP server called MP202_<00908f_MAC>.inx. I went ahead and downloaded it myself from the server (could have extracted it from the pcap hadn't it just worked).

A periodic 4k file retrieved from A's server? this must be some sort of device configuration :)

But what's an .inx file? google and file were unhelpful. At a quick glance, it wasn't plain text, but a closer observation showed that the first 8 characters were the ASCII representation of Salted__, which is indicative of an openssl encryption with a passphrase.

Some googling lead to the MP-20x Release Notes v2.6.3 which proved that this was true, as these devices can accept either plain .cfg files or encrypted .cfx files (as well as .ini/.inx).

Read the directions and directly you will be directed in the right direction.

The example encryption command used the salt value of 1234567890ABCDEF. Apparently the engineers at company A copy-pasted the command without understanding what salt is, as this was the exact salt value in my generated configuration file.

Off with their heads!

A slight thrill creeped in when I tried the password MyPassword123456, but appearantly they did have some sense. The clear salt still doesn't help a lot with decryption of this particular instance, as Im not the NSA and I don't have a huge precalculated triple DES passphrase rainbow table for that salt value.

I found that upon booting, the device will actually try to download a new firmware from the same TFTP server. firmware? awesome! a great exercise to sharpen my reversing skills and possibly find a hardcoded password or other auth bypass.

I downloaded the 4MB firmware file MP202_301.rmt. This one did not seem encrypted off the bat, as I was getting a plain text header very visible at the beginning of the file.

binwalk suggested both an LZMA block and a CramFS signature:

We're all mad here.

The LZMA block properties seems quirky, and the CramFS extract just would not mount under no tool. 7-zip got to list the files, but extracting them they were all zero sized. Digging into some cramFS mounting google results, I came across Valerio Di Giampietro's lzma-uncramfs, which happened to deal with a rather unique usage of LZMA by gateway middleware named OpenRG.

I browsed through the file system, realizing that it's pretty slim. I had some configuration files, some web interface images, and most importantly, MIPS binaries.

  • The configuration files did not contain anything that's not perfectly generic, and seemed like plain factory defaults.

  • A peculiar find in the web interface images directory were several files branded with the logo of the very distinct company B - which holds the same type of devices. IP theft? or cooperation? I can only guess.

  • Some strings searching in all the binaries failed to find references to company A, built-in users or passwords...

Armed with the option to further reverse the binaries later, I returned to traffic analysis, really wanting to catch an HTTPS session where company A authenticates to my device (I do assume that they don't verify the machine's self-signed certificate, but I still generated a very similar certificate, just in case).

However, capturing an HTTPS session will not be very useful at this point, as I wouldn't be able to read it. I needed to setup an SSL MITM proxy to see the form values being posted. I first tried mitmproxy but found that in transparent mode, it uses the host header to extract the target, which would be problematic in my case. In reverse proxy mode, it doesn't support HTTPS, but only serving HTTP. I found an open issue on mitmproxy's github (with a very recent pull request), but I decided to try another way.

I set up an nginx httpd proxy on a VM, and had my router forward there all traffic destined to the MP202. I didn't bother figuring out how to make nginx store request contents, but used a little trick instead: I configured it as a double proxy. An HTTPS listener to intercept inbound traffic and forward locally to an HTTP listener that is a proxy for the MP-202 via HTTPS.

server {
    listen 443;
    server_name _;

    ssl on;
    ssl_certificate mp202.crt;
    ssl_certificate_key mp202.key;

    ssl_session_timeout 5m;

    ssl_protocols SSLv3 TLSv1;
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
    ssl_prefer_server_ciphers on;

    location / {
            proxy_pass http://localhost:50599;
            allow all;
    }
}
server {
    listen 50599;
    server_name _;

    location / {
            proxy_pass https://mp202;
            allow all;
    }
}

Not pretty, but now I finally had an unencrypted capture of web authentication.

Only then did I figure that the login form itself is also protected by a javascript MD5 hashing scheme (another possible target for reversing), meaning that even if I capture a live session I probably wouldn't be able to authenticate with it.

I could set up a fake login page and ask the help desk to connect - then I found Ishay Peled already did it (as well as other similar parts of my research), so that could be a fallback in case other vectors fail.

Next thing I tried was switching the ethernet cable from the WAN port to the LAN port, assuming that more services would be open by default. I was right, I found more open services this time, including 992/telnets.

using telnet -z ssl I was able to get a Username: prompt, but the server would not accept a login as user (reprompting for another username). I ran through some other defaults like the web auth, but it seems to authenticate using the same mechanism.

I moved on to read some posts about firmware analysis, and looked for OpenRG references. I finally came across a brief mention of /save_rg_conf.cgi, which supposedly blurts out the complete configuration of the device.

and it did.

yes, there's also replace_rg_conf.cgi that works.

Why, sometimes I've believed as many as six impossible things before breakfast.

Authenticated as user:user, the device just let me download the complete configuration file! However, I soon found all sensitive fields (such as passwords) were encrypted/obfuscated looking like: (password(&b7;X&5c;&b9;&a2;))

another short query lead me to Zibri's blog, where he provides a simple javascript deobfuscator. there is, in fact, a simple fixed 64-byte vector being added to the password, an easily reversible procedure, which zibri probably extracted from the binary or simply discovered by trial and error.

In a minute of triumph, I had my complete SIP credentials, the provider's administrator account and password, and the configuration files encryption passwords.

a quick openssl 3des -in MP202_<redacted>.inx -out MP202_<redacted>.ini -p <redacted_password> later, I verified that all of these values are pulled on a daily basis to my device (as well as after every boot).

It was a rather disappointingly unsophisticated win, but a win nonetheless.

Tut, tut, child! Everything's got a moral, if only you can find it.

"What is the use of repeating all that stuff, if you don't explain it as you go on? It's by far the most confusing thing I ever heard!"