• Security
  • Java · Spring Boot
  • Praxisbeispiele

Webanwendungen absichern – die häufigsten Schwachstellen und wie man sie behebt

Webanwendungen absichern – die häufigsten Schwachstellen und wie man sie behebt

Die durchschnittliche Webanwendung enthält 33 Sicherheitslücken – sechs davon kritisch.1 Bei 19 % der getesteten Anwendungen hätten Angreifer die vollständige Systemkontrolle erlangen können. Dieser Artikel zeigt, wo die häufigsten Einfallstore liegen, warum sie so verbreitet sind, und wie man sie mit konkretem Java-Code schließt.

Das Problem mit dem Sicherheits-Blindspot

„Unsere Anwendung ist sicher – wir haben HTTPS." Dieser Satz ist keine Karikatur, sondern wird in technischen Gesprächen erstaunlich häufig geäußert. HTTPS schützt die Übertragung – nicht die Anwendungslogik. SQL Injections, Cross-Site-Scripting und schwache Authentifizierungsmechanismen funktionieren über HTTPS genauso zuverlässig wie ohne.

Das Paradoxe: Die häufigsten Schwachstellen sind gut dokumentiert, seit Jahrzehnten bekannt und trotzdem allgegenwärtig. Nicht weil Entwickler schlechte Arbeit leisten, sondern weil Security unter Zeitdruck als nachgelagerte Aufgabe behandelt wird – bis etwas schiefgeht.

Was die Daten sagen

33
Sicherheitslücken im Durchschnitt pro Webanwendung
19 %
der getesteten Apps ermöglichten vollständige Systemübernahme
77 %
aller getesteten Webanwendungen enthielten Cross-Site-Scripting-Lücken

Das Open Web Application Security Project (OWASP) veröffentlicht seit 2003 eine Rangliste der kritischsten Schwachstellen in Webanwendungen. Die Top 10 sind kein akademisches Konstrukt – sie spiegeln wider, was Angreifer in der Praxis tatsächlich ausnutzen. Wer diese zehn Kategorien versteht, schließt die häufigsten Einfallstore.

Was ist OWASP?

Das Open Web Application Security Project ist eine 2001 gegründete Non-Profit-Organisation mit dem Ziel, Sicherheitswissen für das Web zugänglich zu machen. Die OWASP Top 10 – zuletzt 2021 aktualisiert – sind der de-facto-Standard für Webanwendungssicherheit in der Industrie und Grundlage vieler Compliance-Frameworks wie PCI DSS und ISO 27001.

SQL Injection: Die älteste Lücke mit dem größten Schaden

SQL Injections zählen seit über zwei Jahrzehnten zu den gefährlichsten Schwachstellen – und sind trotzdem heute noch in produktiven Systemen zu finden. Das Prinzip ist simpel: Nutzereingaben werden ungeprüft in SQL-Statements eingebaut. Ein Angreifer, der das weiß, kann die Datenbanklogik von außen kontrollieren.

Ein klassisches Beispiel: eine Login-Methode, die Benutzername und Passwort direkt in eine SQL-Query konkateniert.

public boolean isValidLogin(String username, String password) throws SQLException {
    try (Connection con = dataSource.getConnection();
            Statement stmt = con.createStatement()) {

        String sql = "SELECT * FROM USER WHERE username = '" + username
                            + "' AND password = '" + password + "'";
        ResultSet rs = stmt.executeQuery(sql);
        return rs.next();
    }
}

Gibt ein Angreifer als Benutzername a' OR 'b'='b ein, sieht die resultierende Query so aus:

SELECT *
FROM USER
WHERE username = 'a' OR 'b'='b'
AND password = 'a' OR 'b'='b'

Da 'b' = 'b' immer wahr ist, gibt die Query alle Nutzer zurück – die Authentifizierung ist vollständig umgangen. Fortgeschrittene Angriffe gehen weiter: Tabellenstrukturen auslesen, Daten manipulieren, im schlechtesten Fall Betriebssystembefehle ausführen.

