Monday, July 17, 2017

Researching an IoT camera

Introduction:
I bought another camera to play with. This one is wireless, HD, and allows 2-way communication. There are more features. They're listed here: https://www.walmart.com/ip/Minion-Stuart-Cam-HD-Wifi-Camera-Walmart-Exclusive/54905488 I bought it for two reasons. One was to just have it pointing at my plants outside and second was to use it for analysis. I wrote a guide for myself for doing analysis of IoT devices and embedded devices. It's very high level and I'll try to follow it. The things I need to know are:
  • What the system looks like / system model
  • Inputs and outputs
  • What it does during normal operations

The System:
Hardware:
First thing I did after I got the camera was to take it apart. There are internal connections that I don't care about, such as mic, speakers, camera, and IR lights. I did notice four connections for UART though.
Those I care about. Thankfully these connections were labeled. I got some wire and soldered it to RX, TX, and GROUND. I drilled a hole at the bottom of the camera and routed the wires through. I got this idea from here: http://blog.senr.io/blog/hackawebcamcom-upcoming-workshop-preview
This is what it turned out to be:
Now we can try to use UART to gather more information.

So far we know that the camera has UART, Wireless, and from the manual, I know it has two modes. One is for setting up the camera and the other is for normal operations after the setup is complete. It also has LED indicators.

Now to gather more information. I connected to the camera using FTDI Friend from Adafruit. I connected GROUND, RX, TX. https://learn.adafruit.com/ftdi-friend/overview
We have to figure out UART baudrate. There are couple of ways to do this but easiest is to just load up Arduino software then use Serial Monitor and go through the common buadrate speeds. Whenever you see text you can read/recognize, you'll know that's the buadrate.

I used the following command to start my serial connection:
screen /dev/ttyUSB0 115200 8N1

I plugged in the camera and started receiving data in my terminal.
Finally, it dropped me directly into root shell. I didn't have to login.
Here are some resources on how to gather information(some commands wont work due to embedded device creators decided not to include them):

# cat /proc/cpuinfo
Processor       : ARMv7 Processor rev 1 (v7l)
processor       : 0
model name      : ARMv7 Processor rev 1 (v7l)
BogoMIPS        : 373.55
Features        : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc05
CPU revision    : 1

Processor       : ARMv7 Processor rev 1 (v7l)
processor       : 1
model name      : ARMv7 Processor rev 1 (v7l)
BogoMIPS        : 375.60
Features        : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc05
CPU revision    : 1

Hardware        : iMAPx15
Revision        : 0000
Serial          : 0000000000000000

# cat /proc/meminfo
MemTotal:         254704 kB

# lsusb
Bus 001 Device 001: ID 1d6b:0002
Bus 002 Device 001: ID 1d6b:0001

