Vorwort: Warum Sicherheit keine Option, sondern grundlegende Hygiene ist
\n\nStellen Sie sich vor: Sie schreiben einen coolen Webdienst in C#. Alles funktioniert perfekt – Benutzer registrieren sich, hinterlassen Kommentare, suchen nach Produkten. Und dann kommt der "Hacker Vasya" (der eigentlich nur ein Skript aus dem Internet kopiert hat) – und leert die gesamte Datenbank. Oder, noch schlimmer, fügt in Ihre Seite ein Skript ein, das die Cookies aller Besucher stiehlt.
\n\nKlingt wie ein Drehbuch für einen Horrorfilm? Und doch passiert so etwas jeden Tag. Laut OWASP-Statistik gehören Injection-Angriffe (SQL, XSS, LDAP) zu den Top 3 der gefährlichsten Schwachstellen von Webanwendungen. Und C# gibt Ihnen trotz all seiner Zuverlässigkeit standardmäßig keinen Immunitätsschild.
\n\nIn diesem Artikel analysieren wir die beiden häufigsten Angriffe – SQL-Injection und XSS (Cross-Site-Scripting). Sie erhalten nicht nur Theorie, sondern praktische Schutztechniken in C# mit echten Codebeispielen. Los geht's!
\n\nSQL-Injection: Wenn der Benutzer zum Hacker wird
\n\nWie das in der Praxis aussieht
\n\nAngenommen, Sie haben eine einfache Anmeldung. Der Benutzer gibt Login und Passwort ein, und Sie erstellen die Abfrage wie folgt:
\n\nstring login = txtLogin.Text;\nstring password = txtPassword.Text;\nstring query = "SELECT * FROM Users WHERE Login = '" + login + "' AND Password = '" + password + "'";\nSqlCommand cmd = new SqlCommand(query, connection);\n\nSieht logisch aus? Falsch! Wenn ein Angreifer im Login-Feld ' OR 1=1 -- eingibt, wird die Abfrage zu:
SELECT * FROM Users WHERE Login = '' OR 1=1 --' AND Password = '...'\n\nAlles nach -- ist ein Kommentar. Die Bedingung 1=1 ist immer wahr. Die Abfrage gibt alle Benutzer zurück, und die Authentifizierung ist erfolgreich. Und wenn statt des Kommentars DROP TABLE Users eingefügt wird? Tschüss, Datenbank.
Schutz Nr. 1: Parametrisierte Abfragen (Ihr wichtigster Schild)
\n\nDer beste Schutz vor SQL-Injection ist, niemals Strings manuell zu verketten. Verwenden Sie Parameter. Der SQL-Server maskiert gefährliche Zeichen selbst, und Ihre Datenbank erhält die Daten als Werte, nicht als Code.
\n\nstring login = txtLogin.Text;\nstring password = txtPassword.Text;\n\nstring query = "SELECT * FROM Users WHERE Login = @Login AND Password = @Password";\n\nusing (SqlConnection conn = new SqlConnection(connectionString))\n{\n SqlCommand cmd = new SqlCommand(query, conn);\n cmd.Parameters.AddWithValue("@Login", login);\n cmd.Parameters.AddWithValue("@Password", password);\n \n conn.Open();\n SqlDataReader reader = cmd.ExecuteReader();\n // Ergebnisverarbeitung\n}\n\nBeachten Sie: @Login und @Password sind Parameter. Selbst wenn der Benutzer '; DROP TABLE Users; -- eingibt, interpretiert das DBMS dies als gewöhnliche Zeichenfolge, nicht als Code. Sicher und elegant.
Schutz Nr. 2: Gespeicherte Prozeduren
\n\nEin weiteres mächtiges Werkzeug sind gespeicherte Prozeduren. Sie schützen nicht nur vor Injection, sondern verbessern auch die Leistung (Abfragepläne werden zwischengespeichert).
\n\n-- SQL Server\nCREATE PROCEDURE GetUserByLogin\n @Login NVARCHAR(50)\nAS\nBEGIN\n SELECT * FROM Users WHERE Login = @Login\nEND\n\n// C#-Code\nusing (SqlConnection conn = new SqlConnection(connectionString))\n{\n SqlCommand cmd = new SqlCommand("GetUserByLogin", conn);\n cmd.CommandType = CommandType.StoredProcedure;\n cmd.Parameters.AddWithValue("@Login", inputLogin);\n \n conn.Open();\n // ...\n}\n\nSchutz Nr. 3: Entity Framework und ORM
\n\nWenn Sie Entity Framework (oder ein anderes ORM) verwenden, sind Sie bereits teilweise geschützt. EF generiert automatisch parametrisierte Abfragen. Aber es gibt einen Haken: Rohe SQL-Abfragen über EF (Methode FromSqlRaw) sind die gleiche Verkettung. Seien Sie wachsam!
// SCHLECHT:\nvar users = context.Users.FromSqlRaw("SELECT * F