Die Lösung ist bekannt und seit Java 1.1 verfügbar: PreparedStatements. Statement und Parameter werden separat an die Datenbank übergeben – Nutzereingaben können niemals Teil der ausführbaren SQL-Logik werden.

public boolean isValidLogin(String username, String password) throws SQLException {
    String sql = "SELECT * FROM USER WHERE username = ? AND password = ?";
    try (Connection con = dataSource.getConnection();
            PreparedStatement stmt = con.prepareStatement(sql)) {

        stmt.setString(1, username);   // Index startet bei 1
        stmt.setString(2, password);
        ResultSet rs = stmt.executeQuery();
        return rs.next();
    }
}
Spring-Tipp

Wer Spring Data JPA oder Spring JDBC nutzt, bekommt PreparedStatements weitgehend automatisch. @Query-Annotationen mit Parameterbindung (:param) und JpaRepository-Methoden verhindern SQL Injection durch die Framework-Abstraktion. Kritisch bleibt: native Queries mit String-Konkatenation, JdbcTemplate mit direkter SQL-Komposition und dynamische ORDER-BY-Klauseln, die Spaltennamen aus Nutzereingaben beziehen.

Sensitive Data Exposure: Was nach außen dringt

Die überwiegende Mehrheit aller Webanwendungen verarbeitet sensible Nutzerdaten – und schützt sie nicht ausreichend. OWASP nennt diese Kategorie in der aktuellen Top-10-Liste (2021) treffender: Cryptographic Failures. Das ist präziser: Das Problem ist nicht immer fehlende Verschlüsselung, sondern häufig falsch angewendete.

SzenarioRisikoEmpfehlung
HTTP ohne TLS●Daten im Klartext übertragenHTTPS erzwingen, HSTS-Header setzen
TLS ohne HSTS●Downgrade-Angriff möglichStrict-Transport-Security Header aktivieren
Passwörter mit MD5 / SHA-1 gehasht●Rainbow-Table-Angriffe praktikabelbcrypt, Argon2 oder PBKDF2 verwenden
Symmetrische Verschlüsselung mit DES / 3DES●BSI stuft als unsicher einAES-256-GCM
RSA < 2048 Bit●Faktisierbar mit modernen MittelnRSA ≥ 2048 Bit oder ECDSA P-256
Sensible Daten im Browser-LocalStorage●XSS-Angriff kompromittiert alle TokensHttpOnly-Cookies für Session-Tokens
Anti-Pattern: Passwort-Hashing mit MD5

MD5 erzeugt in moderner Hardware Milliarden Hashes pro Sekunde. Ein 8-stelliges alphanumerisches Passwort lässt sich damit in Sekunden bruteforcen. MD5 war nie für Passwörter ausgelegt – es ist eine Prüfsummen-Funktion. Für Passwörter braucht es bewusst langsame, adaptive Hashing-Algorithmen: bcrypt mit Work-Factor ≥ 12, Argon2id oder PBKDF2 mit mindestens 310.000 Iterationen (OWASP-Empfehlung 2024).

Broken Authentication: Wer kommt rein?

Schwache Authentifizierung ist in der OWASP-Statistik für 28 % der Fälle durch fehlende Zugriffsrestriktionen verursacht – gefolgt von fest einprogrammierten Passwörtern mit 22 %.2 Beides sind keine komplexen Angriffsvektoren. Es sind Konfigurationsfehler, die sich verhindern lassen.

Typische Schwachstellen
  • Keine Begrenzung von Login-Versuchen
  • Passwörter im Sourcecode oder in Properties-Dateien
  • Session-IDs in der URL statt im Cookie
  • Fehlende Session-Invalidierung beim Logout
  • Schwache oder vorhersagbare Standard-Passwörter
  • Keine Multi-Faktor-Authentifizierung für privilegierte Konten
