Java-Sicherheit: So schützen Sie Ihren Code vor SQL-Injection und XSS-Angriffen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Wie Sie Hackern das Knacken Ihres Java-Codes erschweren: SQL-Injection und XSS unter der Lupe

\n\n

Stellen Sie sich vor: Sie haben eine perfekte Webanwendung in Java geschrieben. Schönes Interface, schnelle Logik, saubere Architektur. Sie laden sie auf den Server hoch, brühen sich einen Tee auf und... eine Stunde später erhalten Sie die Nachricht, dass die Datenbank gelöscht wurde und auf der Startseite ein frecher ASCII-Art prangt. Eine bekannte Geschichte? Leider für viele Entwickler – ja.

\n\n

Die beiden häufigsten und gefährlichsten Schwachstellen von Webanwendungen – SQL-Injection und Cross-Site-Scripting (XSS) – rauben jährlich Administratoren tausender Websites den Schlaf. Und Java ist trotz seiner Strenge keine Ausnahme. Aber es gibt auch eine gute Nachricht: Der Schutz davor ist machbar. Und sogar nicht besonders schwierig.

\n\n

In diesem Artikel analysieren wir, wie genau Angreifer Java-Anwendungen attackieren, und vor allem – wie Sie mit bewährten Werkzeugen und richtigen Codierungsgewohnheiten einen zuverlässigen Schutzschild aufbauen. Schnallen Sie sich an: Es wird viel Code, Lifehacks und ein Minimum an Fülltext geben.

\n\n

SQL-Injection: Wenn der Benutzer zum Programmierer wird

\n\n

Was ist das und warum funktioniert es?

\n\n

SQL-Injection ist eine Angriffstechnik, bei der ein Angreifer schädlichen SQL-Code über Benutzereingaben in eine Abfrage einschleust. Wenn die Anwendung gedankenlos Strings zusammenklebt, kann der Angreifer auf fremde Daten zugreifen, Tabellen löschen oder sogar die Kontrolle über den Datenbankserver übernehmen.

\n\n

Ein klassisches Beispiel für schlechten Java-Code:

\n\n
String userInput = request.getParameter("username");\nString query = "SELECT * FROM users WHERE username = '" + userInput + "'";\nStatement stmt = connection.createStatement();\nResultSet rs = stmt.executeQuery(query);
\n\n

Was passiert, wenn der Benutzer eingibt: admin' OR '1'='1? Die Abfrage wird zu:

\n\n
SELECT * FROM users WHERE username = 'admin' OR '1'='1'
\n\n

Die Bedingung '1'='1' ist immer wahr. Herzlichen Glückwunsch: Der Angreifer hat sich gerade als Administrator angemeldet, ohne das Passwort zu kennen. Und wenn er '; DROP TABLE users; -- eingibt – dann ist das Kind in den Brunnen gefallen.

\n\n

Wie man sich schützt: PreparedStatement – Ihr Schutzschild

\n\n

Die Regel Nummer eins in der Java-Anwendungssicherheit: niemals Benutzereingaben mit SQL-Abfragen verketten. Verwenden Sie parametrisierte Abfragen mit PreparedStatement.

\n\n

So sollte sicherer Code aussehen:

\n\n
String userInput = request.getParameter("username");\nString query = "SELECT * FROM users WHERE username = ?";\nPreparedStatement pstmt = connection.prepareStatement(query);\npstmt.setString(1, userInput);\nResultSet rs = pstmt.executeQuery();
\n\n

Was ist hier passiert? Die Datenbank erhält die Abfrage und die Daten getrennt. Selbst wenn userInput bösartigen SQL-Code enthält, wird er als normale Zeichenkette und nicht als Befehl interpretiert. PreparedStatement maskiert Sonderzeichen automatisch. Dies ist die erste und wichtigste Verteidigungslinie.

\n\n

Zusätzliche Maßnahmen: Gespeicherte Prozeduren und Validierung

\n\n

Neben PreparedStatement sollten Sie Folgendes verwenden:

\n\n
    \n
  • Gespeicherte Prozeduren – der Aufruf einer Prozedur über CallableStatement trennt ebenfalls Code von Daten.
  • \n
  • Whitelists – wenn Sie einen Tabellen- oder Spaltennamen einsetzen müssen (was selten vorkommt), nehmen Sie ihn niemals aus der Benutzereingabe. Verwenden Sie enum oder streng definierte Konstanten.
  • \n
  • Eingabevalidierung – prüfen Sie, ob eine E-Mail wie eine E-Mail aussieht und eine Zahl eine Zahl ist. Aber denken Sie daran: Validierung ist eine zusätzliche Schicht, kein Ersatz für PreparedStatement.
  • \n
\n\n

Beispiel für die sichere Arbeit mit dynamischen Tabellennamen:

\n\n
public enum TableName {\n    USERS, PRODUCTS, ORDERS\n}\n\npublic void queryTable(TableName table) {\n    String que                

Blogs

Buchempfehlungen