Saturday, May 28, 2016

Hacking an IP camera (Grandstream GXV3611_HD)


I did this about a year ago. I was taking Living Lab course at IUPUI and people at the lab allowed me to borrow the IP camera. This particular camera was having an issue with Power-over-ethernet so I told them to let me check it out. I am not great with electronics but after watching a videos by EEVblog (he has bunch of repair and troubleshooting videos), I wanted to try out some things to see if I can find the issue. I didn't. I asked people at the lab if I could keep the camera for a while and play around with it and they allowed me to. I ended up finding sql injection vulnerability and an undocumented command to run telnet service so you can login as root.

0. Hardware:

At this point, I've already taken apart the camera. Below you can see 10x2 pins. I assumed that they were for debugging and were serial.

I connected my multimeter to all the pins to see if any was putting out more volts than 5. My logic analyzer can handle around 5 volts. (it was one of those cheap ones from ebay. If you can afford it, I recommend getting one from Saleae) Pins did not supply more than 5 volts so I decided to connect the logic analyzer to random pins.

When the camera was turned on, I noticed data on one of the channels and assumed it was serial.

1. Communicating with the camera and getting a shell:

I connected FTDI/Serial adapter to it and connected to the camera using Putty. Baud rate / speed was determined via looking at logic analyzer output. It was around 115200, which is one of the standard baud rates.

The pin that I connected to was TX so I couldn't transmit something to the camera but I could receive stuff in terminal.

I picked the pin above TX pin to see if it would receive input and it did. I still don't know how to determine what pin is for RX without tracing lines on the circuit board. If anyone has any idea, let me know.

I restarted the camera and stopped autoboot. (I know my screen is dusty)

It was using U-Boot. It's a bootloader which is typically used in embedded devices.

I had watched a video from Defcon titled “Hacking 20 devices in 45 minutes” in which the speakers talked about how they got shell by changing init option in U-Boot. I did the same thing.

Printenv command print out all the current boot options.

setenv command allows us to update the boot options. I set init=/bin/sh to get shell.

Bootm command is used to boot from memory. The address is taken from output of printenv.

The camera did indeed boot up and gave me a busybox shell.

2. Getting shell again:

I started browsing the file system and noticed empty folders. This happened because I modified the boot process.

I restarted the camera again and let it boot normally. After boot, it asked me for a username and a password.

I didn't know it so I restarted the camera again, modified init to run /bin/sh then dumped the hashes.

Password is empty/blank.

I booted the camera normally and logged in. I can finally see the files that I didn't see previously.

3. Bug hunting

Now that I have serial shell and access to the file system, I can start looking for remote vulnerabilities by reversing stuff running on the device.

In the screenshot above, you can see webs and cli running. Webs is the web server and cli is the telnet configuration server.

I took both of them to so I can analyze them IDA.

Cli was smaller compared to webs so I started analyzing that first.
Connecting to the telnet server prompts you to input username, password, and commands (when you authenticated)

I loaded the binary in IDA and looked for the string “Username:”

While going through the disassembly, I saw sql statements. I looked at the strings window and functions and found out that the program was using sqlite.

When I was getting cli and webs file onto my computer, I also grabbed system.db file and this was the sqlite database. The database contained a table called user, which contained usernames, passwords, privilege, and account status.

Here's the disassembly of the SQL query that interacts with user table.

The authentication part suffers from sql injection vulnerability.

Normally this is executed:
input = USERNAME
select * from users where name = 'USERNAME';

We can do this instead:
select * from users where name = '';OUR OWN SQL STATEMENT;--';

I opened up system.db database in SQLite Database Browser to try some statements out before I executed them on the camera.

My first thought was to just change the password for the admin account.

And it worked.

When I went back to the camera to try it, it failed.

The connection was killed if too much data was passed in the Username field.

I went back to SQLite Database Browser to try something else and came up with this:
'; update user set password='a';--

It executed the statement below:
select * from users where name = ''; update user set password='a';--';

This sets all the passwords to a.

Now that I think about it, I could have just changed privilege of all the accounts to 0 (admin) and set the disabled field 0, which would have been less noticeable and I could have logged in via anonymous account.

4. Getting remote root shell:

I examined cli file a bit more.

I noticed that there was a command(!#/) that didn't appear when I typed 'help'.

Here's the place where it jumps to:

It executes telnetd on port 20000. After doing sql injection and logging in to command line configuration menu, I can run !#/ command and execute telnetd. I can telnet in and login with root and empty password remotely.

5. Links: