API Security Best Practices: Teil 2 - Broken Object Property Level Authorization

Stellen Sie sich vor, Sie melden sich in einem Onlineshop an – und plötzlich haben Sie Administratorrechte. Unmöglich? Leider nicht. Manchmal reicht ein einziges zusätzliches Feld in einem API, um Unbefugten Zugang zu verschaffen. So kann eine kleine Änderung wie das Hinzufügen eines Rollenfelds zu einer großen Sicherheitslücke führen. Das Problem heißt in Fachkreisen Broken Object Property Level Authorization (BOPLA). Wir erklären Schritt für Schritt, was dahintersteckt und wie Sie sich dagegen schützen können.

Dieser Artikel ist zuerst im Java Magazin 4.2026 unter dem Titel „Registrier’ dir deinen Admin: Wenn ein neues Feld zur Sicherheitslücke wird“ erschienen.

Schauen wir uns ein Webshop-API an, über das sich neue Benutzer registrieren können. Zu Beginn gibt es dort nur normale Nutzer ohne besondere Berechtigungen. Der entsprechende API-Aufruf sieht z. B. so aus wie in Listing 1.

POST /api/users Content-Type: application/json { „username“: „neuerUser“, „password“: „geheim“ }


Die Spring-Boot-Implementierung ist simpel: Der Controller nimmt Benutzername und Passwort entgegen und legt einen neuen User in der Datenbank an. Wichtig dabei: In der ersten Version hat die Klasse User nur id, username und password als Felder (kein Rollenfeld). Der Code könnte etwa so aussehen wie in Listing 2 gezeigt.

