Hacking & Fuzzing Home Surveillance Camera

Ahmed Ezzat (BitTheByte)
6 min readJan 25, 2021

Back Story

Earlier this year we decided to install a new surveillance camera. I knew the lack of “security” on those so I had to try hacking my way through.

Dumping the framework

I tried searching the internet for the mysterious vendor that manufactured this camera and found nothing so I had to dump it myself. I decided to use their android app since it already has an update feature

I was skeptical at first but do it anyway. I just ran tcpdump on my android thinking that it might have some sort of a custom protocol for updates:-

tcpdump -s0 -w /sdcard/emulator.cap

And to my surprise but also disappointment I found that this model was communicating over Plain Text HTTP connection

I had to do some changes to the update request to force it to send a new update image https://reqbin.com/c-zwbudat1

http://upgrade.smartcloudcon.com/0000213ed0cdb8bc/1551352828392870/1576835576192_Flash.pmg

Extracting the ROM was just a matter of running binwalk -e update.img

it’s a minimal Linux environment and The folder hierarchy was pretty simple

abin - custom made binaries 
bin - mostly tools from github/linux
lib - custom made libaries
modules - custom made linux kernal modules
wav - sounds for the camera
www - a minial and pretty vulnerable web application
userdata - empty
sysinfo - hardware informations

Setting up QEMU

The camera had a 32bit ARM processor. and ALL of the binaries was dynamically linked with “/lib/ld-uClibc.so.0” so I had to setup the toolchain this actually was painful -as always-;

  1. Installing QEMU
sudo apt-get install qemu

2. Setup toolchain

$ wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.23.0.tar.xz
$ tar xf crosstool-ng-1.23.0.tar.xz
$ cd crosstool-ng/
$ ./configure
$ make
$ sudo make install
$ ct-ng arm-unknown-linux-uclibcgnueabi
$ ct-ng build

Some additional libraries were needed from https://gfiber.googlesource.com/toolchains/bruno/+/849791dda3c302156da6dbaea229e44c6bfd8469/arm-linux-uclibcgnueabi/sys-root/lib

~/arm-unknown-linux-uclibcgnueabi/arm-unknown-linux-uclibcgnueabi/sysroot/lib

Now we are able to run 32bit ARM binaries from the camera on the host machine (x64)

Setting up AFL (American Fuzzy Lop)

American Fuzzy Lop is a brute-force fuzzer coupled with an exceedingly simple but rock-solid instrumentation-guided genetic algorithm. It uses a modified form of edge coverage to effortlessly pick up subtle, local-scale changes to program control flow.

Since we don’t have the source code for the binaries we will use AFL with qemu mode which allows fuzzing binary-only programs. note that it’s not as fast as the normal mode

$ git clone https://github.com/AFLplusplus/AFLplusplus
$ cd AFLplusplus/
$ make
$ cd qemu_mode/
$ export CPU_TARGET=arm
$ ./build_qemu_support.sh
$ cd ..
$ make install

Now we are ready to start Fuzzing!

Target Mapping

A full port Nmap scan on 192.168.1.100 “camera’s IP” revealed a number of interesting services running

PORT     STATE SERVICE
23/tcp open telnet
80/tcp open http
443/tcp open https
843/tcp open unknown
1234/tcp open hotline
1300/tcp open h323hostcallsc
6688/tcp open clever-tcpip
6980/tcp open unknown
8554/tcp open rtsp-alt
8699/tcp open vnyx
9505/tcp open unknown
MAC Address: EA:76:74:BC:95:E1 (Unknown)

Port 80/443

Both served the same web application located at /www/ the application had a backdoor username super_yg found at “/doc/script/login.js” which allowed me to access the console.

Later I found that an unauthenticated attacker is able to control the camera using a simple GET request to the following URLs

[RIGHT] http://192.168.1.100/PSIA/YG/PTZCtrl/channels/0/continuous?pan=1&tilt=0
[LEFT] http://192.168.1.100/PSIA/YG/PTZCtrl/channels/0/continuous?pan=-1&tilt=0
[UP] http://192.168.1.100/PSIA/YG/PTZCtrl/channels/0/continuous?pan=0&tilt=1
[DOWN] http://192.168.1.100/PSIA/YG/PTZCtrl/channels/0/continuous?pan=0&tilt=-1