Best Practices
  • Rate Limiting + progressive Delays nach Fehlversuchen
  • Secrets über Umgebungsvariablen oder Vault (z. B. HashiCorp)
  • HttpOnly + Secure + SameSite=Strict auf Session-Cookies
  • Session vollständig serverseitig invalidieren
  • Passwortstärke prüfen + Breached-Password-Check (HaveIBeenPwned API)
  • MFA für Admin-Zugänge verpflichtend
Spring Security: Nicht neu erfinden

Spring Security bietet Rate Limiting über AbstractSecurityInterceptor, Session-Management, CSRF-Schutz und OAuth2/OIDC-Integration out of the box. Wer Authentifizierungslogik selbst implementiert, macht in der Regel mehr Fehler als das Framework. Regel: Sicherheitskritischen Code immer auf etablierte Bibliotheken stützen.

Cross-Site-Scripting (XSS): Eigener Code in fremden Seiten

Mit 77 % Vorkommen ist XSS die am weitesten verbreitete Schwachstelle in Webanwendungen.2 Das Prinzip: Nutzereingaben werden ungefiltert in die HTML-Ausgabe übernommen – ein Angreifer kann damit JavaScript in den Browser eines anderen Nutzers einschleusen.

Es gibt zwei Hauptvarianten. Beim Reflected XSS wird Schadcode über URL-Parameter direkt auf die Seite gespiegelt – Angreifer versenden präparierte Links, oft über URL-Shortener verschleiert. Kritischer ist Persistent XSS: Schadcode wird in der Datenbank gespeichert und bei jedem Seitenaufruf ausgeliefert – potenziell an alle Nutzer gleichzeitig.

Screenshot einer Webanwendung mit Sucheingabe, die den eingegebenen Suchbegriff ungefiltert auf der Seite ausgibt – verwundbar für Reflected XSS
Eine Suchseite gibt den Suchbegriff direkt auf der Seite aus – ohne Output-Encoding eine klassische XSS-Angriffsfläche.
Screenshot der gleichen Seite, auf der durch eine XSS-Payload ein JavaScript-Alert-Dialog ausgelöst wurde
Statt eines harmlosen Suchbegriffs wird ein JavaScript-Alert ausgeführt. In der Praxis würde der Angreifer statt alert() Session-Cookies stehlen oder Formulare manipulieren.
XSS-TypQuelleReichweiteGegenmaßnahme
ReflectedURL-ParameterGezielte Angriffe über präparierte LinksOutput-Encoding, CSP-Header
Stored / PersistentDatenbank●Alle Nutzer, die die Seite aufrufenInput-Validierung + Output-Encoding
DOM-basedClient-seitiges JSNutzer mit präpariertem LinkKeine direkten DOM-Schreiboperationen mit Nutzereingaben
Modernes Framework = viel kostenloser Schutz

React, Angular und Vue escapen Ausgaben standardmäßig. innerHTML, dangerouslySetInnerHTML (React) und bypassSecurityTrustHtml (Angular) sind explizite Opt-outs aus diesem Schutz – und sollten im Code-Review immer auffallen. Serverseitig übernimmt Thymeleaf das Output-Encoding automatisch; th:utext (unescaped) ist die Ausnahme, die Aufmerksamkeit verdient.

Wie man die eigene Anwendung prüft

Manuelle Code-Reviews sind unersetzlich – aber nicht allein ausreichend. Eine Kombination aus statischer und dynamischer Analyse deckt systematisch ab, was Reviews übersehen.

ToolTypWas es prüftIntegration
SonarQubeSASTSQL Injection, XSS, Hardcoded Secrets, Code Smells●CI/CD-Pipeline
OWASP ZAPDASTXSS, Injections, CSRF, unsichere Header – im laufenden Betrieb●CI/CD, lokal
Snyk / DependabotSCABekannte CVEs in Abhängigkeiten (npm, Maven, Gradle)●GitHub / GitLab
OWASP Dependency-CheckSCACVEs in Java-Bibliotheken (NVD-Datenbank)●Maven-Plugin
TrivyContainerSchwachstellen in Docker-Images und OS-Paketen●CI/CD
Wichtige Einschränkung

