This year’s West Lake Sword IOT part provided a development board equipped with OpenWrt, and participants needed to analyze the development board and the provided Firmware.zip to answer the questions posed by the organizers.
Two
Overview of Questions and Score Distribution
Since there were no screenshots of the questions retained, I organized the competition questions based on my and my teammates’ memories:Several announcements were also made during the competition:(1) The Firmware.bin provided by the competition is an incomplete firmware, please do not attempt to flash it onto the development board.(2) The MQTT service has RCE vulnerabilities.(3) The MQTT username is xhlj2024.(PS: Announcement (1) was released after I modified the root password and attempted to repackage and flash it XD)
Three
Analysis of Questions 1 to 5
(1) Analyze the Reset Button
There is a relatively obvious silk screen “PORST” on the board, and testing it with a multimeter shows that its normal state is high level:By grounding it with a male-to-male Dupont wire, I observed that the development board successfully reset.
(2) Analyze Flash Model
The flash model can be obtained from two places.First, from the serial output of the micro USB, it is known that the flash model is W25Q256FV:Then, by reading the silk screen on the board, the flash model is also identified as w25q256jveq:It was found that these two were actually different, and the organizer said to take the silk screen as the standard.By consulting the official manual, information about the flash, including its capacity, can be obtained:
(3) Analyze Baud Rate
At the moment the board restarts, press 4 to enter the uboot shell and use printenv to check some parameters during boot.Among them, there is information about the baud rate, which is 57600.
(4) 8888 Port Service Analysis
By searching for “8888” in everything, it was found in nginx.conf:It is found that it forwards to port 1883, which is the MQTT service.
(5) Password Brute Force on XXX Port
In (4), the MQTT service was found, and it is assumed that this xxx port is the MQTT’s 8888, looking for whether there is a password for MQTT.The mqtt password file /etc/pwfile was found in the /etc/mosquitto.conf file.Its content is:
(PS: The content here is the result of dumping the firmware running on the board after the competition, not the content in the firmware.bin provided by the organizer at the beginning)Inquiring with a colleague, it was learned that this is the content after sha-512 and base64 salt encoding, and if the password is a 7-digit number, a brute force script can easily find the answer.Brute force script:
import hashlib
import base64
# Target hash value (string before Base64 decoding)
target_hash_base64 = "aYIMt03T2goWCa6JLX7QY6/p4C3lUzGZIUueePaHibbiihShFGufRHXzhCEeVGW4u7o39DCUEeTPASKH/0N6mQ=="
# Decode the Base64 encoded target hash value into hexadecimal
target_hash = base64.b64decode(target_hash_base64).hex()
print(target_hash)
# Salt value
salt = base64.b64decode("pvCQQygWXp04MJao")
# Hash function, using SHA-512 and considering the salt value
def hash_password(password, salt):
return hashlib.sha512((password).encode()+salt).hexdigest()
print(hash_password(str('0123456').rjust(7,'0'), salt))
# Try all 7-digit passwords
for password in range(0, 10000000):
if hash_password(str(password).rjust(7,'0'), salt) == target_hash:
print(f"Found password: {password}")
break
else:
print("No matching password found.")
Output:Therefore, the login password for MQTT is 2758934.At this point, we need to conduct static analysis on the given firmware to find answers to questions 6 to 8, including (5). If we did not have the organizer’s hints, we would need to extract the firmware from the board to obtain the real complete firmware to brute force the answers.In summary, if we want to further solve the problems, we still need to get a shell, and there are two ideas:(1) Use hardware means to dump the firmware from the board, modify the root password in the firmware, and then flash it back via uboot tftp to obtain the root shell.(2) Use some service vulnerabilities for RCE.
Four
Research on Firmware Dumping
By using a magnifying glass, it can be seen that this is a WSON8 flash, which can be extracted using a WSON8 chip clip and a CH341 programmer.The board also has pins related to flash and 3v3 testing points, and eight wires can be connected to a CH341 programmer or Raspberry Pi for firmware extraction:However, no matter which way the firmware is extracted, it seems incomplete when unzipping with binwalk. After the competition, I communicated with Master BadMonkey from TianShu, who also said that the extracted firmware is incomplete, and I was puzzled as to why. My Raspberry Pi 4b could only read the chip model but could not extract the firmware.Additionally, the board also has a JTAG port:It is suspected to connect to the MCU’s internal flash, but it is a 6-pin non-standard JTAG, making it difficult to determine which is which without a JTAGulator (but I don’t have a JTAGulator QAQ), so it is hard to read and test with JLINK.So I temporarily gave up on the path of dumping the firmware and turned to study RCE.
Five
Research on MQTT RCE
During the competition, the organizer provided a hint that there is an RCE vulnerability in MQTT, but at that time, I hadn’t extracted the eight wires yet, and the competition was nearing its end. So I could only conduct research after the competition.After the competition, the organizers provided the SSH password for the root user, allowing me to connect and check the processes related to MQTT:By comparing with the source code on GitHub, it was found that the reverse code of Mosquitto is not much different from the source code, but mosquitto_sub is somewhat different, and it specifies the “block” and “logs” topics, which seems to be a process implemented by the question setter themselves.By reversing, I was able to find the pseudo-code related to these two topics:It can be seen that the JSON format for sending messages is:
{"log":1,"timestamp":"xxxx","info":"xxxx"}
Moreover, if you publish to the “logs” topic, it will call system to generate files related to the given timestamp in the “/var/log” directory, which seems to allow for command injection by constructing a special timestamp.However, the function “sub_4100dc” performs format validation on the timestamp:The specific format of the timestamp should be as follows:
aa-bb-cc:dd:ee
aa is the standard month format
bb is the standard day format
cc dd ee are the standard hour, minute, second formats
This means it is difficult to inject through the timestamp.Looking at the subsequent processing related to “info”:It can be found that “info” undergoes two rounds of operations to become “info2”, and after passing the verification, “info2” is treated as a parameter and passed to snprintf, ultimately resulting in command execution. If the final “info2” is a string like ‘”\n/bin/sh\n’, command injection can be achieved.To determine whether injection is possible, we need to reverse the operations transforming “info” into “info1” and then into “info2”.With the help of the reverse engineer DaDa, I successfully restored the symbol table of several key functions:(PS: The SM4Crypt is found to be the decryption process of SM4)Filtering by the filter:However, it does not filter “\n”, so there is still a possibility of injection.Backtracking, the input “info” should be a string like ‘”\n/bin/sh\n’ that is first SM4 encrypted and then base64 encoded.It is worth noting that “info1”, which is the first byte of the base64 decoded result of the input “info”, is the control byte. To satisfy the requirements of ctrl and allow memcpy to copy as much content as possible, ctrl should be 0xBF.Thus, the constructed “info” should be the injected string encrypted by SM4, with 0xbf prepended and then base64 encoded.Here, I chose to use wget to retrieve an executable file generated by msf, which would reverse back to the host on port 6666, then chmod +x and execute it as the RCE method. The actual tested maximum length of the injected string is 0x20, so I chose the following three commands:
After RCE, I can log in and execute “netstat -pantu” to check the ports and corresponding processes:It can be seen that 5679 is the process for the network.For questions (6) and (8), they seem to be traffic analysis questions, so I might upload a tcpdump to capture the traffic for evidence, which is not something I am too skilled at, so I just skimmed through it.
Seven
Summary
From reviewing the entire process, this year’s IOT questions involved analysis at both the hardware and firmware levels, but achieving RCE in a short time still seems quite challenging, and it’s easy to fall into the awkward situation of being unable to extract the firmware and RCE (this is the situation I encountered at that time). However, overall, I still gained a lot from the entire review process.
KanXue ID: Nameless_a
https://bbs.kanxue.com/user-home-943085.htm
*This article is a featured article from the KanXue Forum, originally written by Nameless_a, please indicate the source from the KanXue community when reprinting.
# Previous Recommendations
1、Hypervisor From Scratch: Setting Up Our First Virtual Machine
2、Custom Linker Implementation Analysis Path
3、Reverse Analysis of the Kernel Hooked by VT
4、Aliyun CTF 2024 – Solution to ENOTYOURWORLD Challenge
5、Hypervisor From Scratch – Basic Concepts and Configuration Testing Environment, Entering VMX Operation