Web Security für Entwickler: OWASP Top 10, XSS, CSRF und SQL-Injection
Web Security für Entwickler: die OWASP Top 10:2025 erklärt, XSS, CSRF und SQL-Injection mit Code verhindern, Security-Header, Passwörter und Prüfwerkzeuge.
Thema: Web-Entwicklung
Inhalt (11 Abschnitte)
Web Security heißt, eine Web-Anwendung gegen die bekannten Angriffsarten abzusichern. Den Maßstab setzt die OWASP Top 10:2025, angeführt von fehlerhafter Zugriffskontrolle. Die wichtigsten Abwehrmaßnahmen sind Berechtigungsprüfungen auf dem Server, parametrisierte Datenbankabfragen gegen SQL-Injection, kontextgerechte Ausgabe gegen XSS, CSRF-Schutz des Frameworks, sichere Header und aktuelle Abhängigkeiten.
Stand: 13. Oktober 2026. Alle Angaben stammen aus der OWASP Top 10:2025, den OWASP Cheat Sheets, RFC 9116 und den Dokumentationen der genannten Werkzeuge, abgerufen an diesem Tag. Die Quellen stehen am Ende.
Die OWASP Top 10:2025 im Überblick
Das Projekt OWASP veröffentlicht die bekannteste Liste der kritischsten Risiken für Web-Anwendungen. Die aktuelle Ausgabe trägt die Jahreszahl 2025:
| Rang | Kategorie | Was dahintersteckt |
|---|---|---|
| A01 | Broken Access Control | Nutzer kommen an Daten oder Funktionen, die ihnen nicht zustehen; dazu zählen auch CSRF und SSRF |
| A02 | Security Misconfiguration | unsichere Voreinstellungen, offene Debug-Ausgaben, fehlende Header |
| A03 | Software Supply Chain Failures | verwundbare oder manipulierte Abhängigkeiten und Build-Werkzeuge |
| A04 | Cryptographic Failures | fehlende oder schwache Verschlüsselung, falsch gespeicherte Passwörter |
| A05 | Injection | SQL-, NoSQL-, Befehls-Injection und Cross-Site Scripting |
| A06 | Insecure Design | Sicherheitslücken, die schon im Entwurf stecken |
| A07 | Authentication Failures | schwache Anmeldung, Sitzungsfehler |
| A08 | Software or Data Integrity Failures | ungeprüfte Updates, Daten oder Code aus nicht vertrauenswürdigen Quellen |
| A09 | Security Logging and Alerting Failures | Angriffe bleiben unbemerkt, weil nichts protokolliert oder gemeldet wird |
| A10 | Mishandling of Exceptional Conditions | Fehler und Ausnahmezustände werden unsicher behandelt |
Zwei Zahlen aus der Liste zeigen, wo es am häufigsten hakt: Bei Broken Access Control fand OWASP in 100 Prozent der getesteten Anwendungen irgendeine Form des Problems. Injection wurde ebenfalls an 100 Prozent der Anwendungen getestet und hat die meisten gemeldeten Schwachstellen (CVEs); zu Cross-Site Scripting (CWE-79) gibt es laut OWASP mehr als 30.000, zu SQL-Injection mehr als 14.000.
Die folgenden Abschnitte gehen die Punkte durch, die in kleinen und mittleren Web-Apps den größten Unterschied machen.
Zugriffskontrolle: jede Anfrage prüfen
Die häufigste Lücke ist eine fehlende Prüfung, ob der angemeldete Nutzer genau dieses Objekt sehen oder ändern darf. Typisch ist eine Adresse wie /api/rechnungen/1234, bei der die Anwendung nur prüft, ob jemand angemeldet ist, nicht aber, ob die Rechnung ihm gehört. Wer die Zahl ändert, sieht fremde Rechnungen.
Die Abwehr ist eine Prüfung auf dem Server bei jeder Anfrage, am besten direkt in der Datenbankabfrage:
// Unsicher: liefert jede Rechnung, deren ID jemand errät
const { rows } = await pool.query('SELECT * FROM rechnungen WHERE id = $1', [req.params.id]);
// Besser: nur Rechnungen des angemeldeten Kunden
const { rows } = await pool.query(
'SELECT * FROM rechnungen WHERE id = $1 AND kunde_id = $2',
[req.params.id, req.user.kundeId]
);
if (rows.length === 0) return res.status(404).end();
Prüfungen im Frontend, etwa ausgeblendete Knöpfe, sind kein Schutz; wie Fehler und Rechte in einer Schnittstelle sauber zurückkommen, zeigt REST API Design. OWASP schreibt dazu, dass Zugriffskontrolle nur in vertrauenswürdigem Code auf dem Server wirkt, wo ein Angreifer die Prüfung nicht verändern kann. Fertige Backends mit eingebauter Anmeldung vergleicht der Überblick Supabase-Alternativen.
SQL-Injection verhindern
Bei SQL-Injection landen Eingaben als Teil des SQL-Befehls in der Datenbank. OWASP beschreibt das Muster so: Feindliche Daten werden direkt verwendet oder an Abfragen angehängt, sodass Befehl und Daten vermischt werden. Das Beispiel aus der Top 10 zeigt, wie eine Eingabe wie ' OR custID IS NOT NULL OR custID=' einen Filter aushebelt und alle Konten zurückgibt.
Die erste Abwehrmaßnahme im OWASP Cheat Sheet zu SQL-Injection sind Prepared Statements mit parametrisierten Abfragen. Mit node-postgres sieht das so aus:
// Unsicher: Eingabe wird Teil des SQL-Textes
await pool.query(`SELECT * FROM users WHERE email = '${email}'`);
// Sicher: Eingabe geht getrennt als Parameter an die Datenbank
await pool.query('SELECT * FROM users WHERE email = $1', [email]);
Zwei Grenzen nennen die Quellen ausdrücklich. Erstens lassen sich Tabellen- und Spaltennamen nicht als Parameter übergeben und auch nicht escapen; PostgreSQL unterstützt Parameter für Bezeichner nicht. Solche Namen gehören deshalb gegen eine feste Liste erlaubter Werte geprüft. Zweitens schützen gespeicherte Prozeduren nicht automatisch, wenn sie intern wieder Text zu Abfragen zusammensetzen.
Cross-Site Scripting (XSS) verhindern
Bei XSS schleust ein Angreifer Skriptcode in eine Seite, der dann im Browser anderer Nutzer läuft. OWASP ordnet XSS in der Ausgabe 2025 der Kategorie Injection zu.
Das XSS Cheat Sheet hält fest, dass Anwendungen mit modernen Frameworks weniger XSS-Fehler haben, weil Templates Ausgaben automatisch escapen. Gefährlich wird es an den Stellen, an denen Entwickler diesen Schutz umgehen, zum Beispiel:
dangerouslySetInnerHTMLin React ohne Bereinigung des HTML,bypassSecurityTrustAs*in Angular,unsafeHTMLin Lit,- direkte Zugriffe auf das DOM wie
innerHTML.
Für Text im Browser empfiehlt das Cheat Sheet textContent statt innerHTML. Muss wirklich HTML aus einer unsicheren Quelle angezeigt werden, empfiehlt OWASP die Bibliothek DOMPurify, die regelmäßig aktualisiert werden muss:
// Unsicher: HTML aus der Eingabe wird ausgeführt
element.innerHTML = kommentar;
// Sicher für reinen Text
element.textContent = kommentar;
// Wenn HTML nötig ist: vorher bereinigen
element.innerHTML = DOMPurify.sanitize(kommentar);
Eine Content Security Policy, die Inline-JavaScript abschaltet, ist eine zweite Verteidigungslinie. Sie ersetzt die korrekte Ausgabe nicht.
Cross-Site Request Forgery (CSRF) verhindern
Bei CSRF bringt eine fremde Seite den Browser eines angemeldeten Nutzers dazu, eine Aktion in deiner Anwendung auszulösen, etwa eine Überweisung oder eine Passwortänderung. Das funktioniert, weil der Browser Cookies einschließlich Sitzungscookie automatisch mitschickt. OWASP führt CSRF in der Top 10:2025 unter Broken Access Control.
Das CSRF Cheat Sheet gibt eine klare Reihenfolge vor:
- Prüfen, ob das Framework einen eingebauten CSRF-Schutz hat, und ihn benutzen.
- Falls nicht: CSRF-Tokens an alle Anfragen hängen, die etwas verändern, und sie auf dem Server prüfen.
- Zusätzlich das Cookie-Attribut
SameSitesetzen.
Set-Cookie: session=…; Secure; HttpOnly; SameSite=Lax
SameSite=Lax beschreibt das Cheat Sheet als vernünftigen Ausgleich zwischen Sicherheit und Bedienbarkeit, weil die Sitzung beim Aufruf über einen externen Link erhalten bleibt. Es zählt SameSite aber zu den ergänzenden Maßnahmen, nicht zum alleinigen Schutz. Wichtig ist außerdem ein Hinweis aus derselben Quelle: Eine XSS-Lücke kann jeden CSRF-Schutz aushebeln.
Security-Header setzen
Mehrere Risiken der Kategorie Security Misconfiguration lassen sich mit HTTP-Headern abschwächen. Das OWASP HTTP Headers Cheat Sheet empfiehlt unter anderem:
| Header | Empfohlener Wert | Wirkung |
|---|---|---|
Strict-Transport-Security | max-age=63072000; includeSubDomains; preload | Browser nutzen nur noch HTTPS |
X-Content-Type-Options | nosniff | Browser raten den Dateityp nicht |
Referrer-Policy | strict-origin-when-cross-origin | fremde Seiten sehen nur die Herkunft, nicht den Pfad |
Content-Security-Policy | mit frame-ancestors, ohne Inline-Skripte | schränkt Skriptquellen ein, verhindert Einbetten in fremde Frames |
X-XSS-Protection | nicht setzen oder ausschalten | kann laut OWASP in manchen Fällen selbst XSS-Lücken erzeugen; CSP ist der Ersatz |
Zu HSTS warnt das Cheat Sheet: Bei falscher Konfiguration oder einem Zertifikatsproblem können legitime Nutzer die Seite nicht mehr erreichen. Eine Content Security Policy ist laut OWASP aufwendig einzurichten und zu pflegen; dafür gibt es ein eigenes Cheat Sheet.
Passwörter richtig speichern
Passwörter gehören nie im Klartext oder mit einem schnellen Hash wie SHA-256 in die Datenbank. Das OWASP Password Storage Cheat Sheet nennt konkrete Mindestwerte:
| Verfahren | Mindestkonfiguration laut OWASP |
|---|---|
| Argon2id (erste Wahl) | 19 MiB Speicher, 2 Iterationen, Parallelität 1 |
| scrypt (falls Argon2id fehlt) | Kostenparameter 2^17, Blockgröße 8, Parallelität 1 |
| PBKDF2 (wenn FIPS-140 verlangt ist) | 600.000 Iterationen mit HMAC-SHA-256 |
| bcrypt (nur bestehende Systeme ohne Argon2id und scrypt) | Work Factor mindestens 10, Passwörter höchstens 72 Byte |
Die meisten Frameworks und Auth-Bibliotheken bringen eines dieser Verfahren mit. Wer Anmeldung selbst implementiert, sollte die Werte gegen diese Tabelle prüfen.
Abhängigkeiten und Lieferkette
Software Supply Chain Failures steht 2025 auf Rang 3. Für JavaScript-Projekte ist npm audit der erste Schritt: Der Befehl schickt laut Dokumentation eine Beschreibung der Abhängigkeiten an die Registry und erhält einen Bericht über bekannte Schwachstellen.
npm audit
npm audit fix
npm audit fix spielt verfügbare Korrekturen ein. Nicht alles lässt sich automatisch beheben; manche Lücken brauchen ein Update von Hand oder die Option --force, die laut Dokumentation auch Updates auf eine neue Hauptversion (SemVer-major) einspielt. Deshalb --force nie blind ausführen, sondern die betroffenen Pakete einzeln anheben und testen.
Updates automatisieren: Dependabot und Renovate
Sicherheitslücken in Abhängigkeiten werden meist durch liegengebliebene Updates gefährlich: Wer einmal im Jahr alles auf einmal anhebt, bekommt viele Änderungen gleichzeitig und weiß bei einem Fehler nicht, welche schuld ist. Kleine, regelmäßige Updates halten jede Änderung einzeln prüfbar. Zwei Bots öffnen dafür automatisch Pull Requests:
| Werkzeug | Plattformen | Einrichtung |
|---|---|---|
| Dependabot | GitHub | Datei .github/dependabot.yml mit Paket-Ökosystem und Intervall; mehrere Pakete lassen sich per groups in einem Pull Request bündeln |
| Renovate | GitHub, GitLab, Bitbucket, Azure DevOps und weitere | als App oder selbst betrieben; Gruppierung, Zeitfenster und Automerge per Regel, Übersicht im Dependency Dashboard |
Drei Regeln halten die Zahl der Pull Requests klein: zusammengehörige Pakete gruppieren (etwa alle @types/*), einen festen Termin pro Woche setzen und Sicherheitsupdates davon ausnehmen, Automerge nur für Patch-Updates von Entwicklungs-Abhängigkeiten mit grünen Tests. Die Lockdatei (package-lock.json, pnpm-lock.yaml) gehört ins Repository, sonst laufen auf dem Server andere Versionen als lokal. Und eine Versionsnummer ist kein Beweis: Nach Semantic Versioning darf sich bei Paketen mit Hauptversion 0 jede neue Version inkompatibel verhalten, und auch ein Patch kann Verhalten ändern, auf das dein Code baut. Die eigentliche Absicherung sind deine Tests, siehe Testing-Strategie für kleine Teams.
Sicherheit prüfen und Meldungen ermöglichen
Drei Werkzeuge und Quellen helfen beim Prüfen und Lernen:
- ZAP (Zed Attack Proxy, früher OWASP ZAP): quelloffener Scanner für Web-Anwendungen, laut Projektseite der weltweit meistgenutzte. Er findet von außen sichtbare Probleme, ersetzt aber keine Prüfung des Codes.
- Web Security Academy: kostenloses Online-Training von PortSwigger, den Machern von Burp Suite, mit interaktiven Übungslaboren.
- OWASP Web Security Testing Guide: Anleitung für Sicherheitstests an Web-Anwendungen, gedacht für Entwickler und Sicherheitsfachleute.
Zum Schluss eine kleine Datei mit großer Wirkung: security.txt nach RFC 9116. Sie liegt unter /.well-known/security.txt und sagt Sicherheitsforschern, wie sie Lücken melden können. Pflicht sind die Felder Contact und Expires; das Ablaufdatum soll laut RFC weniger als ein Jahr in der Zukunft liegen.
Contact: mailto:security@example.com
Expires: 2027-06-30T00:00:00.000Z
Preferred-Languages: de, en
Für die Kategorie A09 gilt: Angriffe, die niemand bemerkt, kann auch niemand abwehren. Wie du Fehler und Ausfälle rechtzeitig mitbekommst, steht im Ratgeber Website Monitoring.
Quellen und Stand
Alle Angaben wurden am 13. Oktober 2026 geprüft an:
- OWASP Top 10:2025 mit den Seiten zu A01 Broken Access Control und A05 Injection
- OWASP Cheat Sheets: SQL Injection Prevention, Cross Site Scripting Prevention, CSRF Prevention, HTTP Headers, Password Storage
- node-postgres: Queries
- npm Docs: npm audit
- GitHub Docs: Dependabot-Optionen, Renovate Docs und Semantic Versioning 2.0.0 (Abschnitt zu Hauptversion 0), Ergänzung vom 26. Oktober 2026
- RFC 9116: security.txt
- ZAP, PortSwigger Web Security Academy und OWASP Web Security Testing Guide
- BSI: Webanwendungen
Häufige Fragen
Was ist Web Security?
Web Security umfasst alle Maßnahmen, die Web-Anwendungen, ihre Daten und ihre Nutzer vor Angriffen schützen. Dazu gehören Zugriffskontrolle, Schutz vor Injection und XSS, sichere Anmeldung, Verschlüsselung, sichere Konfiguration und aktuelle Abhängigkeiten. Die OWASP Top 10 fasst die wichtigsten Risiken zusammen.
Was sind die OWASP Top 10?
Eine Liste der zehn kritischsten Sicherheitsrisiken für Web-Anwendungen, herausgegeben vom OWASP-Projekt. Die Ausgabe 2025 führt Broken Access Control auf Rang 1, gefolgt von Security Misconfiguration und Software Supply Chain Failures. Injection einschließlich XSS steht auf Rang 5.
Was ist der Unterschied zwischen XSS und CSRF?
Bei XSS schleust ein Angreifer Skriptcode in deine Seite, der im Browser anderer Nutzer läuft. Bei CSRF bringt eine fremde Seite den Browser eines angemeldeten Nutzers dazu, ungewollt eine Aktion in deiner Anwendung auszulösen. XSS wehrst du mit korrekter Ausgabe ab, CSRF mit Tokens und SameSite-Cookies. Laut OWASP hebelt eine XSS-Lücke jeden CSRF-Schutz aus.
Wie verhindere ich SQL-Injection?
Mit parametrisierten Abfragen (Prepared Statements): Der SQL-Text bleibt fest, Eingaben gehen getrennt als Parameter an die Datenbank. Das ist laut OWASP die erste Abwehrmaßnahme. Tabellen- und Spaltennamen lassen sich nicht parametrisieren und gehören gegen eine Liste erlaubter Werte geprüft.
Welcher Web-Security-Scanner ist kostenlos?
ZAP (Zed Attack Proxy, früher OWASP ZAP) ist ein kostenloser, quelloffener Scanner für Web-Anwendungen. Er prüft eine laufende Anwendung von außen. Für JavaScript-Abhängigkeiten zeigt npm audit bekannte Schwachstellen. Beides ersetzt keine Prüfung des eigenen Codes auf fehlende Zugriffskontrollen.
Was ist eine security.txt?
Eine Textdatei nach RFC 9116 unter /.well-known/security.txt, die Sicherheitsforschern zeigt, wie sie Lücken melden können. Pflicht sind die Felder Contact mit einer Kontaktmöglichkeit und Expires mit einem Ablaufdatum, das weniger als ein Jahr in der Zukunft liegen soll.
Wo lerne ich Web Security für Entwickler?
Kostenlos mit der Web Security Academy von PortSwigger, die interaktive Übungslabore anbietet. Die OWASP Cheat Sheets erklären die Abwehr je Thema mit Beispielen. Das BSI veröffentlicht Leitfäden zur Entwicklung sicherer Webanwendungen, auch für Auftraggeber.