Ein mittelgroßer Energieversorger in Nordrhein-Westfalen entwickelt eine REST-API für die Integration von Wärmepumpen. Das Ziel: Wärmepumpen-Hersteller sollen über die Schnittstelle auf Netzsignale reagieren können — bei Spitzenlast drosseln, bei Einspeiseüberschuss hochfahren. Regulatorisch ist das sogar gewünscht, Stichwort § 14a EnWG.
Drei Wochen nach Go-live: 47.000 Requests pro Stunde auf einem Endpoint, der für 500 ausgelegt war. Keine einzige legitime Wärmepumpe dahinter — automatisierte Scraper auf der Suche nach exponierten Messdaten. Die SAP-Anbindung läuft unter Last, das Entstörungsdashboard reagiert verzögert, das IT-Team verbringt den Montag damit, Schaden einzugrenzen.
Niemand hatte Rate Limiting eingebaut.
Das ist kein Einzelfall. Es ist das vorhersehbare Ergebnis, wenn APIs nach dem Muster „erst bauen, dann irgendwann absichern“ entwickelt werden.
Warum Stadtwerke besondere Angriffsziele sind
Energieversorger und Stadtwerke gelten nach BSI-IT-Grundschutz und NIS2-Richtlinie als kritische Infrastruktur. Das bedeutet: Angreifer haben ein besonderes Interesse an diesen Systemen — nicht nur für Datenmissbrauch, sondern für Versorgungsunterbrechungen, Erpressung und gezielten Vertrauensschaden beim Endkunden.
Gleichzeitig öffnen Stadtwerke IT-Architekturen, die jahrzehntelang intern betrieben wurden, zunehmend nach außen:
- Kundencenter-Portale mit Self-Service (Zählerstandsmeldung, Abschlagsänderung, Vertragsverwaltung)
- APIs für § 14a-konforme Steuerung von Wärmepumpen und Ladesäulen
- Smart-Meter-Gateway-Kommunikation über standardisierte Schnittstellen
- B2B-Portale für Installateure, Hausverwalter und Energieberater
Jeder dieser Kanäle ist ein potenzielles Einfallstor. Nicht weil die Entwicklerteams schlechte Arbeit leisten — sondern weil „öffentlich erreichbar“ und „abgesichert“ zwei verschiedene Aussagen sind.
Schicht 1: Eingabe-Validierung — kein blindes Vertrauen in Payloads
Der erste Angriffspunkt jeder API ist der eingehende Datenstrom. Ein Request an /api/v1/zaehlerstand trägt Nutzdaten mit — und viele APIs behandeln diese Daten als vertrauenswürdig, bevor sie irgendeine Prüfung durchlaufen haben.
Das ist ein Fehler.
Was Eingabe-Validierung konkret bedeutet
Validierung prüft, ob eingehende Daten das erwartete Format, den erwarteten Typ und den erwarteten Wertebereich haben — bevor sie irgendetwas in der Systemarchitektur auslösen.
import { z } from "zod";
const zaehlerstandSchema = z.object({
zaehlerNummer: z.string().regex(/^[0-9]{8,12}$/),
ablesewert: z.number().min(0).max(999999),
ablesedatum: z.string().datetime(),
ablesegrund: z.enum(["selbstablesung", "netzbetreiber", "einzug", "auszug"]),
});
const parsed = zaehlerstandSchema.safeParse(body);
if (!parsed.success) {
return errorResponse(400, "VALIDATION_ERROR", "Ungültige Eingabedaten");
}
Was das konkret verhindert
Injection-Angriffe: Ein zaehlerNummer-Wert mit SQL-Sonderzeichen ('; DROP TABLE messwerte;--) erreicht nie die Datenbankschicht. Das Regex-Muster ^[0-9]{8,12}$ lässt ausschließlich achtstellige bis zwölfstellige Ziffernfolgen durch.
Plausibilitätsfehler: Ein ablesewert von -500 oder 9.999.999 wird abgelehnt, bevor er in SAP IS-U oder das Messwertemanagementsystem einläuft.
Formatfehler: Ein ablesegrund von "hacking" ist kein gültiges Enum-Mitglied — sofortige Ablehnung ohne weiteren Code-Pfad.
Oversized Payloads: Maximallängen auf String-Feldern verhindern, dass 10-MB-Payloads die API-Schicht blockieren.
Die meisten Sicherheitslücken entstehen nicht durch ausgeklügelte Exploits, sondern durch fehlende Eingabeprüfung. Das gilt für Stadtwerke genauso wie für jede andere API-Architektur.
Schicht 2: Rate Limiting — auch KRITIS-Infrastruktur hat Kapazitätsgrenzen
Validierung schützt vor falschen Daten. Rate Limiting schützt vor zu vielen davon.
Das Grundprinzip
Pro IP-Adresse wird gezählt, wie viele Requests innerhalb eines definierten Zeitfensters eingehen. Überschreitet ein Client das Limit, erhält er 429 Too Many Requests — bis das Zeitfenster zurückgesetzt ist.
Für Stadtwerke-APIs ist ein IP-basierter Ansatz der Einstieg. Für B2B-Integrationen — Wärmepumpen-Hersteller, Installateure, Aggregatoren — ist ein Key-basiertes Limiting sauberer, weil hinter einer einzelnen IP mehrere legitime Geräte stecken können.
Limits nach Endpoint-Typ
| Endpoint-Typ | Empfohlenes Limit | Begründung |
|---|---|---|
| Öffentliche Informations-Endpoints | 120/Minute pro IP | Lesend, kostengünstig, hohe Toleranz vertretbar |
| Zählerstandsmeldung (POST) | 5/Minute pro Kundenkonto | Reale Nutzer melden selten mehr als einmal täglich |
| § 14a-Steuerungs-API | 10/Minute pro Device-Key | Pro Wärmepumpe bzw. Ladesäule klar definiert |
| Störungsmeldung | 3/Minute pro IP | Schreibend, E-Mail-Trigger, hohes Missbrauchsrisiko |
| Authentifizierungs-Endpoint | 5/Minute pro IP | Brute-Force-Schutz für Login-Versuche |
Die Limits müssen zum realen Nutzungsverhalten passen. Wenn ein Installateur über ein B2B-Portal 200 Geräte anlegt, greift er innerhalb einer Stunde legitim sehr häufig zu. Ein pauschales Niedriglimit blockiert legitime Nutzung — das ist genauso schädlich wie gar kein Limit.
Die Response bei Limit-Überschreitung
Ein konforme API-Client liest die HTTP-Header und wartet:
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1743523200
{
"error": "RATE_LIMITED",
"message": "Zu viele Anfragen. Bitte in 45 Sekunden erneut versuchen.",
"retryAfterMs": 45000
}
Eine Wärmepumpe, die nach § 14a in 15-Minuten-Intervallen Steuersignale abruft, kommt mit einem Limit von 10/Minute problemlos zurecht. Ein automatisierter Scraper, der 200 Requests pro Sekunde sendet, wird gestoppt.
Schicht 3: Error Sanitization — Fehlermeldungen als Informationsquelle
Wenn etwas schiefgeht, antwortet jede API mit einer Fehlermeldung. Was diese Meldung enthält, entscheidet darüber, wie viel ein Angreifer über die interne Systemarchitektur lernt.
Das Problem: ungefilterte Fehler in Produktion
Ein typischer Entwicklungsfehler, der im Produktivbetrieb landet:
{
"error": "Error: P2002 — Unique constraint failed on the fields: (`zaehlerNummer`)",
"stack": "at PrismaClient._executeRequest (/app/node_modules/@prisma/client/runtime/library.js:127:15) at /app/lib/db/meter.ts:43:22"
}
Was ein Angreifer daraus ableitet:
- Den verwendeten ORM (Prisma)
- Den Datenbanktyp (PostgreSQL oder MySQL — beide nutzen Fehlercode P2002)
- Den Dateipfad im Produktionssystem
- Die interne Feldbezeichnung
zaehlerNummer - Dass Zählernummern als Unique-Index hinterlegt sind — Information für gezielte Enumeration
Das ist kein hypothetisches Risiko. Es passiert täglich in Systemen, die seit Jahren im Betrieb sind und nie ein strukturiertes Security-Review hatten.
Saubere Error-Responses
{
"success": false,
"error": {
"code": "INTERNAL_ERROR",
"message": "Interner Serverfehler."
}
}
Die vollständige Fehlermeldung landet im internen Logging-System — wo sie Entwickler sehen können. Externe Aufrufer bekommen ausschließlich den Code und eine generische Beschreibung.
Definierte Error-Codes für Stadtwerk-APIs
| Code | HTTP-Status | Verwendung |
|---|---|---|
UNAUTHORIZED | 401 | API-Key fehlt oder abgelaufen |
FORBIDDEN | 403 | Key hat keine Berechtigung für diesen Endpoint |
RATE_LIMITED | 429 | Limit überschritten |
VALIDATION_ERROR | 400 | Eingabedaten entsprechen nicht dem Schema |
NOT_FOUND | 404 | Zählernummer oder Kundenkonto nicht gefunden |
INTERNAL_ERROR | 500 | Serverfehler ohne interne Details |
Sechs Codes decken 99 % aller Fehlerzustände ab. Wer diese Codes in der API-Spezifikation dokumentiert, ermöglicht integrierenden Systemen — Wärmepumpensteuerungen, B2B-Portale, Smart-Home-Plattformen — gezielt darauf zu reagieren, ohne interne Systemdetails zu kennen.
Schicht 4: Authentifizierung — wer darf welchen Endpoint aufrufen
Öffentliche Stadtwerke-Websites haben Inhalte, die ohne Authentifizierung sichtbar sind: Preisblätter, Tarifrechner, Kontaktseiten. Das ist korrekt.
Aber die API dahinter ist nicht automatisch öffentlich, weil die Website öffentlich ist.
Das Spektrum: offen bis geschlossen
| API-Typ | Authentifizierung | Begründung |
|---|---|---|
| Tarifrechner (GET) | Keine | Information ist öffentlich, kein Personenbezug |
| Störungsmeldung (POST) | Kein API-Key | Öffentliche Infrastruktur — Rate Limit schützt ausreichend |
| Zählerstandsmeldung | Kundenkonto-Auth | Personenbezogene Daten, DSGVO-relevant |
| B2B Wärmepumpen-API | API-Key mit Scopes | Pro Integrator ein dedizierter Key |
| § 14a-Steuerungs-API | API-Key + Device-ID | Jedes Gerät eindeutig identifiziert |
| Internes Reporting | OAuth 2.0 | Ausschließlich für autorisierte interne Systeme |
API-Key-Scopes — minimale Berechtigung pro Integrator
Ein Wärmepumpen-Hersteller bekommt einen API-Key mit genau den Scopes, die seine Integration benötigt — nicht mehr:
Bearer sk_live_partner_abc123...
Scopes: steuerung:read, steuerung:write
Erlaubte Endpoints: /api/v1/geraet/*, /api/v1/steuerung/*
Rate Limit: 600/Stunde (konfiguriert für die erwartete Gerätezahl des Partners)
Dieser Key kann keine Kundendaten abrufen. Kann keine Zählerstände lesen. Kann keinen anderen Integrations-Partner beeinflussen. Wird der Key kompromittiert, ist der Schadenradius auf die explizit freigegebenen Endpoints begrenzt.
Schicht 5: Was intern bleibt
Genauso wichtig wie aktive Schutzmaßnahmen ist die Entscheidung, welche Daten nie den internen Bereich verlassen.
Für Stadtwerk-APIs bedeutet das konkret:
- Interne Zählpunktnummern (MeLo/MaLo-IDs): Nie in API-Responses — stattdessen anonymisierte Referenzen
- SAP IS-U-Objekt-IDs: Keine Datenbank-Primärschlüssel in öffentlichen Responses
- Smart-Meter-Rohdaten: Granulare 15-Minuten-Verbrauchsdaten ausschließlich über gesicherte Kanäle
- Framework- und Systemversionen: Kein
Server: Express 4.18.2-Header, keine Versionsangaben in Fehlermeldungen - Stack Traces: Ausschließlich intern, nie an externe Aufrufer
- Mitarbeiterdaten: Keine Kundenbetreuer-IDs oder Dispatcher-Namen in API-Responses
Das klingt selbstverständlich. Ist es in der Praxis nicht. Automatisch generierte API-Dokumentation aus dem Code enthält oft interne Feldbezeichnungen. Logging-Systeme, die in Cloud-Dashboards landen, enthalten manchmal mehr als geplant. Und jede neue Funktion ist eine neue Gelegenheit für versehentliche Exposition.
Checkliste: Security-Mindeststandard für Stadtwerk-APIs
☐ Validierungsschema definiert für jeden Endpoint (Typen, Wertebereiche, Pflichtfelder)
☐ Rate Limiting konfiguriert — differenziert nach Endpoint-Klasse
☐ Error Responses sanitized — keine Stack Traces, keine ORM-Fehlercodes in Produktion
☐ HTTP Security Headers gesetzt (HSTS, X-Content-Type-Options, X-Frame-Options)
☐ Keine internen IDs (SAP-Objekte, DB-Primärschlüssel) in öffentlichen Responses
☐ API-Keys mit Scopes — minimale Berechtigung pro Integrator
☐ Logging ohne personenbezogene Daten (DSGVO-konform)
☐ Dokumentiertes Endpoint-Inventar — wer darf welchen Endpoint aufrufen
☐ BSI-Grundschutz Baustein APP.3.1 (Webanwendungen) adressiert
☐ Revoke-Mechanismus für kompromittierte API-Keys vorhanden
Diese Liste deckt nicht alle Anforderungen eines vollständigen BSI-Grundschutz-Audits ab. Aber sie deckt die Basis ab, die jede öffentlich erreichbare Stadtwerk-API haben muss — bevor irgendein Integrations-Partner angebunden wird.
Was ich für Sie entwickle
Ich baue API-Infrastruktur für Stadtwerke und Energieversorger, die regulatorische Anforderungen von Anfang an berücksichtigt — BSI-Grundschutz, NIS2-Richtlinie und DSGVO eingeschlossen.
Validierungsschicht — Schema-basierte Eingabe-Validierung für alle Endpoints, mit standardisierter Fehlerschematisierung und DSGVO-konformem Logging.
Rate-Limiting-Middleware — Differenzierte Limits nach Endpoint-Klasse und Integrator-Typ, inkl. Header-basierter Kommunikation für konforme API-Clients.
API-Key-Management — Scoped API-Keys pro B2B-Partner mit Revoke-Mechanismus und Audit-Log für BSI-konforme Nachvollziehbarkeit.
Error-Handling-Framework — Standardisierte Error-Codes mit sanitisierten Responses in Produktion und vollständigem internem Logging für Debugging.
Security-Review bestehender APIs — Analyse vorhandener Endpoints nach den fünf genannten Schichten, Priorisierung nach Risikolevel, Umsetzungsplan ohne Komplettumstieg.
Kein Relaunch der bestehenden Architektur erforderlich — diese Schichten lassen sich als Middleware in bestehende Node.js-, .NET- oder Java-Umgebungen integrieren.
Fazit
Stadtwerke öffnen ihre IT-Infrastruktur — aus nachvollziehbaren Gründen. § 14a EnWG, Smart-Meter-Rollout, B2B-Integrationen für Wärmepumpen und Ladesäulen: Die Digitalisierung der Energiewirtschaft erfordert offene, maschinenlesbare Schnittstellen.
Diese Offenheit hat einen Preis — wenn sie nicht von Anfang an mit Sicherheitsarchitektur geplant wird. Rate Limiting, Eingabe-Validierung, saubere Fehlerbehandlung und granulare Authentifizierung sind kein Overhead. Sie sind die Voraussetzung, damit externe Integrationen funktionieren, ohne zur Angriffsfläche für die Versorgungsinfrastruktur zu werden.
Die gute Nachricht: Keine dieser fünf Schichten erfordert einen Systemwechsel. Sie lassen sich schrittweise nachrüsten — auch in gewachsenen SAP-Umgebungen mit heterogenen API-Landschaften.
Wenn Sie wissen möchten, wo Ihre API-Infrastruktur heute steht und wo die größten Risiken liegen, sprechen Sie mich an. Ein strukturierter Security-Review dauert keine Wochen.


