Pentest 48.3 MEDIUM + 48.4 INFO: Rate-Limit + Token-Invalidierung beim Staff-Passwort-Reset

48.3 (Rate-Limit fehlt): POST /api/users/:id/password verlangt seit
47.3 die Eingabe des eigenen Admin-Passworts. Ohne Throttle könnte
ein Angreifer mit gestohlenem JWT die Re-Auth per Brute-Force
aushebeln.
- Neuer staffPasswordReAuthLimiter (5 Versuche / 10 min,
  bucket: IP + target-user-id, skipSuccessfulRequests: true)
- emit SecurityEvent RATE_LIMIT_HIT severity HIGH
- Vor authenticate gemounted, damit auch unauth-Spamming
  begrenzt wird

48.4 (Alter Token überlebt Self-Reset): Nach erfolgreichem Setzen
wird tokenInvalidatedAt des Ziel-Users auf jetzt gesetzt. Greift
besonders bei Self-Reset (Admin setzt sich selbst zurück) – ein
zuvor gestohlenes Token wird sofort ungültig, statt bis zum
natürlichen Ablauf (15 min) brauchbar zu bleiben. Die bestehende
Auth-Middleware liest tokenInvalidatedAt bereits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-01 13:01:44 +02:00
parent 2c0166ed99
commit 5d21574c81
3 changed files with 51 additions and 3 deletions
+5 -2
View File
@@ -1,6 +1,7 @@
import { Router } from 'express';
import * as userController from '../controllers/user.controller.js';
import { authenticate, requirePermission } from '../middleware/auth.js';
import { staffPasswordReAuthLimiter } from '../middleware/rateLimit.js';
const router = Router();
@@ -10,8 +11,10 @@ router.post('/', authenticate, requirePermission('users:create'), userController
router.get('/:id', authenticate, requirePermission('users:read'), userController.getUser);
router.put('/:id', authenticate, requirePermission('users:update'), userController.updateUser);
router.delete('/:id', authenticate, requirePermission('users:delete'), userController.deleteUser);
// Passwort-Reset durch Admin dedizierter Endpoint (Pentest Runde 12)
router.post('/:id/password', authenticate, requirePermission('users:update'), userController.setUserPassword);
// Passwort-Reset durch Admin dedizierter Endpoint (Pentest Runde 12).
// 47.3 verlangt Re-Auth (currentPassword), 48.3 wirft einen Rate-Limit
// davor, damit ein gestohlener JWT das Admin-Passwort nicht brute-forcen kann.
router.post('/:id/password', staffPasswordReAuthLimiter, authenticate, requirePermission('users:update'), userController.setUserPassword);
// Roles
router.get('/roles/list', authenticate, requirePermission('users:read'), userController.getRoles);