Archive for April, 2008

BERLIN: Strikääääääää!

Tja, da hat der Kollege Pflüger wohl ordentlich ins Klo gegriffen. Und die versammelte Springer-Presse gleich mit, denn: Der Volksentscheid zum Weiterbetrieb des Flughafens Tempelhof ist gescheitert. Komplett. Ein für alle mal.

Irgendwie ist das insgesamt ein nettes Wochenende: Tolles Wetter und Springer eins in die Fresse gegeben.

Schön.

RESPEKT: Endlich traut sich jemand!

SPON berichtet gerade, dass Yvonne Bönisch, ihres Zeichens Olympiasiegerin im Judo 2004, an der Eröffnungsfeier der olympischen Spiele in Peking nicht teilnehmen will und sich weitere Protestmaßnahmen vorbehält.

Absoluten Respekt und vollste Hochachtung dafür! Schade aber, dass sowas die Ausnahme ist – von mündigen Bürgern könnte man durchaus mehr erwarten. Die Herrschaften Sportler sind allerdings durch und durch korrumpiert auf ihren eigenen Vorteil bedacht angehalten, sich zurück zu halten- und halten deswegen den Mund. Könnte ja ein Sponsor nicht gut finden, sowas.

Schlimmer ist nur noch, dass das ja kein spezielles Problem der Sportler ist, sondern durchaus im Kleinen anfängt: Da wird weggeschaut, da wird der Mund gehalten, da wird lieber nix gesagt – man könnte ja irgendwelche Nachteile erfahren. Feiglinge.

Nochmal: Vollste Hochachtung für diese Haltung. Könnten sich eine Menge Leute eine Scheibe von abschneiden.

BERLIN: Pro Provinz!

Also, wenn ich mir dieses Bild ansehe, dann bin ich für die Provinz.

Zur Erklärung: In Berlin läuft momentan ein Volksbegehren für den Erhält von Tempelhof (der Luftbrückenflugplatz) als Flugplatz. Initiiert wurde das Begehren von in Tempelhof ansässigen Firmen und der Berliner CDU – der CDU, die es in den neunziger Jahren in Person vom damaligen Verkehrsminister Wissmann zur Bedingung für den neuen Großflughafen BBI gemacht hat, dass Tegel und Tempelhof geschlossen werden sollen.

Argumentiert wird u.a. damit, dass Berlin einen City-Flughafen benötige. Dummes Argument, denn BBI ist keine zehn Kilometer weg. Ebenfalls heißt es, dass Tempelhof ein großer Verkehrsträger sei – 600.000 Geschäftsleute im Jahr seien ja eine wichtige Größe. Doof nur, wenn man sich das auf den Tag runterrechnet – da bleiben weniger als 2.000 meist sehr zahlungskräftige Kunden übrig. Die dann für mehr als 20 Millionen Verlust pro Jahr sorgen. Nicht zu reden vom Lärm, von der Unsicherheit und von der Fläche, die schlichtweg viel sinnvoller genutzt werden könnte.

Nö, für Tempelhof spricht bis auf Clientelwirtschaft überhaupt nix. Es ist ja nicht so, dass das denkmalgeschützte Flughafengebäude abgerissen, oder die Geschichte nicht mehr erzählt werden soll. Oder das etwa ab morgen wieder eine Luftbrücke benötigt werden sollte. Es sollen lediglich nicht mehr Millionen von EUR für Superreiche verschwendet werden.

Wenn man sich darüber hinaus mal anschaut, wer da alles beim Bürgerbegehren(?) mit macht, dann wird die Zielrichtung schon klarer: CDU, FDP, Springer-Presse. Na, klingelts? Genau! Die, die den Flughafen dicht machen wollen, sind die Roten. Und die Schwarz-Braunen Gelben brauchen dringend mal wieder ein Erfolgserlebnis. Deshalb holen die jetzt die Volks- (“Alle Macht geht vom Volke aus” – nur weiß niemand, was das nun genau mit Tempelhof zu tun haben soll) und die Provinzkeule raus.

Macht sich ja sonst so doof, so auf Jahrzehnte in der Opposition, weil man nur den Diepgen Steffel Pflüger hat.

Übrigens, die 100 Gründe, die laut der B.Z. (einer Springer-Zeitung) für Tempelhof sprechen, werden hier sehr lesenswert zerpflückt.

MEDIEN: Stimmt damals wie heute

Dem muss man eigentlich nix hinzufügen:

via Hauptstadtblog.

