[Security] Authentication bypass: admin API endpoints lack session enforcement after /login
- 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