Monday, January 11, 2016

SANS Holiday Hack Challenge 2015 - Part 0x01



Christmas means many things to many people, in my case, this an excellent season to share with my family and friends, but also, it's the perfect time for a security challenge. I really enjoyed SANS Holiday Challenge 2013, and even if I couldn't participate in 2014, and was expecting this year Challenge.

I was right, the Counter Hack Team did an excellent job: https://www.holidayhackchallenge.com/, creating an amazing plot, 8bits video game and a technical challenge that included: network/firmware forensic, Web Application with NoSQL Pen-Testing, and a C application Pen-Testing. 

This post is the first of the SANS Holiday Hack Challenge 2015 series, which includes part 01, 02 and 03 of the Challenge. I've changed all IP addresses to localhost, because the targets used in the Challenge were using AWS, and those IPs can be assigned to other tenants.

I’ll start each section with a short answer to the questions, and then provide a more technical explanation. 

Part 1: Dance of the Sugar Gnome Fairies: Curious Wireless Packets


1) Which commands are sent across the Gnome’s command-and-control channel?


There is a command exchange between the gnome and a super gnome (GS-01), using DNS queries with TXT type records encoded with base64. The main commands are:

- NONE: nothing to execute- EXEC: execute an internal command (application), like: iwconfig, cat /tmp/iwlistscan.txt- FILE: retrieve a file from the gnome.  FILE:/root/Pictures/snapshot_CURRENT.jpg


2) What image appears in the photo the Gnome sent across the channel from the Dosis home?

It’s a photo of the Dosis’ room, taken from the gnome:





John Dosis provided me with the pcap file in the Dosis Neighborhood. The pcap file contains two types of traffic: 802.11 exchange between client and Access Point (Probe request and Beacon Frame) and DNS (UDP, port 53) between the gnome (10.42.0.18) and the gnome Server. 

Let’s focus on the DNS query exchange. The client (gnome) continuously queries a “DNS server” with the following information: “cmd.sg1.atnascorp.com: type TXT, class IN”, and the server responds with a TXT record, e.g.: "TXT:  Tk9ORTo=“. The TXT is a standard type, however, the weird part is the content of the TXT record. The presence of the “=“ symbol aims to a possible BASE64 encoding. In order to find out, we cam simple send this string to openssl base64:

echo "Tk9ORTo=" | openssl base64 -d ; echo

This results with the following string: “NONE:"

Trying a couple more of TXT records, we can find the following strings:

RVhFQzppd2NvbmZpZwo=: EXEC:iwconfig

With this command things become more interesting, because the client (gnome) starts sending TXT responses to the Server (Supergnome) as a standard DNS TXT response (but client to server, instead of server to client):

RVhFQzpTVEFSVF9TVEFURQ==: EXEC:START_STATE

Instead of continuing testing all posible base64 strings, a better approach is to filter only the DNS flow, and create a new PCAP file with this flow, and use scapy to automate the recovery. With the support of scapy and python, the recovery of the base64 commands and responses is very easy. The script can be found here: https://github.com/skysec/SANSHolidayHack2015/tree/master/part01/scripts.
It takes three parameters: <path to the cap file> <path to the results file> <operation mode>.

There are two operations mode: “command” and “image”. Executing the script with operation mode “command", recovers all commands with the corresponding base64 strings. After decoding all base64 strings, there is a command that ask the gnome to send the current image: “FILE:/root/Pictures/snapshot_CURRENT.jpg”, for this reason, the recoverData.py script includes an option to decode the image included in the PCAP file. 

As a side note, there is another weird thing, but this time in the 802.11 traffic. The gnome is using a Network with the ESSID “DosisHome-Guest”, but most of the probes and requests are performed with the network “December”. However, in the iwscanlist  only shows the following networks: 

- ESSID: “CHC”, Encryption: On, Channel: 1- ESSID: “DosisHome”, Encryption: On, Channel: 6- ESSID: “DosisHome-Guest”, Encryption: Off, Channel: 6

Also, the iwconfig shows that the gnome is connected to the "DosisHome-Guest” network, which makes sense based on the information extracted from the firmware. 

Part 2: I’ll be Gnome for Christmas: Firmware Analysis for Fun and Profit

3) What operating system and CPU type are used in the Gnome? What type of Web framework is the Gnome web interface built in?

