-
Notifications
You must be signed in to change notification settings - Fork 646
Description
Three event endpoints in timesketch/api/v1/resources/event.py accept a user-supplied _index parameter and perform write operations on it without verifying
the index belongs to the sketch in the URL. This allows an authenticated user to modify events (tags, attributes) in sketches they do not have access to.
Affected endpoints:
- EventUnTagResource.post() (line 1552) — removes tags from events
- EventTaggingResource.post() (line 560) — adds tags to events
- EventAddAttributeResource.post() (line 429) — adds attributes to events
EventAnnotationResource.post() (line 1001) in the same file correctly validates the index against the sketch's timelines, confirming this omission is
unintentional.
To Reproduce
Setup: user "dev" owns private Sketch 1, user "attacker" owns Sketch 2, attacker has no access to Sketch 1.
-
Confirm attacker cannot access Sketch 1:
GET /api/v1/sketches/1/ → 403 Forbidden -
Attacker strips tags from Sketch 1's events using their own Sketch 2:
curl -b attacker.cookies -X POST /api/v1/sketches/2/event/untag/
-H "Content-Type: application/json"
-d '{"events": [{"_id": "ZuZ9yZwBRv_2AkVDRN1P",
"_index": "4bb035e2f3ae4cbd87eeadb08d53cf5d"}],
"tags_to_remove": ["important", "confidential"]}'
Returns 200 OK. Victim's tags removed. -
Same pattern works for POST /api/v1/sketches/2/event/tagging/ (tag injection) and POST /api/v1/sketches/2/event/add_attribute/ (attribute injection).
Tested on Timesketch dev Docker, commit 39fcea1.
Expected behavior
The server should verify that the _index in the request body belongs to a timeline in the sketch specified in the URL. If it does not, the request should
be rejected with 403.
Suggested fix
Add index validation before processing events, matching the pattern already used in EventAnnotationResource:
allowed_indices = {t.searchindex.index_name for t in sketch.timelines
if t.get_status.status.lower() not in ("deleted", "archived")}
if searchindex.index_name not in allowed_indices:
abort(403, "Search index does not belong to this sketch.")
Additional context
This was reported to Google VRP and closed as not severe enough for security tracking. Google suggested public disclosure. The _index value is a stable
OpenSearch index name visible in every event API response, so a revoked collaborator who previously observed it can continue modifying events after access
revocation.