Automatisierte Tools finden bekannte Muster – sie ersetzen keinen menschlichen Security-Review und kein Penetrationstesting. Falsch-Positive sind häufig, Falsch-Negative ebenfalls. Der größte Wert liegt in der kontinuierlichen Integration: Schwachstellen, die beim Commit entdeckt werden, sind um Größenordnungen günstiger zu beheben als solche, die in Produktion gefunden werden.

Was das für Java-Projekte konkret bedeutet

Sicherheit ist keine nachgelagerte Aufgabe – sie ist eine Architekturentscheidung, die von Tag eins mitgedacht werden muss. Für den Java/Spring-Stack bedeutet das in der Praxis:

Häufige Fehler im Projektalltag
  • SQL über String-Konkatenation gebaut
  • Passwörter in application.properties im Repository
  • Spring Security deaktiviert für „einfachere lokale Entwicklung"
  • Abhängigkeiten monate- oder jahrelang nicht aktualisiert
  • Stack-Traces in API-Fehlermeldungen nach außen gegeben
  • CORS auf * gesetzt und nie angepasst
Strukturierte Gegenmaßnahmen
  • JPA / Spring JDBC mit Parameterbindung konsequent nutzen
  • Secrets über Umgebungsvariablen oder Spring Cloud Vault
  • Security-Konfiguration von Beginn an im Team etablieren
  • Dependabot oder Renovate automatisch PRs erstellen lassen
  • @ControllerAdvice mit generischen Fehlermeldungen
  • CORS nur für bekannte Origins erlauben

Fazit

Die beunruhigendste Erkenntnis aus den Daten ist nicht, dass Schwachstellen existieren – sondern dass es sich bei den häufigsten um bekannte, dokumentierte und seit Jahren lösbare Probleme handelt. SQL Injection wurde 1998 erstmals systematisch beschrieben. XSS ist seit 2000 in der OWASP-Liste. Broken Authentication seit der ersten Ausgabe 2003.

Die richtigen Werkzeuge sind verfügbar: PreparedStatements, bcrypt, Spring Security, OWASP ZAP, SonarQube. Sie einzusetzen erfordert kein spezialisiertes Security-Wissen – es erfordert die Entscheidung, Sicherheit nicht als optionales Feature zu behandeln, sondern als Teil der Definition of Done.

Praktische Faustregel

Jede Nutzereingabe ist feindlich, bis das Gegenteil bewiesen ist. Validierung beim Eingang, Encoding beim Ausgang, Parameterbindung in Datenbankabfragen – diese drei Prinzipien eliminieren den Großteil der häufigsten Angriffsvektoren.


Architektur und Sicherheitskonzept prüfen lassen?

In einem strukturierten Architektur-Review prüfe ich Architektur und Sicherheitskonzept Ihrer Anwendung – etwa Authentifizierung, Schnittstellen und Datenhaltung – und liefere konkrete Handlungsempfehlungen, priorisiert nach Risiko und Aufwand.

Zum Architektur-Review
  1. Positive Technologies, „Web Application Vulnerabilities Statistics 2019", PT Security, 2019. Durchschnittlich 33 Schwachstellen pro Anwendung, 6 davon kritisch; 19 % ermöglichten vollständige Systemübernahme.
  2. OWASP, „OWASP Top 10 – 2017", Open Web Application Security Project, 2017. XSS-Vorkommen 77 %; fehlende Zugriffsrestriktionen bei Broken Authentication 28 %, Hardcoded Credentials 22 %.
  3. BSI, „IT-Grundschutz-Kataloge: G 4.35 – Unsichere kryptographische Algorithmen", Bundesamt für Sicherheit in der Informationstechnik. DES, 3DES, MD5, SHA-1 und RSA unter 2048 Bit als unsicher klassifiziert.
  4. OWASP, „OWASP Top 10 – 2021", Open Web Application Security Project, 2021. Aktuellste Ausgabe; „Sensitive Data Exposure" umbenannt zu „Cryptographic Failures".