Security-Hardening Runde 4: 9 Live-IDORs + Error-Handler
Live-Pentest gegen Dev-Server mit Portal-Token deckte auf, dass customer.* und gdpr.* Endpoints nur den Data-Sanitizer, aber KEINEN canAccessCustomer-Check hatten. Ein Portal-Kunde mit customers:read konnte per ID-Manipulation komplette Fremddatensätze auslesen. - customer.controller.getCustomer + getAddresses + getBankCards + getDocuments + getMeters + getRepresentatives + getPortalSettings: canAccessCustomer - gdpr.controller.getCustomerConsents + getAuthorizations + checkConsentStatus: canAccessCustomer - createAddress/createBankCard/createDocument/createMeter (customerId aus URL): canAccessCustomer (Defense-in-Depth – wird aktuell schon per Permission geblockt, aber im Controller ungeschützt) - Global Error-Handler: err.status respektieren (PayloadTooLargeError → 413 "Anfrage zu groß", SyntaxError → 400 "Ungültiges JSON" statt pauschal 500) Live-verifiziert: ✓ /api/customers/4 als Portal → 200 VORHER, 403 NACHHER ✓ 9 andere IDOR-Endpoints gleiches Muster ✓ Eigene Daten (/api/customers/1) weiter 200 ✓ 12 MB Body → 413, malformed JSON → 400 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ import * as gdprService from '../services/gdpr.service.js';
|
||||
import * as consentService from '../services/consent.service.js';
|
||||
import * as consentPublicService from '../services/consent-public.service.js';
|
||||
import * as appSettingService from '../services/appSetting.service.js';
|
||||
import { canAccessCustomer } from '../utils/accessControl.js';
|
||||
import { createAuditLog, logChange } from '../services/audit.service.js';
|
||||
import { ConsentType, DeletionRequestStatus } from '@prisma/client';
|
||||
import prisma from '../lib/prisma.js';
|
||||
@@ -229,6 +230,7 @@ export async function getDashboardStats(req: AuthRequest, res: Response) {
|
||||
export async function getCustomerConsents(req: AuthRequest, res: Response) {
|
||||
try {
|
||||
const customerId = parseInt(req.params.customerId);
|
||||
if (!(await canAccessCustomer(req, res, customerId))) return;
|
||||
const consents = await consentService.getCustomerConsents(customerId);
|
||||
|
||||
// Labels hinzufügen
|
||||
@@ -251,6 +253,7 @@ export async function getCustomerConsents(req: AuthRequest, res: Response) {
|
||||
export async function checkConsentStatus(req: AuthRequest, res: Response) {
|
||||
try {
|
||||
const customerId = parseInt(req.params.customerId);
|
||||
if (!(await canAccessCustomer(req, res, customerId))) return;
|
||||
const result = await consentService.hasFullConsent(customerId);
|
||||
res.json({ success: true, data: result });
|
||||
} catch (error) {
|
||||
@@ -799,6 +802,7 @@ export async function sendAuthorizationRequest(req: AuthRequest, res: Response)
|
||||
export async function getAuthorizations(req: AuthRequest, res: Response) {
|
||||
try {
|
||||
const customerId = parseInt(req.params.customerId);
|
||||
if (!(await canAccessCustomer(req, res, customerId))) return;
|
||||
// Sicherstellen dass Einträge für alle aktiven Vertreter existieren
|
||||
await authorizationService.ensureAuthorizationEntries(customerId);
|
||||
const authorizations = await authorizationService.getAuthorizationsForCustomer(customerId);
|
||||
|
||||
Reference in New Issue
Block a user