The operating System is based on Linux (OpenWRT, Bleeding Edge, r47650) with an ARM CPU. OpenWRT is a Linux distribution for embedded devices.

The Web Framework is a Server Side JavaScript system: Node.JS.

4) What kind of a Database engine is used to support the Gnome web interface? What is the plaintext password stored in the Gnome database?

The Database used is a NoSQL database: MongoDB. The plaintext password stored in the database is: “SittingOnAShelf”, for the user: “admin".

With the help of Jessica, in the Dosis Neighborhood, I downloaded the Gnome’s firmware (sha256):
bee93a79bb8ee2eba526494b4e6e56a601e1fa9589a1cccf7bfe61261ab8db20  giyh-firmware-dump.binExecuting “strings” on the image (strings giyh-firmware-dump.bin) shows a PEM encoded certificate and boot loader information. Reviewing the Certificate with openssl (openssl x509 -in cert.pem -noout -text), shows a self-signed x509 v3 Certificate with the following information:

- Issuer (same as subject): “O=ATNAS Corporation"- Not before:  "Nov 28 12:25:45 2015 GMT"- Not After: “Nov 25 12:25:45 2025 GMT"- Public Key: RSA 4096 bits

In order to extract more information, “binwalk”, is extremely helpful. Binwalk shows the following information (“./part02/files/binwalk.info"):

- 0 (0x0): PEM Certificate- 1809 (0x711): “ELF 32-bit LSB shared object, ARM, version 1"- 168803 (0x29363): “ Squashfs filesystem, little endian, version 4.0, compression:gzip, size: 17376149 bytes,  4866 inodes, blocksize: 131072 bytes, created: Tue Dec  8 18:47:32 2015"

This is a lot better, with “strings" the first two sections can be known, but now with the information obtained using binwalk,  it’s possible to extract the third section (squashfs). This is a job for “dd”, skip the first two sections, and then write the rest of the firmware image into a new file:

"dd if=giyh-firmware-dump.bin of=filesystem.squashfs bs=1 skip=168803"

This will take a long time (using one byte block size). This is very slow, but in order to speed up the process, it’s necessary to increase the block size, which means finding a number that can divide “168803” and the rest of the image (17376149), making this task very hard. 

After extracting the squashfs image (“filesystem.squashfs”), we can mount it using the following commands:

mkdir firmware_dirsudo mount -o loop filesystem.squashfs firmware_dir

Stepping into “firmware_dir” shows a POSIX based system. The “/etc” has most system configurations, a couple of files: “openwrt_release” and “openwrt_version”. Openwrt is a Linux distribution for embedded devices. 

The “/etc/hosts” contains the IP address of the Supergnome 01:

- “A.B.C.D    supergnome1.atnascorp.com sg1.atnascorp.com supergnome.atnascorp.com sg.atnascorp.com"

With a comment: “# LOUISE: NorthAmerica build”. This Supergnome (SG1) is for North America, so, there should be more of them around the globe. 

Let’s step into “init.d”, here there are five custom scripts with comments: mongod, nodejs, autowlan, sgstatd, sgstatd and sgdnsc2. It looks like: Stuart, Auggie, Louise and Nedford, have written these scripts. These scripts include the path of the executable commands. Let’s take a look:

- mongod: Looks like a standard mongo server program for ARM architectures: “ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)”. The config file is located in “/etc/mongod.conf” and has the path of the “db” directory: “/opt/mongodb”. We’ll look at it later.- nodejs: The program path is located in “/www/bin/www”, where “/www” is a standard directory estructure for a node.js application, including a package.json. - autowlan: This is a shell script with a loop (while true) that scans wireless network available, and tries to connect to open networks (encryption key: off). This explains how the Gnome connects from every home to the Supergnomes. - sgdnsc2: This is a binary file: “ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)” located in "/usr/bin”. Let’s run “strings” against this file:

“""Server specified NONE action.Server specified EXEC action.Failed to execute the command requested.Server specified FILE action.Control server says HELLO. Entering command mode.Connection could not be made. Sleeping.reply.willingvictim.comcmd.willingvictim.comcheck.willingvictim.com172.16.240.129HELLO:NONE:EXEC:FILE:EXEC:START_STATEEXEC:STOP_STATEFILE:START_STATE,NAME=FILE:STOP_STATE“""

This is the binary that performs the communication with the SuperGnome using DNS as a supporting protocol. 

