Building the IoT CTF Challenge for the HoneyLab CyberQuest CTF

I had been thinking about creating an IoT-based CTF (Capture The Flag) challenge for a while, but three pieces were missing: a CTF event, a good IoT target, and some outside motivation. But finally, all three came together at the same time.

We have recently hired Daniel, who told me that he also wanted to create an IoT-based CTF challenge. He was also already developing new CTF challenges for an upcoming CTF event in Budapest, called CyberQuest CTF by HoneyLab. And, just weeks before the CTF, I found this interesting demo app on the Espressif GitHub website:

This is simply an ESP32 with an e-ink display. The main idea of the app is that this is a test Matter light bulb device, and, as an additional twist, you can create a custom badge with your name/company name – although this was not used in the CTF. One thing I learned (the hard way) is that you should not develop your IoT device from scratch. And this platform seemed like a great start to build the CTF challenge on.

Matter is a connectivity standard designed to ensure interoperability between smart home devices from different manufacturers. Clearly, the first challenge was to pair/commission the device. By default, this is typically accomplished through a QR code provided by the IoT manufacturer. Matter made this process as easy as possible, so it would not be a challenge by default. The players of the CTF could see a QR code, but at first, it was gibberish. The challenge description suggested that the information is XOR-encoded with a 2-byte key. And if someone examines the Matter protocol, it is easy to determine that the QR code translates to a text starting with “MT:”.

This is an easy, 100-point cryptography challenge, where you XOR the gibberish with “MT:” to obtain the key. Or, for lazy people, brute-force all the keys and grep for “MT:” :). There was another unintended solution, which involved connecting to the device via USB/UART, using the “help” command, and discovering that there was a “matter” command. Then, using “matter help”, you could see options such as “matter onboardingcodes onnetwork” or “matter config”.

There were several possibilities for the pairing/commissioning. The easiest option was to use an iPhone, but this path would become a liability on subsequent levels. The more challenging solution was to use the chip-tool (CHIP is the earlier name of Matter). It is not trivial to determine which command-line option to use, but either a thorough reading of the documentation or a quick look at the LLM help can assist you. chip-tool pairing code <nodeid> <qrcodestring> is the one needed here. Another option could be to set up a Home Assistant server locally 🙂 Or matter.js if you are into Node.JS. Unfortunately, to do the pairing/commissioning from Android, you would need a Google Nest Hub or a similar Matter Hub device.

Once you successfully commission the device, you get the first flag!

The next task was to turn the light ON. This was probably the easiest flag to obtain, either by using the Apple Home app (click a single button) or by using the chip-tool app (chip-tool onoff toggle 110 1).

The next task was easy if you already had the chip-tool-based commission – or if you had dumped the firmware (unintended solution, but it’s fine). The goal was to query the device’s “hardware version string”. I don’t think it is possible to solve this one via the iPhone-only option.

Sorry* (*not sorry).

The following is the output for chip-tool basicinformation read hardware-version-string 110 0.

Or this is how the device looks in Home Assistant:

For the final challenge, once commissioned, this device served as a temperature monitor, providing new status updates every second. If you queried the device via chip-tool or viewed the Apple Home UI, you would have seen that the temperature fluctuates between 49 °C and 125 °C. Anyone who has played at least one CTF in the past can deduce that the flag is encoded in ASCII within the temperature. However, the easiest solution was to examine the UART output of the device, as it clearly displayed the full flag if you looked closely.

While developing these challenges, Daniel and I ran into tons of bugs and strange behaviors (and incompatible esp-idf/Matter versions), but in the end, everything worked out pretty well, and multiple attendees were able to solve all of the IoT-based challenges.

We congratulate all the participants and hope you can find a warm home and tinker with this ESP32 device at home.