GHSA-42cr-w2gr-m54q
wger: IDOR via user-unscoped cache keys on routine API actions exposes workout data
상세
### Summary
Five routine detail action endpoints check a cache before calling `self.get_object()`. Cache keys are scoped only by `pk` — no user ID is included. When a victim has previously accessed their routine via the API, an attacker can retrieve the cached response for the same PK without any ownership check.
### Details
`wger/manager/api/views.py` — five actions follow this pattern (lines 134–201):
```python @action(detail=True) def date_sequence_display_mode(self, request, pk=None): cache_key = make_routine_api_date_sequence_display_cache_key(pk) cached = cache.get(cache_key) if cached: return Response(cached) # returned WITHOUT calling self.get_object() # only reaches ownership check on cache miss routine = self.get_object() ... ```
Cache key construction in `wger/utils/cache.py:89–106`:
```python def make_routine_api_date_sequence_display_cache_key(routine_id): return f"routine-api-date-sequence-display-{routine_id}" # No user ID in key ```
Cache TTL: 1 month (`4 * 604800` seconds, `settings_global.py:461`).
Affected endpoints: ``` GET /api/v2/routine/{pk}/date-sequence-display/ GET /api/v2/routine/{pk}/date-sequence-gym/ GET /api/v2/routine/{pk}/structure/ GET /api/v2/routine/{pk}/logs/ GET /api/v2/routine/{pk}/stats/ ```
### PoC
``` 1. Victim (user A) visits GET /api/v2/routine/5/structure/ → response cached under key "routine-api-structure-5" 2. Attacker (user B) visits GET /api/v2/routine/5/structure/ → cache hit → returns user A's routine structure without any ownership check ```
Requires the victim to have previously accessed the endpoint (cache must be populated). Once populated, the cache entry is valid for 1 month.
### Impact
An attacker with a registered account can retrieve another user's routine details — workout day sequences, exercise structure, training logs, and statistics — from cache without ownership verification.
**Fix**: Include the user ID in the cache key: ```python def make_routine_api_date_sequence_display_cache_key(routine_id, user_id): return f"routine-api-date-sequence-display-{user_id}-{routine_id}" ```
Or move `self.get_object()` before the cache lookup so ownership is always verified first.
이 버전이 영향받나요?
사용 중인 패키지 버전을 입력하면 즉시 평가합니다.
영향 패키지
0 No fixed version published yet for wger (pip). Pin to a known-safe version or switch to an alternative.