@Entity(name = „users“) public class User { @Id public Long id; @Column public String username; @Column public String password; } @PostMapping(“/api/users”) public ResponseEntity<User> createUser(@RequestBody User user) { // unsicher, kein Schutz gegen Überschreiben. user.setPassword(passwordEncoder.encode(user.getPassword())); userRepository.save(user); return ResponseEntity.status(CREATED).body(user); }


Hier bekommt jeder neue Benutzer implizit die Standardrolle (z.B. USER), weil es gar keine anderen gibt. Ein Beispiel für ein Registrierungsformular auf der Website des Webshops zeigt Abbildung 1.


Figure 1: Abb. 1: Registrierungsformular auf der zugehörigen Website

Nun kommt ein Featurewunsch: Man will zwischen Kunden und Administratoren unterscheiden, also Benutzerrollen einführen. Der schnellste Weg: Die bestehende User-Klasse um ein Feld role erweitern. Der Entwickler passt also den Code minimal an: Die Datenklasse User erhält ein neues Feld role. Den entsprechenden Diff zeigt Listing 3.

@Entity(name = „users“) public class User { @Id public Long id; @Column public String username; @Column public String password; - // bisher kein Rollenfeld (alle Nutzer waren “USER”) + @Column + public String role = „USER“; // Benutzerrolle (z. B. “USER”/”ADMIN”) }


Auf den ersten Blick scheint das zu funktionieren: Das Registrierungsformular auf der Website bleibt, wie es ist. Nur im Backend kann die Anwendung jetzt zwischen „Kunde“ und „Administrator“ unterscheiden. Doch was wurde übersehen? Durch diese Änderung kann jetzt jeder, der den API-Aufruf kennt, versuchen, sich mit einer beliebigen Rolle zu registrieren.

Exploit: Registrierung eines Admins

Angreiferin Mallory wittert ihre Chance. Sie schickt direkt einen API Request und gibt dabei manuell die Rolle ADMIN mit (Listing 4).

POST /api/users Content-Type: application/json { “username”: “mallory”, “password”: “123456”, “role”: “ADMIN” }


Was passiert? Unsere Anwendung übernimmt arglos alle Felder und legt in der Datenbank einen Benutzer mallory mit Passwort 123456 und der Rolle ADMIN an. Es findet keine Prüfung statt, ob der Aufrufer das darf. Das Backend vertraut blind dem Request. Mallory kann sich nun einloggen und hat volle Adminrechte.

Das ist ein klassischer Fall von Mass Assignment: Die Anwendung bindet Request-Daten automatisch an interne Objekte, ohne sicherheitskritische Felder auszuschließen. Angreifer können so versteckte oder eigentlich schreibgeschützte Properties setzen, die vom Client nicht kommen dürften, in unserem Fall die Adminrolle. Aus einem harmlosen Featurewunsch ist eine gravierende Sicherheitslücke geworden: vertikale Rechteausweitung (ein normaler Nutzer verschafft sich Adminrechte). Kein Wunder, dass BOPLA auf Platz 3 in den OWASP API Security Top 10 auftaucht (Abb. 2).


Figure 2: Abb. 2: BOPLA-Risiko in Zahlen – ein zusätzliches Feld, ein kompletter Rechteverlust

Warum fällt das nicht sofort auf?

Solche Lücken entstehen oft aus Bequemlichkeit oder aufgrund falscher Annahmen. Der Entwickler dachte vielleicht: „Unsere eigene Frontend-App wird keine Adminregistrierung schicken.“ Das mag stimmen. Aber kann man garantieren, dass nur die eigene App das API aufruft? Nein. Sobald ein API öffentlich ist, kann jeder darauf zugreifen. Mobile-App, Web-Frontend, Drittsysteme … Alles, was der URL kennt, kann Requests schicken. Im Idealfall ist das API geschützt (Authentifizierung), aber in unserem Fall soll die Registrierung ja offen und auf der Website möglich sein. Ein Angreifer kann sich die Netzwerkaufrufe der offiziellen App anschauen (z. B. via Browser-DevTools oder Mobile- Proxy) und dann mit eigenen Tools (Postman, cURL) die gleiche Anfrage mit manipulierten Daten senden. Wir haben keinerlei Kontrolle darüber, wer unsere HTTP-Schnittstelle anspricht. Das ist der fundamentale Unterschied zwischen internem Methodenaufruf und öffentlichem API.

Auch automatisierte Scanner entdecken so etwas nicht unbedingt, denn formal ist es kein Fehler: Das API erlaubt ja das Feld role (absichtlich oder unabsichtlich). Erst gezielte Abuse-Tests oder Sicherheitsreviews decken auf, dass sich hier jeder zum Admin befördern kann.

Frameworks wie Spring machen das Data Binding sehr bequem: Man kann direkt ein Domainobjekt als @RequestBody nutzen. Doch genau das ist das Problem: Ohne zusätzliche Vorkehrungen übernimmt Spring alle Felder aus dem JSON ins Objekt. Was nicht ausdrücklich ignoriert oder validiert wird, landet ungehindert dort. Solange die Klasse User kein role hatte, war alles gut, doch jetzt haben wir uns damit eine Hintertür eingebaut.

Gegenmaßnahmen: Mass Assignment verhindern

Wie schützt man sich davor? Die wichtigste Regel lautet: „Niemals blind den Request-Daten trauen!“ Konkret gibt es mehrere Ansätze, um Mass Assignment zu verhindern. Am besten kombiniert man mehrere derjenigen, die wir im Folgenden beschreiben.

Schichtentrennung mit DTOs (Data Transfer Objects)

Verwenden Sie für den Request ein gesondertes DTO, anstatt direkt die JPA-Entität User zu befüllen, z. B. UserRegistrationDto nur mit username und password, ohne role-Feld darin. Der Controller mappt dieses DTO dann ins Datenbankmodell und vergibt dabei die Rolle serverseitig. Weil das DTO gar keinen role- Parameter erlaubt, kann ein Angreifer auch keinen einschleusen. Dieses Vorgehen – also explizit zu bestimmen, welche Felder übernommen werden – ist die sicherste Gegenmaßnahme gegen Mass Assignment. In vielen Webframeworks gehört Feld-Whitelisting zum Standard; in Spring/Java ist es am einfachsten, mittels gezielter Konfiguration (@JsonIgnore bei JSON-APIs, WebDataBinder bei Formularen) oder DTOs sicherzustellen, dass unerwünschte Felder ignoriert werden. Die Implementierung könnte so aussehen wie in Listing 5 oder Listing 6.

@Entity(name = “users”) public class User { ... public String password; + @JsonIgnore @Column public String role = “USER”; }


@PostMapping(“/api/users”) public ResponseEntity<?> registerSecure(@Valid @RequestBody UserRegistrationDto req) { // req enthält nur username und password User newUser = new User(); newUser.setUsername(req.getUsername()); newUser.setPassword(passwordEncoder.encode(req.getPassword())); newUser.setRole(„USER“); // Rolle hart vergeben userRepository.save(newUser); // Response vorbereiten (Passwort nie zurückgeben) UserResponseDto resp = new UserResponseDto(newUser.getUsername(), newUser.getRole()); return ResponseEntity.status(HttpStatus.CREATED).body(resp); }


Hier wird das Passwort gehasht gespeichert, und die Rolle ignoriert jegliche Eingabe (immer auf USER gesetzt). Die Response enthält ebenfalls nur ausgewählte Felder (kein Passworthash). Dadurch ist es egal, was der Client schickt. Die Rolle Admin wird niemand außer uns selbst vergeben.

Eingaben validieren und bereinigen

Ergänzend sollte jede Eingabe validiert werden. Bean Validation (z.B. mit @NotBlank, @Size usw.) stellt sicher, dass Felder wie username und password sinnvolle Werte enthalten. Wenn man dem Client erlaubt, ein Rollenfeld mitzugeben (z.B. zur Unterscheidung zwischen USER und SELLER), muss die Validierung sicherstellen, dass nur erlaubte Rollenwerte akzeptiert werden. Ein Wert wie ADMIN sollte in diesem Fall explizit abgelehnt oder ignoriert werden.

In Spring Boot werden unbekannte Felder im JSONRequest standardmäßig nicht übernommen, allerdings auch nicht beanstandet. Das liegt daran, dass die Einstellung FAIL_ON_UNKNOWN_PROPERTIES im verwendeten ObjectMapper per Default auf false steht. Um unbekannte Felder dennoch zu übernehmen (was in sicherheitskritischen Kontexten nicht empfohlen wird), müsste z.B. @JsonAnySetter verwendet werden.

Einige JavaScript-Frameworks wie Express in Kombination mit celebrate/Joi bieten ebenfalls Möglichkeiten zur Feldkontrolle. Dort kann man mit der Option stripUnknown (standardmäßig false) festlegen, dass unbekannte Felder automatisch entfernt werden. Ein manipuliertes Feld wie role: „ADMIN“ würde so gar nicht im verarbeiteten Objekt auftauchen.

Achtung: Das stillschweigende Entfernen unbekannter Felder hat Vor- und Nachteile. Zwar wird ein potenzieller Angriff dadurch neutralisiert, doch bleibt er möglicherweise unbemerkt. In sicherheitskritischen Anwendungen ist es daher oft sinnvoller, solche Felder mit einem Fehler zu quittieren oder zumindest zu protokollieren, um potenzielle Missbrauchsversuche nachvollziehen zu können.

Privilegierte Aktionen trennen

Überlegen Sie beim Design, ob ein normaler Registrierungs- Endpoint überhaupt Admins oder andere privilegierte Nutzer anlegen können muss. Eigentlich muss er das nicht. Die Vergabe von Adminrechten gehört in einen eigenen, geschützten Endpoint (z.B. /api/admin/users für eine Admin-User-Anlage oder eine Rollenänderung). Selbst wenn der Standard-Endpoint manipulierbar wäre, hätte ein gesendetes role-Feld dort keine Wirkung, weil es ignoriert würde. Dieses Prinzip der getrennten Pfade reduziert die Angriffsfläche enorm. Zusätzlich kann man solche Admin-Pfade gezielt absichern – etwa im Gateway nur für interne Aufrufe freigeben (z.B. externe Zugriffe auf /api/admin/* blockieren). So ist sichergestellt, dass ein externer Angreifer diese Funktionen gar nicht nutzen kann, selbst wenn er authentifiziert ist. Eine einfache, aber sehr effektive Maßnahme.

Tests und Codereviews

Änderungen an sicherheitsrelevanten Features sollten streng geprüft werden. Hier hätte ein einfacher Negativtest den Fehler gezeigt: der Versuch, einen Nutzer mit role: „ADMIN“ zu registrieren, und erwarten, dass das nicht funktioniert. Solche Tests gehören in die Testsuite, insbesondere wenn man weiß, dass gefährliche Felder im Spiel sind. Ebenso lohnt sich eine Codereview mit dem „Was wäre, wenn“-Blick. Ein Kollege hätte die Frage stellen können: „Kann jemand dieses neue Feld missbrauchen?“ Security-Scans (SAST/DAST) finden Mass Assignment leider nicht immer zuverlässig, aber manche Tools (z.B. CodeQL oder Fortify) haben Patterns, die Alarm schlagen, wenn ein Request-Objekt unkontrolliert in die Persistenzschicht fließt.

Responses abspecken

BOPLA betrifft auch die ungewollte Datenausgabe (Excessive Data Exposure). Achten Sie darauf, nur benötigte Felder zurückzugeben. In unserem Beispiel senden wir in der Response nur Username und Rolle – nicht etwa den Passworthash. Allgemeiner: Wenn z.B. GET /api/users/{id} implementiert wird, sollte ein normaler Nutzer darüber niemals vertrauliche Felder anderer sehen (z.B. isAdmin, creditCard, permissions etc.). Solche sensiblen Properties gehören entweder gar nicht in die Response oder müssen serverseitig gefiltert werden (z.B. mit @JsonIgnore oder gezielten DTOs für die Ausgabe).

Das Prinzip: Alles, was ein Client nicht unbedingt wissen muss, sollte er gar nicht erst zu Gesicht bekommen. So schließt man auch diese Hälfte der BOPLA-Problematik.

Früherkennung: OpenAPI-Spezifikation und Spectral

Nehmen wir an, der Entwickler übersieht die Sicherheitsproblematik beim Coding. Wie hätte man die Lücke vor dem Deployment bemerken können? Ein Schlüssel dazu ist die API-Dokumentation. Professionelle APIs haben eine OpenAPI-Spezifikation, die beschreibt, welche Felder ein Request haben darf (OpenAPI ist der Nachfolger von Swagger).

Fügen wir beispielsweise die Abhängigkeit org. springdoc:springdoc-openapi-starter-webmvc-ui:2.8.14 zu unserem Spring-Boot-Projekt hinzu und rufen /v3/api-docs ab, so erhalten wir bereits eine OpenAPI-Definition unserer Schnittstelle. In unserem ursprünglichen Zustand sieht sie etwa so aus wie in Listing 7.

openapi: 3.1.0 info: title: Webshop Demo API paths: /users: post: requestBody: content: application/json: schema: $ref: ‘#/components/schemas/User’ required: true responses: ‘200’: description: OK content: ‘*/*’: schema: $ref: ‘#/components/schemas/User’ components: schemas: User: type: object properties: id: { type: integer, format: int64 } username: { type: string } password: { type: string }


Hier sind nur id, username und password als erlaubte Felder definiert. Doch ein entscheidendes Detail fehlt: Die Eigenschaft additionalProperties ist nicht gesetzt. Das bedeutet, dass das API standardmäßig auch zusätzliche, nicht definierte Felder akzeptiert: ein potenzielles Einfallstor für Mass Assignment.

Die Einstellung additionalProperties: false bedeutet, dass keine weiteren Felder zugelassen sind. Eine extrem wichtige Sicherheitsvorgabe. Wir passen daher die OpenAPI-Beschreibung an (Listing 8).

... type: object properties: id: { type: integer, format: int64 } username: { type: string } password: { type: string } + additionalProperties: false


Diese Änderung setzen wir selbstredend nicht manuell um, da das OpenAPI-Dokument generiert wurde. Stattdessen nutzen wir die Annotation io.swagger.v3.oas.annotations.media.Schema an der User-Klasse:

@Entity(name = “users”) + @Schema(additionalProperties = FALSE) public class User { ...


Was passiert nun, nachdem der Entwickler das role-Feld in der User-Klasse, wie in Listing 3 gezeigt wurde, hinzugefügt hat? Das generierte OpenAPI ändert sich (Listing 9).

... properties: username: { type: string } password: { type: string } + role: { type: string } # <- neues Feld additionalProperties: false # bleibt auf false


Jetzt ist für jeden sichtbar (zumindest intern im Team): Im Registrierungs-Request gibt es plötzlich ein Feld role. Ein Security-Architekt würde sofort fragen, warum eine normale Registrierung eine Rolle akzeptieren soll. Diese Transparenz ist der erste Vorteil einer sauberen Spezifikation. Aber auch ohne menschlichen Blick kann man hier ansetzen: Mit Tools wie Spectral (ein OpenAPI Linter, siehe [4]) lässt sich die Einhaltung von API-Guidelines automatisiert prüfen.

Ein bewährtes Pattern ist, jede Objektdefinition in der Spec mit additionalProperties: false zu versehen (wie oben). Spectral kann so konfiguriert werden (bzw. es gibt vordefinierte OWASP-Regeln dafür), dass es einen Fehler wirft, wenn in einem Schema additionalProperties fehlt oder auf true steht. Damit wird sichergestellt, dass Entwickler alle erlaubten Felder explizit definieren. In unserem Beispiel wäre das bereits erfüllt gewesen, die Spec war streng. Hätte der Entwickler jedoch versäumt, die Spec zu aktualisieren, wäre die Diskrepanz offensichtlich:

  • API-Code akzeptiert ein Feld role.
  • Spec erlaubt nicht, dass ein solches Feld gesendet wird (additionalProperties: false ohne Nennung von role).
Ein API Gateway mit Schemavalidierung (dazu gleich mehr) würde solche Requests blockieren. Aber schon beim Entwickeln hätte Spectral gemahnt, falls jemand auf die Idee käme, additionalProperties: true zu setzen (um bequem alle Felder zuzulassen). So ein Linter erzwingt also die Striktheit der Schnittstelle. Er kann nicht direkt „erraten“, dass role ein gefährliches Feld ist. Er stellt aber sicher, dass jede Abweichung bewusst geschehen muss. Das neue role-Property taucht im Diff unübersehbar auf und kann diskutiert werden, bevor es live geht.

GitOps für API-Spezifikationen (APIOps)

Wie integriert man diese Ideen in den Entwicklungsprozess? Hier kommt APIOps ins Spiel. APIOps ist ein Ansatz analog zu GitOps, bei dem sowohl Code als auch API-Dokumentation und Gateway-Konfiguration in Git versioniert werden. In der Praxis könnte das so aussehen:

  • Repo A (Code unseres Spring-Boot-Projekts): Der Entwickler ändert den Code und damit die generierte OpenAPI-Spezifikation (fügt role hinzu). Es wird ein Pull Request erstellt. In der CI-Pipeline läuft Spectral über die Spec und stellt sicher, dass Regeln eingehalten werden (z.B. additionalProperties: false). Ist alles grün, wird gemergt.
  • Repo B (Gateway-Konfiguration): Das API Gateway (z. B. Membrane oder Kong) hat seine eigene Konfigurationsbasis. Hier liegt ebenfalls die OpenAPIDatei, auf die das Gateway die Requests validiert. Ein automatischer Prozess erkennt die geänderte Spec aus Repo A und erstellt einen Pull Request auf Repo B, um die neue Spec ins Gateway einzuspielen.
  • Review und Deploy: Bevor dieser PR gemerged wird, schaut idealerweise ein Security- oder DevOps Engineer drüber, ggf. im Vier-Augen-Prinzip. Dabei fällt z.B. auf: „Oh, da kommt ein role-Feld in der Registrierung hinzu! Ist das gewollt?“ Im besten Fall wird gefragt, ob Missbrauch möglich ist, und der PR wird gestoppt, bis geklärt ist, dass die Implementierung sicher ist. Erst nach Freigabe geht die Änderung live und das Gateway akzeptiert das neue Feld.

Figure 3: Abb. 3: APIOps in unserem Beispiel

Dieser Prozess klingt aufwendig, ist aber für sicherheitskritische APIs extrem empfehlenswert. Er stellt sicher, dass Security-Themen nicht unter den Tisch fallen, sondern früh im Lifecycle diskutiert werden.

Validierung im API Gateway

Ein großer Vorteil, wenn man die OpenAPI-Spezifikation so ernst nimmt: Man kann sie zur Laufzeit nutzen. Viele API Gateways können eingehende Anfragen strikt gegen die Spec prüfen. Das heißt, das Gateway lässt nur durch, was im Vertrag steht. In unserem Beispiel hätte ein Gateway im ursprünglichen Zustand einen Request mit unbekanntem Feld role abgelehnt. Hätte der Entwickler die Spec zwar angepasst, aber niemand das Okay dafür gegeben, wäre der neue Spec-Stand gar nicht erst ins Gateway gekommen.

Um das greifbar zu machen, zeigt Listing 10 ein Beispiel dafür, wie eine solche Gateway-Konfiguration aussehen könnte.

<api port=“2000“> <!-- OpenAPI-Spezifikation einbinden --> <openapi location=”openapi.yaml” validateRequests=”true” validateResponses=”true” validateSecurity=”true” validationDetails=”true”/> <!-- Logging (optional) --> <accessLog/> <!-- Backend-Service definieren --> <target host=”localhost” port=”8080”/> </api>


In diesem Membrane-Beispiel wird eine OpenAPIDatei (openapi.yaml) geladen und gegen alle Requests und Responses geprüft. Ein unerwartetes Feld führt automatisch zu einer Fehlermeldung („validation failed: property ‚role‘ is not allowed“, o. Ä.). Ähnliches geht auch mit anderen Gateways, z. B. Kong via Plug-in.

Listing 11 zeigt einen Ausschnitt einer deklarativen Kong-Konfiguration (per decK). Das Request-Validator- Plug-in prüft hier den JSON-Body: Erlaubt sind nur username und password (sonst nichts). Ein Angreifer- Request mit role würde vom Gateway mit „400 Bad Request“ abgelehnt, noch bevor unsere Anwendung irgendetwas davon sieht.

_format_version: “2.1” services: - name: user-registration url: http://user-service:8080 routes: - name: register-route paths: [ /api/users ] methods: [ POST ] plugins: - name: request-validator config: body_schema: type: object properties: username: { type: string } password: { type: string } additionalProperties: false


Natürlich muss man den Mehraufwand solcher Maßnahmen berücksichtigen. Nicht jedes kleine interne API rechtfertigt eine vollautomatisierte APIOps-Pipeline oder strikte Gateway-Filter. Doch in Bereichen mit hohen Sicherheitsanforderungen (externe APIs, kritische Daten) sind diese Mechanismen Gold wert. Sie fungieren als mehrfach gestaffelte Schutzmaßnahmen: sichere Entwicklung, strenge Spezifikation, automatisierte Checks, Gatekeeper vor der Anwendung. Kommt es doch zu einer unerwarteten Änderung, fängt eine der Schichten das Problem ab.

Tabelle 1: Typische BOPLA-Anzeichen
AnzeichenBeschreibung/Risiko
fehlendes additionalProperties: false OpenAPI erlaubt zusätzliche Felder; Risiko: Angreifer können unerwartete Properties einschleusen (z.B. role)
direktes Binding von Domain-Objekten Request-Daten werden ohne DTO oder Feld-Whitelist an JPA-Entitäten gebunden; Risiko: Mass Assignment
generische Setter oder z.B. BeanUtils.copyProperties() kopiert alle Felder inkl. sensibler Properties; Risiko: Manipulation sicherheitskritischer Felder
PATCH-Endpunkte ohne Feldkontrolle Teilaktualisierungen akzeptieren beliebige JSON-Felder; Risiko: versteckte Payload
keine Validierung erlaubter Werte Rollen oder Statusfelder werden übernommen, ohne auf erlaubte Werte zu prüfen; Risiko: Rechteausweitung
fehlende Constraints in Datenbank oder ORM DB akzeptiert beliebige Werte für Rollen oder Status; Risiko: Umgehung von Codechecks
ungefilterte Response-Serialisierung Backend gibt komplette Objekte zurück; Risiko: sensitive Properties werden offengelegt
kein Logging bei unbekannten Feldernunerwartete Felder werden stillschweigend ignoriert; Risiko: Angriffe bleiben unbemerkt
unzureichende Tests für negative Szenarien Testsuite prüft nur den Happy Path; Risiko: Angriffe wie „role=ADMIN“ bleiben unentdeckt

Takeaways für Entwickler

Entwickler sollten vor allem folgende Punkte im Hinterkopf behalten:

  • Keine automatischen Bindings sensibler Felder: Nutzt DTOs oder Konfiguration, um zu steuern, welche JSON-Felder akzeptiert werden. Domain-Entitäten mit sicherheitsrelevanten Feldern sollten nie direkt vom Request befüllt werden.
  • Whitelist statt Blacklist: Übernehmt nur die Felder, die wirklich gebraucht werden. Alles andere ignorieren oder validiert ablehnen. Das ist einfacher, als hinterher bestimmte Felder verbieten zu müssen.
  • Serverseitige Defaults: Setzt wichtige Felder im Backend. Die Rolle etwa sollte bei Registrierung immer vom Server kommen (Standard = USER). So verpufft ein etwaiges role-Feld im Request wirkungslos.
  • Teste den Missbrauchsfall: Denkt an negative Tests: Was passiert, wenn jemand versucht, das System auszutricksen? Ein Test, der sicherstellt, dass role ignoriert wird, hätte unseren Bug verhindert.
  • Denke wie ein Angreifer: Frage dich bei Features immer: „Wie könnte man das missbrauchen?“ Diese Perspektive hilft, viele Probleme schon beim Entwickeln zu erkennen.

Takeaways für Architekten & Security-Teams

Für Architekten und Security-Teams sind vor allem folgende Punkte von Bedeutung:

  • „Contract first“ denken: Sorgt dafür, dass zu euren APIs aktuelle OpenAPI-Spezifikationen vorliegen. Nutzt diese als Sicherheitsnetz: Was nicht in der Spec steht, sollte auch nicht akzeptiert werden.
  • Linting und Policies: Setzt Linter wie Spectral ein, um Standards durchzusetzen. Beispielsweise sollte immer additionalProperties: false gesetzt sein, außer es ist explizit nötig. Solche Policies zwingen Entwickler, ihr API bewusst zu gestalten, und verhindern „schlampige“ Öffnungen.
  • API Gateway als Schutzwall: Nutzt die Fähigkeit moderner Gateways, Requests und Responses gegen die Spec zu validieren. Gerade bei öffentlich zugänglichen APIs lohnt es sich, streng zu sein. Ein Gateway mit Schemavalidation fängt viele Fehler oder Angriffe ab, bevor sie Schaden anrichten.
  • GitOps/Review-Prozesse für APIs. Überlegt, API-Änderungen genau wie Code durch PRs und Reviews laufen zu lassen (APIOps). Eine zweite Instanz (z. B. ein DevSecOps Engineer) sollte ein Auge auf Änderungen wie neue Felder, Endpunkte oder Berechtigungsanforderungen haben. Das Vier-Augen-Prinzip reduziert die Gefahr, dass jemand versehentlich eine Lücke einbaut.
  • Schulung und Kultur. Sensibilisiert eure Entwickler für Themen wie Mass Assignment und Datenexposition. Wer die OWASP API Top 10 verinnerlicht hat, baut automatisch vorsichtiger. Sicherheitsreviews sollten nicht als lästige Pflicht, sondern als Qualitätsmerkmal gesehen werden. Das muss die Teamkultur reflektieren.

Fazit

Das „Registrier’ dir deinen Admin“-Szenario zeigt eindrücklich, wie aus einer kleinen Codeänderung eine gravierende Sicherheitslücke werden kann. Broken Object Property Level Authorization mag ein Zungenbrecher sein, doch dahinter stecken bekannte Probleme (Mass Assignment, Excessive Data Exposure), die vermeidbar sind. Mit sauberer Trennung von Schichten, strikten Schemas und mehrstufigen Prüfungen lässt sich diese Gefahr bannen. Entwickler sollten Eingaben niemals blind vertrauen, sondern immer nur genau das verarbeiten, was erlaubt ist. Architekten und Sicherheitsingenieure sollten darauf achten, dass APIs einen klaren Vertrag haben und dass Abweichungen davon auffallen, sei es durch Tools oder Prozesse.

Der Spoiler aus der Einleitung bewahrheitet sich also: „Registrier’ dir deinen Admin“ darf kein legitimes Feature sein. Mit den richtigen Maßnahmen stellen wir sicher, dass Adminrechte da bleiben, wo sie hingehören, und nicht versehentlich über die Benutzerregistrierung verteilt werden.

Von: Tobias Polley
Datum: 14. Juni 2026

API Gateway eBook

Erfahre im kostenlosen eBook wie du mit OAuth2, API-Keys, JWT und einem Gateway APIs schützen kannst.

API Gateway eBook Cover
Training

Lerne von unseren Autoren in der API Security Schulung.

Online Training
12. - 13. 10.2026
Jetzt anmelden
für 1.340,- €*

Schulungen in Bonn
Jetzt anmelden
für 1.470,- €*