SICHERHEIT: Schutz vor SQL-Injection

Das klassische Argument für den Einsatz parametrisierter Statements ist der Schutz vor SQL-Injection. SQL-Injection bezeichnet dabei den Vorgang des Einschleusens von fremden SQL-Statements in eigene SQL-Statements.

Beispiel: Die klassische Benutzer-Authentifizierung, bei der Benutzername und Kennwort übergeben werden. Der typische (C#-) Code für das generieren des SQL-Statements sieht dann in etwa so aus:

   // Werte einlesen
   String username = tbLoginName.Text;
   String password = tbPassword.Text;

   // Statement bauen
   String sqlStatement = “SELECT COUNT(1) FROM Users ” +
      “WHERE Username = ‘” + username + “‘ ” +
      “AND Password = ‘” + password + “‘”;

   // Command erzeugen
   DbCommand command = conn.CreateCommand();
   command.CommandText = sqlStatement;

   // Statement ausführen
   int result = (int) command.ExecuteScalar();

Lassen Sie uns mal einige Varianten für Benutzernamen und Kennwörter durchspielen.

Variante #1:

  • Benutzername: foo
  • Kennwort bla
  • SQL-Statement: SELECT COUNT(1) FROM Users
    WHERE Username = ‘foo‘ AND Password = ‘bla

Kein Problem hier, alles gut. Wenn Benutzername und Kennwort passen, dann ist es fein.

Variante #2:

  • Benutzername: ‘ OR 1=1 –
  • Kennwort: Weiß nicht
  • SQL-Statement: SELECT COUNT(1) FROM Users
    WHERE Username = ‘‘ OR 1=1 –‘ AND Password = ‘Weiß nicht

Großes Problem hier. Das SQL-Statement sieht irgendwie krank aus und kann ganz sicher nicht funktionieren. Sicher?! Doch, es funktioniert, denn die beiden aufeinanderfolgenden Bindestriche interpretiert ein SQL-Server beispielsweise als Kommentar – alles, was danach kommt, wird also ignoriert. Das tatsächlich ausgeführte SQL-Statement sieht also so aus:

  • SQL-Statement: SELECT COUNT(1) FROM Users WHERE Username = ” OR 1=1

Ganz gewaltiges Problem jetzt: Die Abfrage selektiert alle Datensätze, deren Username-Spalte entweder leer ist, oder für die 1=1 gilt. Und da 1=1 immer gilt, werden also alle Datensätze selektiert. Die Anmeldung wird jetzt also klappen.

Variante #3:

  • Benutzername: ‘; INSERT INTO Users (‘karsten’, ‘sicher’) –
  • Kennwort: Keine Ahnung
  • SQL-Statement: SELECT COUNT(1) FROM Users
    WHERE Username = ‘‘; INSERT INTO Users (‘karsten’, ‘sicher’) –‘ AND Password = ‘Keine Ahnung

Ebenfalls großes Problem: Nun werden zwei SQL-Statements ausgeführt, denn das Semikolon trennt SQL-Statements voneinander. Alles, was nach dem Kommentar-Zeichen kommt, wird komplett ignoriert. Das eigentliche SQL-Statement sieht also so aus:

  • SQL-Statement: SELECT COUNT(1) FROM Users WHERE Username = ”; INSERT INTO Users (‘karsten’, ‘sicher’)

Super, jetzt haben wir einen zweiten Datensatz in der Tabelle!

Die Lösung

Der Lösungsansatz ist ganz einfach: Parametrisierte SQL-Statements verwenden. Dazu muss der obenstehende Code nur ein wenig abgewandelt werden:

   // Werte einlesen
   String username = tbLoginName.Text;
   String password = tbPassword.Text;

   // Statement bauen
   String sqlStatement = “SELECT COUNT(1) FROM Users ” +
      “WHERE Username = @Username ” +
      “AND Password = @Password”;

   // Command erzeugen
   DbCommand command = conn.CreateCommand();
   command.CommandText = sqlStatement;

   // Parameter anfügen
   DbParameter param = command.CreateParameter();
   param.ParameterName = “@Username”;
   param.Value = username;
   command.Parameters.Add(param);

   param = command.CreateParameter();
   param.ParameterName = “@Password”;
   param.Value = password;
  command.Parameters.Add(param);


   // Statement ausführen
   int result = (int) command.ExecuteScalar();

Nun werden die Daten anders an die Datenbank übergeben – nämlich in zwei Schritten: Zuerst wird das Statement übergeben, anschließend erfolgt die Übergabe der Parameter. Auf Ebene der Datenbank wird nun nicht etwa ein SQL-Statement dynamisch zusammengebaut, sondern es wird wie in Form eines Prozeduraufrufs verarbeitet. Für die Beispiele gilt also:

Variante #1:

  • Benutzername: foo
  • Kennwort bla
  • SQL-Statement: SELECT COUNT(1) FROM Users
    WHERE Username = @Username AND Password = @Password

Kein Problem hier, alles gut. Wenn Benutzername und Kennwort passen, dann ist es fein.

Variante #2:

  • Benutzername: ‘ OR 1=1 –
  • Kennwort: Weiß nicht
  • SQL-Statement: SELECT COUNT(1) FROM Users
    WHERE Username = @Username AND Password = @Password

Kein Problem hier. Wenn es nicht zufällig einen Datensatz mit dem Benutzernamen ‘ OR 1=1 – und dem Kennwort Weiß nicht gibt, dann wird nix gefunden. Und wenn es den Datensatz gibt, ist der Benutzer ordnungsgemäß authentifiziert.

Variante #3:

  • Benutzername: ‘; INSERT INTO Users (‘karsten’, ‘sicher’) –
  • Kennwort: Keine Ahnung
  • SQL-Statement: SELECT COUNT(1) FROM Users
    WHERE Username = @Username AND Password = @Password

Kein Problem hier. Wenn es nicht zufällig einen Datensatz mit demBenutzernamen ‘; INSERT INTO Users (‘karsten’, ‘sicher’) – und dem Kennwort Keine Ahnung gibt, dann wird nix gefunden. Und wenn es den Datensatz gibt, ist der Benutzer ordnungsgemäß authentifiziert.

Also, keine Sicherheitsprobleme bei Verwendung von parametrisierten Statements.

Wer mehr über SQL-Injection wissen möchte, sollte dringend einen Blick in die Wikipedia werfen.

DOTNET: Nehmt endlich parametrisierte SQL-Statements!

Meine Güte, ich halts langsam nicht mehr aus: Viel zu viele “Entwickler” verwenden klassische (=dynamisch zusammengestellte) SQL-Statements und wundern sich dann über komischste Seiteneffekte. Dabei kann es doch so einfach sein, wenn man nur mal auf die Ratschläge hören würde, die einem an jeder Ecke entgegen gerufen werden.

Die wichtigsten Gründe für parametrisierte Statements sind:

  • Schutz vor SQL-Injection
  • Keine “komischen” Effekte beim Einfügen von Daten
  • Höhere Performance von SQL-Statements
  • Bessere Wartbarkeit von Applikationen

Für die klassischen SQL-Statements spricht heutzutage nichts mehr. Das gilt sowohl für Java, als auch für .NET-Applikationen. Um so schlimmer, dass es immer noch Bücher und Tutorials gibt, die dennoch diese völlig veraltete, unperformante und unsichere Art der Datenbankansprache postulieren.

Wenn man mich so fragt…

…dann bin ich für die Provinz.::::Zur Erklärung: In Berlin läuft momentan ein Volksbegehren für den Erhält von Tempelhof (der Luftbrückenflugplatz) als Flugplatz. Initiiert wurde das Begehren von in Tempelhof ansässigen Firmen und der Berliner CDU – der CDU, die es in den neunziger Jahren in Person vom damaligen Verkehrsminister Wissmann zurr Bedingung für den neuen Großflughafen BBI gemacht hat, dass Tegel und Tempelhof geschlossen werden sollen. Mit im Boot ist natürlich noch die FDP. Argumentiert wird u.a. damit, dass Berlin einen City-Flughafen benötige. Dummes Argument, denn BBI ist keine zehn Kilometer weg. Ebenfalls heißt es, dass Tempelhof ein großer Verkehrsträger sei – 250000 Geschäftsleute im Jahr seien ja eine wichtige Größe. Doof nur, wenn man sich das auf den Tag runterrechnet – da bleiben weniger als 700 meist sehr zahlungskräftige Kunden übrig. Die dann für mehr als 20 Millionen Verlust pro Jahr sorgen.::::Nö, für Tempelhof spricht bis auf Clientelwirtschaft überhaupt nix. Es ist ja nicht so, dass das denkmalgeschützte Flughafengebäude abgerissen, oder die Geschichte nicht mehr erzählt werden soll.::::Aus dem Grund bleibe ich dann lieber doch Provinz.::::