With some focus and zoom abilities

http://192.168.1.100/PSIA/YG/PTZCtrl/channels/0/continuous/focus?data=1
http://192.168.1.100/PSIA/YG/PTZCtrl/channels/0/continuous/zoom?data=1
http://192.168.1.100/PSIA/YG/PTZCtrl/channels/0/continuous/iris?data=1

There’s also a way to get an unauthenticated live feed however I’ll publish it not to get abused by script kiddies. however, it’s easy to spot you’ll also need to implement your client

Port 1300/843

Both were controlled by “/abin/noodles”. and Oh man this binary was a recipe for disaster. it allowed anyone to execute commands on the camera and download/upload files even flashing a new ROM. All unauthenticated!

it was a very interesting target, so I knew I had to find more interesting bugs :)

Fuzzing “noodles”

The main problem that was for AFL to interact with the binary it needed to receive the input from stdin since AFL doesn’t play very well with sockets I had to use an old trick. I used LD_PRELOAD to override the standard “recv” function with this one. which reads from /tmp/input to the passed buffer thus allowing AFL to interact with the binary without using socket connections

Full code at https://pastebin.com/qtLK4TiA

Using the following command to build desock.so

$ ~/arm-unknown-linux-uclibcgnueabi/bin/arm-unknown-linux-
uclibcgnueabi-gcc -fPIC -lpthread -Wall -Wextra desock.c -shared -ldl -o desock.so

AFL supports LD_PRELOAD however it’s advised to use AFL_PRELOAD. I also used the persistent mode to prevent AFL from starting the binary all over again each time it mutates the input this gave me a 35 execution per second which is slow but acceptable

$ AFL_PRELOAD=./desock-arm32.so AFL_PERSISTENT=1 afl-fuzz -Q -f /tmp/input -i in -o out -- ./noodles-patched

If you haven’t noticed already I patched the noodles binary to make it easier for AFL as I was not interested in some branches. I left AFL running for a month and it found 36 unique crashes 31 of them was at the XML parsing logic with no harm other than crashing the target it also found 5 exploitable bugs — I intend not to publish those

Port 1234/8554/1935

Those were for live streaming each with a custom streaming protocol

1234 - http-flv
8554 - rtsp
1935 - rtmp

Connecting to rtsp://192.168.1.100:8558/profile0 using VLC player give me a login form. and I couldn’t guess the username and password however I plan to try a brute-force attack later.

Connecting to rtmp://192.168.1.100:8558/profile0 using rtmpdump was successful however no feed was obtained from it

The flv:// protocol was new to me so I decided to leave it for some other time. it may be vulnerable. who knows ¯\_( ͡❛ ͜ʖ ͡❛)_/¯

Port 6688

A simple HTTP server was running on 6688. however, it allowed anyone to capture a screenshot camera’s live feed just by sending a GET request to http://192.168.1.100:6688/snapshot.jpg

At this point, I got bored of the target since I already confirmed my suspicion. it certainly has more vulnerabilities to discover but there is no good in doing that it’s pretty vulnerable as it is and to sum up all the findings.

  1. Remote Code Execution — /abin/noodles
  2. Unauthenticated File Upload/Download — /abin/noodles
  3. 36 Discovered Crashes — /abin/noodles
  4. Unauthenticated Target Control — web:80,443
  5. Unauthenticated Live Access to Camera’s feed — web:80,443
  6. Unauthenticated Screenshot from feed — web:6688
  7. Manufacture pre-installed Backdoor
  8. Flash Image Update over HTTP

You might need to check your home camera for these findings as most of the Chinese vendors are reusing the same ROM

Closing Word

Not everyone has the time nor the skills required to verify the strength of their home IoT devices so please keep those out of your main network preferably keep it on an isolated network with no internet access. also, stay away from Chinese products — Stay Safe!

--

--