File size: 1,975 Bytes
ab4a9f0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
---
license: apache-2.0
tags:
  - security
  - proof-of-concept
  - picklescan
---

# PoC — picklescan blocklist evasion via `marshal.loads` + `types.FunctionType`

Proof-of-concept accompanying a **huntr Model File Vulnerabilities (MFV)** report against
[`picklescan`](https://github.com/mmaitre314/picklescan) **1.0.5**.

**This is a security research artifact.** The payload is deliberately harmless: it writes a
local file named `cyfra_marker` containing `EXEC_OK`. It does not touch the network, delete
anything, or write outside the working directory.

## The issue

`picklescan` blocks `types.CodeType` ("can construct arbitrary code objects") but:

1. **`marshal` is absent from the blocklist entirely** — and `marshal.loads(bytes)` returns a
   code object, so the `CodeType` entry is bypassable by design.
2. **`types.FunctionType` is not blocked**, so that code object can be turned into a callable
   and invoked through a second `REDUCE`.

Result: a pickle that executes arbitrary code on a plain `pickle.load()` is reported as merely
*suspicious*, with `Infected files: 0` and `Dangerous globals: 0`.

## Reproduce

```bash
pip install picklescan==1.0.5
python generate_poc.py

python -m picklescan.cli --path chain.pkl
#   Scanned files: 1
#   Infected files: 0
#   Suspicious globals: 2
#   Dangerous globals: 0      <-- not flagged as dangerous

python -c "import pickle; pickle.load(open('chain.pkl','rb'))"
cat cyfra_marker              # EXEC_OK  -> arbitrary code executed
```

No custom loader, no container trick, no attacker-controlled prerequisite: the standard
library loader runs it. For comparison, `fickling` 0.1.12 flags the identical file as
`LIKELY_OVERTLY_MALICIOUS`, showing detection is feasible.

## Suggested fix

- Add `marshal` (`loads`/`load`) to `_unsafe_globals` as dangerous.
- Add `types.FunctionType` (and consider `types.MethodType`) alongside `CodeType`.

## Attribution

Cyfra Tech Solutions (Roman Arce Bran), Costa Rica.