- sgstatd: This is a binary file: “ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV)”. This is odd, this file is a x86 binary file, not an ARM compiled version. This explains a couple of things, like why Stuart, Louise, Auggie and Nedford couldn’t make the init script work in the Gnome. Of course it worked in development Louise, most probably you were using a x86 platform, not an ARM platform. Second, if this binary was compiled for a x86 architecture, maybe it’ll be used in the SuperGnomes. Let’s grab some information using “strings”:

“"“nobodyWelcome to the SuperGnome Server Status Center!Please enter one of the following options:1 - Analyze hard disk usage2 - List open TCP sockets3 - Check logged in users/bin/dfFailed to run command/bin/netstat -tan/usr/bin/whoEnter a short message to share with GnomeNet (please allow 10 seconds) =>Request Completed!Invalid choice!Canary not repaired.This function is protected!Server started...Unable to set SIGCHLD handlerUnable to create socketUnable to set socket reuse optionUnable to bind socketUnable to listen on socketUnable to find user/var/run/sgstatdUnable to change directory to /var/run/sgstatdUnable to remove extra groupsUnable to change GIDUnable to change UID/dev/urandom;*2$"GCC: (Debian 4.7.2-5) 4.7.2GCC: (Debian 4.4.7-2) 4.4.7“”"

There is a lot of information here: a menu, a couple of commands, user input message, and a canary. We’ll take a closer look later. 

Let’s explore the whole filesystem:

find . -type f -exec file '{}' \; > ../find.files"

It seems like our only x86 binary file is sgstatd, the rest of the files are: ARM executables, ASCII text, shell scripts and data. The following command:

egrep -R  '(STUART|LOUISE|AUGGIE|NEDFORD)' * | cut -d: -f1 | uniq"

Shows the files where those guys were involved (at least the ones they put their name on):

“”"etc/hostsetc/init.d/autowlanetc/init.d/mongodetc/init.d/nodejsetc/init.d/sgdnsc2etc/init.d/sgstatdetc/mongod.confetc/rc.d/Kmongodetc/rc.d/Knodejsetc/rc.d/Ksgdnsc2etc/rc.d/Ksgstatdetc/rc.d/S90autowlanetc/rc.d/S97mongodetc/rc.d/S98nodejsetc/rc.d/S98sgstatdetc/rc.d/S99sgdnsc2usr/sbin/autowlanwww/routes/index.js“”"

We’ve already checked most of these files, except the node.js app directory. 

Now, let’s check the mongodb database files: /opt/mongod. This is the content of the file directory: “ _tmp  gnome.0  gnome.ns  journal  local.0  local.ns”. The files local.* store the data of the “local” database, which stores data for the replication process and other instance-specific data (taken from mongodb reference manual). In this case, let’s sneak into the gnome files using “strings”:

“”"nome.settingssettingCurrent config file:value./tmp/e31faee/cfg/sg.01.v1339.cfgsettingAllow new subordinates?:valuesettingCamera monitoring?:valuesettingAudio monitoring?:valuesettingCamera update rate:value60minsettingGnome name:valueSG-01settingAllow file uploads?:valuesettingAllowed file formats:value.pngsettingAllowed file size:value512kbsettingFiles directory:value/gnome/1/files/gnome.statussg-availsg-upgnome.usersusernameuserpassworduseruser_levelusernameadminpasswordSittingOnAShelfuser_level“"'

I’ve removed a couple of entries, but it looks like configuration information of a SuperGnome, including usernames and passwords stored in clear text. For the sake of fun, let’s copy these files, and install our own instance of MongoDB. I copied the gnome.* files to the db directory in another host, set the right permissions, and run mongod. After accessing the mongo shell with “mongo”, we can run a couple of commands:

