BreadCrumbs — HackTheBox Writeup

Aniket Badami
11 min readJun 5, 2021

This is a practical Walkthrough of “Breadcrumbs” machine from HackTheBox. Credit goes to helich0pper for making this machine available to us.

Passwords, hashes and Flags will be redacted to encourage you to solve those challenges on your own.


“Breadcrumbs” is marked as hard difficulty machine that features Apache hosting PHP web pages on Windows 10 OS. The homepage is a library to look for books and borrow them for reading. The book checkout section is misconfigured and that allow us to look for other files (.php) on the server. Certain .php file reveals secret key for JWT signature, hardcoded admin username, cookie generating mechanism. We take advantage and get admin account, admin has access to upload zip files to server, we use that to get our initial access on target. We use breadcrumbs left for us to gain user access and we perform sql injection on locally running DB to get administrator encrypted creds. We decrypt the creds using AES key to get clear text password.

Skills Required

  • Web Enumeration
  • PHP Code Review
  • DB Enumeration

Skills Learned

  • PHP Code Enumeration
  • AES Decryption



Nmap reveals that target is running SSH, HTTP/S, SMB, MYSQL. Target is windows OS and MYSQL don’t allow other IPs to connect it, probably the connection is only allowed to localhost.

Let’s checkout the webpage.


It’s a PHP website, no robots.txt file, nothing in source code and no login on webpage. Looks like a library where we can search for books.