# mount
rootfs on / type rootfs (rw,relatime)
devtmpfs on /dev type devtmpfs (rw,relatime,size=92180k,nr_inodes=23045,mode=755)
proc on /proc type proc (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /dev/shm type tmpfs (rw,relatime,mode=777)
tmpfs on /tmp type tmpfs (rw,relatime)
tmpfs on /root type tmpfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
/dev/mtdblock5 on /mnt/config type jffs2 (rw,relatime)

# ls /dev/mtdblock*
/dev/mtdblock0  /dev/mtdblock2  /dev/mtdblock4  /dev/mtdblock6
/dev/mtdblock1  /dev/mtdblock3  /dev/mtdblock5

# cat /proc/partitions
major minor  #blocks  name

 31        0        512 mtdblock0
 31        1         64 mtdblock1
 31        2         64 mtdblock2
 31        3      10240 mtdblock3
 31        4      10240 mtdblock4
 31        5        512 mtdblock5
 31        6      11136 mtdblock6

# df -h
Filesystem                Size      Used Available Use% Mounted on
devtmpfs                 90.0M         0     90.0M   0% /dev
tmpfs                   124.4M         0    124.4M   0% /dev/shm
tmpfs                   124.4M     44.0K    124.3M   0% /tmp
tmpfs                   124.4M      4.0K    124.4M   0% /root
/dev/mtdblock5          512.0K    196.0K    316.0K  38% /mnt/config


# du / -h -d 1
0       /var
0       /mnt
700.0K  /ko
4.0K    /root
0       /proc
3.1M    /bin
0       /media
0       /dev
876.0K  /etc
1.9M    /usr
584.0K  /package
48.0K   /libexec
216.0K  /opt
5.4M    /lib
0       /home
44.0K   /tmp
212.0K  /sbin
4.0K    /system
0       /sys
13.0M   /


Now that we're done gathering info about hardware and storage, we can gather information about software and OS.

Software and OS:
# uname -a
Linux IPC 3.10.0-InfoTMIC+ #495 SMP PREEMPT Mon Nov 7 10:33:53 CST 2016 armv7l GNU/Linux

# cat /etc/os-release
NAME=Buildroot
VERSION=2014.02-git
ID=buildroot
VERSION_ID=2014.02-git
PRETTY_NAME="Buildroot 2014.02-git"

# cat /etc/issue
Welcome to IPC

# cat /proc/version
Linux version 3.10.0-InfoTMIC+ (qa1@localhost.localdomain) (gcc version 4.7.3 (Buildroot 2014.02-git) ) #495 SMP PREEMPT Mon Nov 7 10:33:53 CST 2016

# cat /etc/hosts
127.0.0.1       localhost
127.0.1.1       IPC

# cat /etc/hostname
IPC

# netstat -l
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 10.0.0.7:9232           0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:www             0.0.0.0:*               LISTEN      
tcp        0      0 0.0.0.0:9595            0.0.0.0:*               LISTEN      
udp        0      0 0.0.0.0:10000           0.0.0.0:*                           
raw     1408      0 0.0.0.0:1               0.0.0.0:*               1           
raw     2112      0 0.0.0.0:1               0.0.0.0:*               1        

# ps
[CUT]
 747 root     my_watch_dog
 748 root     /opt/ipnc/avserver_x15.bin
 752 root     [IMAP mt9d111 CH]
 753 root     audioEng
 757 root     {exe} ash /sbin/update_speaker_volume.sh
 764 root     /sbin/syslogd -n -C4096
 767 root     /sbin/klogd -n
 838 root     -sh
 852 root     wpa_supplicant -Dnl80211 -iwlan0 -c/tmp/wpa_supplicant.conf
 853 root     {check_cameng.sh} /bin/sh /sbin/check_cameng.sh
 854 root     {exe} ash /sbin/keep_scan.sh
 857 root     {exe} ash /sbin/check_netcapture.sh
 910 root     cameng
 911 root     goahead
1186 root     udhcpc -A 3 -i wlan0 -h x15
1286 root     netcapture
9956 root     sleep 30
10105 root     sleep 10
10156 root     sleep 5
10158 root     sleep 1
10159 root     ps

# lsof  |grep \.sh
757     /bin/busybox    /sbin/update_speaker_volume.sh
853     /bin/busybox    /sbin/check_cameng.sh
854     /bin/busybox    /sbin/keep_scan.sh
857     /bin/busybox    /sbin/check_netcapture.sh

# ls /lib/*
/lib/ld-uClibc-0.9.33.2.so           /lib/libnsl-0.9.33.2.so
/lib/ld-uClibc.so.0                  /lib/libnsl.so.0
/lib/lib8270enc.so                   /lib/libnvram.so
/lib/libOMX.Infotm.Video.Encoder.so  /lib/libopencv.so
/lib/libc.so.0                       /lib/libpthread-0.9.33.2.so
/lib/libcrypto.so                    /lib/libpthread.so.0
/lib/libcrypto.so.1.0.0              /lib/libresolv-0.9.33.2.so
/lib/libcurl.so                      /lib/libresolv.so.0
/lib/libcurl.so.4                    /lib/librt-0.9.33.2.so
/lib/libcurl.so.4.4.0                /lib/librt.so.0
/lib/libdl-0.9.33.2.so               /lib/libsdutils.so
/lib/libdl.so.0                      /lib/libshmav.so
/lib/libg1dec_dwl.so                 /lib/libssl.so
/lib/libgcc_s.so                     /lib/libssl.so.1.0.0
/lib/libgcc_s.so.1                   /lib/libthread_db-0.9.33.2.so
/lib/libh1enc.so                     /lib/libthread_db.so.1
/lib/libiw.so                        /lib/libuClibc-0.9.33.2.so
/lib/libiw.so.29                     /lib/libutil-0.9.33.2.so
/lib/libm-0.9.33.2.so                /lib/libutil.so.0
/lib/libm.so.0

# env
TSLIB_ROOT=/usr/bin
HISTFILESIZE=1000
INPUTRC=/etc/inputrc
TSLIB_TSDEVICE=/dev/input/event3
USER=root
HOSTNAME=IPC
TSLIB_TSEVENTTYPE=INPUT
LD_LIBRARY_PATH=/usr/lib:/usr/local/share/minigui/res
HOME=/root
QTDIR=/usr/lib/
PAGER=/bin/more
TSLIB_FBDEVICE=/dev/fb0
PS1=#
TSLIB_PLUGINDIR=/usr/lib/ts
TSLIB_CONSOLEDEVICE=none
LOGNAME=root
TERM=vt102
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/bin/X11:/usr/local/bin:/opt/ipnc
TSLIB_CONFFILE=/etc/ts.conf
DMALLOC_OPTIONS=debug=0x34f47d83,inter=100,log=logfile
HISTSIZE=1000
SHELL=/bin/sh
QWS_DISPLAY=LinuxFB:mmWidth=800:mmHeight=480
PWD=/root
QWS_MOUSE_PROTO=tslib:/dev/input/event3
TSLIB_CALIBFILE=/etc/pointercal
EDITOR=/bin/vi

# cat /etc/group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:
tty:x:5:
disk:x:6:
lp:x:7:
kmem:x:9:
wheel:x:10:root
cdrom:x:11:
dialout:x:18:
floppy:x:19:
video:x:28:
audio:x:29:
tape:x:32:
www-data:x:33:
utmp:x:43:
plugdev:x:46:
staff:x:50:
lock:x:54:
haldaemon:x:68:
dbus:x:81:
netdev:x:82:
ftp:x:83
nobody:x:99:
nogroup:x:99:
users:x:100:
default:x:1000:

# cat /etc/passwd
root::0:0:root:/root:/bin/sh
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:100:sync:/bin:/bin/sync
mail:x:8:8:mail:/var/spool/mail:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
operator:x:37:37:Operator:/var:/bin/sh
haldaemon:x:68:68:hald:/:/bin/sh
dbus:x:81:81:dbus:/var/run/dbus:/bin/sh
ftp:x:83:83:ftp:/home/ftp:/bin/sh
nobody:x:99:99:nobody:/home:/bin/sh
sshd:x:103:99:Operator:/var:/bin/sh
default:x:1000:1000:Default non-root user:/home/default:/bin/sh

# cat /etc/shadow
root::10933:0:99999:7:::
bin:*:10933:0:99999:7:::
daemon:*:10933:0:99999:7:::
adm:*:10933:0:99999:7:::
lp:*:10933:0:99999:7:::
sync:*:10933:0:99999:7:::
shutdown:*:10933:0:99999:7:::
halt:*:10933:0:99999:7:::
uucp:*:10933:0:99999:7:::
operator:*:10933:0:99999:7:::
ftp:*:10933:0:99999:7:::
nobody:*:10933:0:99999:7:::
default::10933:0:99999:7:::

# lsmod
Module                  Size  Used by    Tainted: G  
bcmdhd                419460  0
af_packet              15288  4
enable_32k_rtc           524  0

# ls /bin/
amixer            fdflush           mktemp            rmdir
ash               fgrep             more              run-parts
audioEng          flash             mount             sed
brctl             flash_cp          mountpoint        setarch
busybox           flash_read        mt                setserial
cameng            flash_write       mv                sh
cat               ftpget            my_watch_dog      sleep
catv              ftpput            netcapture        stty
chattr            getopt            netstat           su
chgrp             goahead           nice              sync
chmod             grep              ntpdate           tar
chown             gunzip            nvram_clear       touch
cp                gzip              nvram_cmd         true
cpio              hostname          nvram_get         umount
date              info_msg          nvram_pre_check   uname
dd                kill              nvram_renew       upload.cgi
df                linux32           nvram_set         upload_all.cgi
dhd_helper        linux64           nvram_show        upload_linux.cgi
dmesg             ln                pidof             usleep
dnsdomainname     login             ping              vi
dumpkmap          ls                pipe_progress     watch
echo              lsattr            printenv          wl
egrep             lzop              ps                wpa_cli
ethtool           mkdir             pwd               wpa_supplicant
false             mknod             rm                zcat

# ls /sbin/
10get                     ipaddr                    poweroff
10put                     iplink                    reboot
Ethernet_check.sh         iproute                   remove_webs.sh
av_check_kill.sh          iprule                    resolve_server_addr.sh
blkid                     iptunnel                  restart_udhcpc.sh
bt_reset.sh               iwconfig                  rmmod
check_cameng.sh           iwgetid                   route
check_ethernet.sh         iwlist                    runlevel
check_netcapture.sh       iwpriv                    sdapp.sh
check_wpa_cmd.sh          iwspy                     setconsole
common.sh                 keep_scan.sh              shkill.sh
config_cameng.sh          kill_check.sh             sta_check.sh
config_netcapture.sh      kk                        start-stop-daemon
connect_tplinkseedonk.sh  klogd                     swapoff
devmem                    lan.sh                    swapon
extract_webs.sh           loadkmap                  switch_root
factory_reset_do.sh       logread                   sysctl
freeramdisk               losetup                   syslogd
fsck                      lsmod                     timeUpdate.sh
getty                     makedevs                  tz.sh
halt                      mdev                      udhcpc
hdparm                    mkswap                    update_speaker_volume.sh
hwclock                   mmc_check.sh              upgrade.sh
ifconfig                  modprobe                  upload_kill.sh
ifdown                    nameif                    vconfig
ifup                      nfs_mount.sh              wan.sh
init                      nslookup.sh               watchdog
insmod                    p2p_lan.sh
ip                        pivot_root


Now we know a bit more about the system (and we'll discover more later on). We can move into gathering info about networking.

Networking:
# ifconfig -a
lo        Link encap:Local Loopback  
         inet addr:127.0.0.1  Mask:255.0.0.0
         UP LOOPBACK RUNNING  MTU:65536  Metric:1
         RX packets:171 errors:0 dropped:0 overruns:0 frame:0
         TX packets:171 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:0
         RX bytes:11498 (11.2 KiB)  TX bytes:11498 (11.2 KiB)

wl0.1     Link encap:Ethernet  HWaddr 44:2C:05:XX:XX:XX
         BROADCAST MULTICAST  MTU:1500  Metric:1
         RX packets:0 errors:0 dropped:0 overruns:0 frame:0
         TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:1000
         RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

wlan0     Link encap:Ethernet  HWaddr 44:2C:05:XX:XX:XX
         inet addr:10.0.0.7  Bcast:10.0.0.255  Mask:255.255.255.0
         UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
         RX packets:1253 errors:0 dropped:8 overruns:0 frame:0
         TX packets:541 errors:0 dropped:0 overruns:0 carrier:0
         collisions:0 txqueuelen:1000
         RX bytes:135614 (132.4 KiB)  TX bytes:70738 (69.0 KiB)


# iwconfig
wlan0     IEEE 802.11  ESSID:""  Nickname:""
         Mode:Master  Frequency:2.412 GHz  Access Point: 14:91:82:XX:XX:XX
         Bit Rate=72 Mb/s   Tx-Power:32 dBm   
         Retry min limit:10   RTS thr:off   Fragment thr:off
         Encryption key:off
         Power Managementmode:All packets received
         Link Quality=5/5  Signal level=-57 dBm  Noise level=-91 dBm
         Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
         Tx excessive retries:1  Invalid misc:0   Missed beacon:0

lo        no wireless extensions.

wl0.1     IEEE 802.11  ESSID:"StuartCam"  Nickname:""
         Mode:Master  Frequency:2.412 GHz  Access Point: 44:2C:05:XX:XX:XX  
         Bit Rate=72 Mb/s   Tx-Power:32 dBm   
         Retry min limit:10   RTS thr:off   Fragment thr:off
         Power Management:off

# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         10.0.0.1        0.0.0.0         UG    0      0        0 wlan0
10.0.0.0        *               255.255.255.0   U     0      0        0 wlan0

# netstat -t
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 10.0.0.7:48428          ec2-54-165-153-153.compute-1.amazonaws.com:5104 ESTABLISHED
tcp       54      0 10.0.0.7:38514          ec2-54-236-101-95.compute-1.amazonaws.com:5104 CLOSE_WAIT  

# cat /etc/resolv.conf
search Belkin # wlan0
nameserver 10.0.0.1 # wlan0
nameserver 8.8.8.8 # wlan0

We know a bit more about the hardware, software, networking, and etc. Now we should determine our inputs and outputs. This may help us discover attack surfaces as well. Since I'm the only person working on this and I have limited time, I can't go too deep into this.

Hardware inputs: Mic, Camera, Wireless, Mode switch(setup/normal usage), and power.
Hardware outputs: Speakers, IR lights, indicator LEDs, and Wireless.

Wireless output/input: well, it just does 2.4GHz. There is no bluetooth or other radio device.
When setup mode is enabled, by flipping the switch in the back, wl0.1 is turned on and it works as an AP. wlan0 is still on and if you did setup already, it will continue its connection to your AP while you configure the device through AP created on wl0.1.

Software outputs/inputs: It has some services running on it that make connection to AWS servers. We saw that when running netstat command. We also saw some ports open when running netstat as well, mainly port 80. There is a web server running on it. While testing, I noticed that when the switch is flipped to setup mode, more files are added in the web directory. When switch is flipped to normal operations mode, there is just one file in the web directory.  There are more things but this is just phase one.

Normal operations:
When you first get the camera, you'll have to set it up using a mobile app. The switch in the back is set to Setup mode. This creates an AP you connect to using your phone. After that you can run the setup application. You can select your AP that you want the wireless camera to connect to. After connection is made, you can setup an account and attach the camera to your account. After setup is done, you can flip the switch to normal operations mode.
The camera connects to cloud service to receive more information about configurations. It also sends out video to the AWS server.

Attacking:
If an attacker wanted remote shell on the device, there are some issues. First is, the camera is behind a NAT. It's not something you can find while scanning the internet. Another issue is, the attack surface is low. There are a few ports open. The web server, in normal operations mode, only serves one page.

Note:
So far, I haven't found any vulnerabilities. I may or may not continue researching this. Hopefully the commands and the process was useful though.

16 comments:

  1. Did you get anywhere else with this? I'm curious on trying to get the stream exported to VLC somewhere. please let me know

    ReplyDelete
    Replies
    1. Sadly, no. I will try to see if I can get RTSP stream working or capture the video feed of it as soon as I time.

      Delete
    2. Hey! Some good news.
      I setup the camera then put the switch in the back in "Camera" mode then I switched it again to "Setup" mode.
      I went to webserver folder and after messing around for a while, I found jsstream.asp, which pulls jpegs and streams. I'm still trying to figure some other stuff out and make sure this is repeatable.

      Delete
    3. Problem with putting it in the Setup mode is that it'll have open wifi for anyone else to connect. I'm trying to figure out a better workaround. Btw, jsstream.asp would be in http://WEBSERVER_IP/apcam/apcam/jsstream.asp for what I've describe in the above comment.

      Delete
    4. This comment has been removed by the author.

      Delete
    5. Thanks for the info/work. I know there is some other people on some other threads trying to figure out how to export the stream to Blue Iris or something else as well if you can get this working I'm sure donations will be coming your way. Thanks

      Delete
  2. (forgot to subscribe for notifications)

    ReplyDelete
  3. I'm definitely interested in being able to hack the StuartCam to allow access to the video stream via RTSP and/or HTTP so I can integrate these cameras into my home Zoneminder monitoring setup. I picked up 3 of them on sale at Walmart for $25 each and I'm really happy with the picture quality using the Tend app however having it integrated into Zoneminder to record locally instead across the Internet would be extremely ideal. If you need anyone to test just lemme know as I have about 20 years professional experience with Linux administration (it's my server and desktop OS of choice) including tinkering with SoC devices such as this via 3.3v TTL serial.

    ReplyDelete
  4. Might be able to spoof the ftp server it uses to upload data to via fake DNS entry. Run tcpdump on your router when it's capturing an event and you'll see what I mean.

    ReplyDelete
    Replies
    1. I was able to sniff the traffic but that sadly didn't help much. I've been messing with the device via serial.

      I did discover that adding stuff to /mnt/config is persistence across reboots.

      I was looking into getting remote command execution via the web pages so I can load up other files to the system.

      I wish the developers and designers had made this device better for people with different needs.

      Delete
  5. Most recent firmware @ https://app.isecurityplus.com/seedonk/firmware/minions/A356_upgrade_00.10.023_20180323.img

    ReplyDelete
  6. the person who create this post it was a great human..thanks for shared this with us. Melbourne Alarm Systems Installed

    ReplyDelete
  7. There are a number of types of lenses on sale for camera buffs who intend on capturing anything from wide angle to panoramic pictures. camcorder user guides

    ReplyDelete
  8. Any luck with this at all? I'm interested in streaming from this camera as well.

    ReplyDelete
  9. so I was able to access the video stream locally by setting the camera to setup mode and using the http://WEBSERVER_IP/apcam/apcam/jsstream.asp URL you provided, the bad think is that the camera is still in open AP mode, would it be possible to disable that wlan interface from the serial console?

    ReplyDelete