jofpin / jofpin/trape

[Security] Authentication bypass: admin API endpoints lack session enforcement after /login

Open
#405 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
9k
Forks
1.4k
PR merge metrics
No merged PRs in 30d

Description

**Severity:** CRITICAL

**Affected file:** `core/stats.py` (login route: lines 51-57; unauthenticated endpoints: lines 59-125)

### Description
`/login` (`core/stats.py:51`) checks the POST'ed `id` against `trape.stats_key`, but on success it only returns a JSON payload with the operator's private paths (`home_path`, `remove_path`, etc.) — it never creates a Flask session, sets a signed cookie, or issues any token. The client just stores the key in `localStorage` and redirects.

None of the following endpoints verify the caller afterwards:
- `POST /get_data` (`stats.py:59`) — returns all tracked victims (IP, geolocation, browser fingerprints, captured form values)
- `POST /get_preview` (`stats.py:83`) — returns full profile for any `vId`
- `POST /get_requests` (`stats.py:99`) — returns all intercepted form submissions
- `POST /get_socialimpact` (`stats.py:105`)
- `POST /pn` (`stats.py:120`) — renames any victim record
- the dynamically generated `remove_path` endpoint (`stats.py:112`) — deletes any victim's data

These are fixed (non-random) or leaked paths, so authentication is effectively cosmetic: the only "gate" is a one-time key check on a page that never propagates any credential to subsequent requests.

### Reproduction
1. Locate a running trape instance (ngrok URL, local scan, or the `home_path`/`remove_path` values leaked by a successful `/login` response, victim-facing `injectCode`, Referer headers, etc.).
2. Without ever calling `/login` or knowing `stats_key`, send:
```
curl -X POST http://target:port/get_data
curl -X POST http://target:port/get_requests
curl -X POST -d "vId=&n=Spoofed" http://target:port/pn
```
3. All calls succeed and return/modify operator-only data.

### Impact
Any network-reachable third party (not just the intended operator) can read all captured victim PII/credentials, or tamper with victim records, with zero knowledge of `stats_key`.

### Suggested remediation
- On successful `/login`, establish a signed server-side session (`flask.session`) or issue a short-lived token.
- Add a decorator/`before_request` check on every admin endpoint (`/get_data`, `/get_preview`, `/get_requests`, `/get_socialimpact`, `/pn`, the remove path) that validates the session/token before executing any query.
- Do not rely on path obfuscation as an access-control mechanism.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in core/stats.py at the /login route on lines 51-57, then inspect the admin endpoints on lines 59-125 and the dynamically generated remove_path endpoint. Reproduce the unauthenticated curl requests to establish the current behavior. Done means successful login establishes a credential and every listed admin endpoint rejects unauthenticated requests while allowing authenticated access.

Written by the indexing model from the issue text.

Assessment

Tech stack
flask, python
Domain
api, authentication, backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.