- “show collections”:“”"camerassettingsstatussystem.indexesusers“”"- “ db.cameras.find()”:“”"{ "_id" : ObjectId("56225c994a37f7d48337b9be"), "cameraid" : 1, "tz" : -5, "status" : "online" }{ "_id" : ObjectId("56225ca84a37f7d48337b9bf"), "cameraid" : 2, "tz" : 5, "status" : "online" }{ "_id" : ObjectId("563606624f51b1c4472f365e"), "cameraid" : 3, "tz" : -5, "status" : "online" }{ "_id" : ObjectId("563606834f51b1c4472f365f"), "cameraid" : 4, "tz" : -5, "status" : "online" }{ "_id" : ObjectId("563606a14f51b1c4472f3660"), "cameraid" : 5, "tz" : -8, "status" : "online" }{ "_id" : ObjectId("563606e84f51b1c4472f3661"), "cameraid" : 6, "tz" : 9, "status" : "online" }{ "_id" : ObjectId("56433d16ed9881a101c95422"), "cameraid" : 7, "tz" : -5, "status" : "online" }{ "_id" : ObjectId("56433d1aed9881a101c95423"), "cameraid" : 9, "tz" : -4, "status" : "online" }{ "_id" : ObjectId("56433d1bed9881a101c95424"), "cameraid" : 8, "tz" : -6, "status" : "online" }{ "_id" : ObjectId("56433d28ed9881a101c95425"), "cameraid" : 10, "tz" : -5, "status" : "online" }{ "_id" : ObjectId("56433d2bed9881a101c95426"), "cameraid" : 11, "tz" : 6, "status" : "online" }{ "_id" : ObjectId("56433d2fed9881a101c95427"), "cameraid" : 12, "tz" : 7, "status" : "online" }“”"- “ db.settings.find()”:“”"{ "_id" : ObjectId("562269a1b6e8d3a99a07300c"), "setting" : "Current config file:", "value" : "./tmp/e31faee/cfg/sg.01.v1339.cfg" }{ "_id" : ObjectId("562269b2b6e8d3a99a07300d"), "setting" : "Allow new subordinates?:", "value" : "YES" }{ "_id" : ObjectId("562269e0b6e8d3a99a07300e"), "setting" : "Camera monitoring?:", "value" : "YES" }{ "_id" : ObjectId("562269e9b6e8d3a99a07300f"), "setting" : "Audio monitoring?:", "value" : "YES" }{ "_id" : ObjectId("562269f3b6e8d3a99a073010"), "setting" : "Camera update rate:", "value" : "60min" }{ "_id" : ObjectId("56226a03b6e8d3a99a073011"), "setting" : "Gnome mode:", "value" : "SuperGnome" }{ "_id" : ObjectId("56226a0db6e8d3a99a073012"), "setting" : "Gnome name:", "value" : "SG-01" }{ "_id" : ObjectId("56226a1bb6e8d3a99a073013"), "setting" : "Allow file uploads?:", "value" : "YES" }{ "_id" : ObjectId("56226a2ab6e8d3a99a073014"), "setting" : "Allowed file formats:", "value" : ".png" }{ "_id" : ObjectId("56226a38b6e8d3a99a073015"), "setting" : "Allowed file size:", "value" : "512kb" }{ "_id" : ObjectId("56226a47b6e8d3a99a073016"), "setting" : "Files directory:", "value" : "/gnome/1/files/" }“”"- “ db.status.find()”:“”"{ "_id" : ObjectId("56421153b0aa2a3be47a2d04"), "sg-avail" : 5, "sg-up" : 5, "gnomes-avail" : 1733315, "gnomes-up" : 1653325, "backbone" : "UP", "storage" : 1353235, "memory" : 835325, "last-update" : 1447170332 }{ "_id" : ObjectId("564212abb0aa2a3be47a2d05"), "sg-avail" : 5, "sg-up" : 5, "gnomes-avail" : 1733315, "gnomes-up" : 1653325, "backbone" : "UP", "storage" : 1353235, "memory" : 835325, "last-update" : 1447170395 }“”"- “ db.users.find()”:“”"{ "_id" : ObjectId("56229f58809473d11033515b"), "username" : "user", "password" : "user", "user_level" : 10 }{ "_id" : ObjectId("56229f63809473d11033515c"), "username" : "admin", "password" : "SittingOnAShelf", "user_level" : 100 }“”"

Now, we’ve usernames and passwords!


Part 3: Let it Gnome! Let it Gnome! Let it Gnome! Internet-Wide Scavenger Hunt!

5) What are the IP addresses of the five SuperGnomes scattered around the world, as verified by Tom Hessman in the Dosis Neighborhood?
6) Where is each SuperGnome located geographically?

With the help of shodan.io, and using “supergnome” as search pattern, the following IP addresses are shown (and verified by Tom Hessman):


- SG-01: United States, Ashburn.
- SG-02: United States, Boardman.
- SG-03: Australia, Sydney
- SG-04: Japan, Tokyo
- SG-05: Brazil, Sao Paulo.




No comments:

Post a Comment