So sad to see that no books on LOTR :(

We got some book names by just using title name as single alphabet.


If we click on any book, then it pops up this screen.


If we click “yes”, then it gives us this poup.


Let’s capture request in burp suite.


The post request is to /bookController.php file, if we change the method value to 1 and send the request then we get the below warning response.


As you can see in second warning, it is using a php function called “file_get_contents” to get information from a directory called “/books/”.

As we changed the method value to 1, my guess is Method 0 is listing the contents of directory and method 1 will read a specific file from the directory.

If there’s a book directory then let’s try to access it directly via browser.


These are not actual books, but just information.


Let’s capture request from ‘action’.

buro request

As you can see it’s requesting “book3.html” using method 1. We can leverage this to read other files from the directory. Let’s read ‘index.php’.

read index.php

As you can see it returned with warning, saying failed to access index.php. That file is not in the current directory (/books), so let’s take one directory back and try to read it.


It worked, we can go back and forth any directory to read the contents of file. Let’s read that POST request file (/includes/bookController.php).


This php file is revealing (/db/db.php), by the response it looks like it’s using mysql DB. Let’s read that db.php file.


We got DB user:password and DB name. It looks like it’s bound to only local host, that means it’s not possible to authenticate remotely to DB, we have to have access to local machine to access. After initial access we can probably access it.

I tried using those credentials to SSH, but it didn’t work. Let’s run gobuster to find fils and directories, which we will read once we know.


We got couple interesting directories and files. Let’s visit portal via browser.

We got login page but the error says, it’s restricted for my IP address. Let’s signup and login.


We logged in successfully, but our role is awaiting for approval. If we check tasks, then we’d some issues which has been resolved and one is not.


The file management is not accessible to us. Let’s run gobuster on /portal directory to find any files.

gobuster on /portal

Interesting files in /portal directory, let’s read login.php via burp suite.


When we read “login.php” code, it reveals another php file called ‘authController.php”. Let’s read that file.


This php file reveals a “secret key” and cookie.php file. Secret key is being used signing for JWT (JSON Web Token). JWT will only be used for account authorization purposes.

Let’s login on /portal, intercept request on burp and find our own JWT.


As you can see we have PHP session ID and token (JWT) both are under cookie header. Before we read cookie.php file, let’s confirm that in fact we are using JWT or not.

To confirm you can use wesbite. Copy the token and paste it in encoded section.


As you can see, it decoded the token. My username is displayed in payload and in header we have HS256 (HMAC SHA256 — Hashing algorithm) to sign and verify. It’s also showing that signature is invalid. Let’s copy that “secret key” which we got from “authController.php” file and input it in signature section.

JWT Signature

As you can see now it says that valid signature. That “secret key” is actually being used for verification of JWT header. Now we can modify headers to gain privileged user access.

For privileged user access we need PHP Session ID of that admin user. If you remember from user management, there are three administrators.

admin accounts

We have to use one of them to get admin access. But first we need to figure out how these cookies are being generated. To know that we again use burp to read “cookie.php” file.


According to php code, it’s taking 1 random string from username, hashing it using MD5 algorithm and using it as session cookie. Let’s say for example, “paul” user, there are four possible session IDs, because paul has four alphabets.

  • a2a6a014d3bee04d7df8d5837d62e8c5
  • 61ff9d4aaefe6bdf45681678ba89ff9d
  • 8c8808867b53c49777fe5559164708c3
  • 47200b180ccd6835d25d034eeb6e6390

You can generate for yourself like below.


Why I used paul user is, in one of the /includes directory I found another PHP file called “fileController.php”.

/includes Directory

If we read this file using burp, then we’d find “paul” is hardcoded as admin and he has access to upload zip files to server.


Now we have all the required elements to gain admin (paul) access. Now we craft JWT with “paul” as username.


Now we use this encoded data with paul’s Session ID. We can use them with burp suite, but every time we move around webpage we have to use cookie ID and JWT. So we use cookie-editor, it is available for Firefox.

cookie editor

Paste the encoded token and Session ID and save it. Reload the webpage.

admin dashboard

Initial Access

Now we have access to admin account (paul). Check “file management” section. It allows us to upload files.


As you can see, it only allows to upload “.zip” files, we can change the extension in burp suite to bypass the restriction. Use any PHP webshell, give it a name, upload and intercept in burp suite.

Note: Remember, this is a windows OS, linux PHP web shells won’t work. Use This Web Shell

At the end of the request, we have to remove .zip and add “.php” to our uploaded file. Now send the request to server. If everything goes right, then you’d see “success, have a great weekend” message.

Our web shell is on target, now we need to access it to get reverse shell. Setup a netcat listener and access you php file.

access php
Reverse shell

Aight, *hacker voice* we are in. We got our initial access. As you can see we got service account, not user account. Let’s switch to Powershell mode and find users.


We got two users, “Juliette” and “Development”. Let’s search all the files for “Juliette” string and look for any stored credentials.


We found user credentials in one of the directory under xampp. Let’s SSH into that user and read our user flag.

user flag

Let’s read that todo.html file from desktop.


This file gives us some hints to our next path. They are migrating their stored passwords from “sticky notes” to “Password Manager”. It’s still in progress, so if we can find the sticky notes DB then we can read the stored passwords.

Privilege Escalation — root

A quick google search reveals that sticky notes use a sqlite DB and the default file name is “plum.sqlite”. So, we can search for this filename using PS.

Sqlite DB

We need to copy these DB files to our kali linux machine to read the contents. We will use Impacktes to start a SMB server on Kali Linux.


Our SMB server is ready to receive files. Let’s access our “kali” shared directory and copy the DB file in it.

Access SMB
Copy DB Files
DB on Kali Linux

We got the all the required DB files, let’s read the DB for any stored clear text credentials.


They have already moved the administrator password to password manager application, but we got credentials of development user account. Let’s SSH into that user.


In C:\ drive there’s a development directory and in that there’s a linux binary. Let’s copy that to our Kali Linux using same methods which we used previously.

copy binary

It’s an ELF file, so we can print the sequence of printable characters from the file. As you can see it’s requesting a specific hostname and port address and trying to fetch username and password of administrator from the database.

Let’s check port if 1234 is open or not on Windows machine.

port 1234

It is listening on not on, that means this port is not directly accessible from remote machines, like ours. We can forward this 1234 port to our Kali Linux using SSH or Chisel.

port forward

I will use SSH to forward the target local port to my port. Now let’s access 1234 port.


As you can see from the above error, it’s accessing index.php file from administrators desktop. This error also shows that it is using “mysqli” extension to access MYSQL Database server. Perhaps we can perform SQL Injection to dump all the database.


We got administrator password and AES Key. The Password looks like Base64 encoded data and the actual password is encrypted using AES algorithm. First we have to decode using base64 and then decrypt using AES key. For this process we can use GCHQ’s CyberChef.


We go the password of administrator by decrypting AES with its key. Now we can SSH into Admin shell.

root flag

We got all the flags required to complete this machine.


After getting admin credentials I tried to access DB of 1234 port, for some reason the DB didn’t allow me to access. So, I check the index.php code and found that the DB username is completely different and password is which we retrieved from sqlmap.


Thank you for reading this blog. While attempting this challenge I learned so many things. This was unique target with unique vulnerability.