Jo: SQL-Injection mit PostgreSQL

Hallo,

ich arbeite bisher mit MySQL und maskiere so meine aufgefangenen Variablen um SQL-Injection zu verhindern:

$abfrage = "SELECT spalte1
            FROM tabelle
            WHERE spalte2 = '".mysql_real_escape_string($_POST['spalte2Wert'])."'";
$query = mysql_query($abfrage) or die("Datenbankabfrage ist fehlgeschlagen!");

jetzt muß ich das gleiche mit PostgreSQL realisieren. Wie kann ich hier vorgehen um SQL-Injection zu verhindern? (ich verwende PHP 5 mit ADODB)

Danke
Jo

  1. Hallo,

    ich bin mir nicht ganz sicher, aber selbst bei MySQL und PostgreSQL mit PHP gibt es Prepared Statements. Setzt man diese ein, kann so gut wie nie eine SQL-Injection stattfinden.
    Desweiteren würde eine SQL-Injection bei PostgreSQL auch nicht so leicht wie bei MySQL funktionieren. MySQL - quasi der Internet Explorer unter den Datenbanken - meint, dass geöffnete Kommentare (SQL-Injection) automatisch geschlossen werden müssen, was die SQL-Injection ja erst ermöglicht.

    zB eine Passwortüberprüfung:
    SELECT name FROM tabelle where password=xxxx;

    Durch eien SQL-Injection in mySQL wird daraus
    SELECT name FROM tabelle /* where password=xxxx; */

    PostgreSQL würde so etwas generieren (ohne abschließender Kommentarschließung)

    SELECT name FROM tabelle /* where password=xxxx;

    PostgreSQL würde das Statement als fehlerhaft werten und nichts liefern.

    Markus

    1. Hello,

      ich bin mir nicht ganz sicher, aber selbst bei MySQL und PostgreSQL mit PHP gibt es Prepared Statements. Setzt man diese ein, kann so gut wie nie eine SQL-Injection stattfinden.

      okay, PreparedStatements schaffen schneller Abhilfe.

      Desweiteren würde eine SQL-Injection bei PostgreSQL auch nicht so leicht wie bei MySQL funktionieren. MySQL - quasi der Internet Explorer unter den Datenbanken - meint, dass geöffnete Kommentare (SQL-Injection) automatisch geschlossen werden müssen, was die SQL-Injection ja erst ermöglicht.

      meinst du wirklich, dass automatisch geschlossene Kommentare das Problem sind. Vielleicht sind sie eines, aber bestimmt nicht das.
      Wie wäre es mit
      SELECT * FROM users WHERE name = '$name' AND password = '$password' und du gibst als Passwort
      ' OR 1=1 OR password='
      an? Du erhälst
      SELECT * FROM users WHERE name = '...' AND password = '' OR 1=1 OR password=''
      ein Statement, dass die alle User zurückliefert.

      SELECT name FROM tabelle /* where password=xxxx;
      PostgreSQL würde das Statement als fehlerhaft werten und nichts liefern.

      warum sollte es das tun, das ist syntaktisch ein komplett korrektes Statement. Es liefert alle Datensätze der Tabelle zurück.

      MfG
      Rouven

      --
      -------------------
      sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
      Computer programming is tremendous fun. Like music, it is a skill that derives from an unknown blend of innate talent and constant practice. Like drawing, it can be shaped to a variety of ends: commercial, artistic, and pure entertainment. Programmers have a well-deserved reputation for working long hours but are rarely credited with being driven by creative fevers. Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination, but because their imagination reveals worlds that others cannot see. -- Larry OBrien and Bruce Eckel in Thinking in C#
      1. Hallo,

        Ja, das ist eine weitere Möglichkeit einer SQL-Injection.

        SELECT name FROM tabelle /* where password=xxxx;
        PostgreSQL würde das Statement als fehlerhaft werten und nichts liefern.
        warum sollte es das tun, das ist syntaktisch ein komplett korrektes Statement. Es liefert alle Datensätze der Tabelle zurück.

        Ich probierte es zwar noch nicht aus, aber ich las, dass PostgreSQL mit einem fehlerhaften Statement abbrechen würde, wenn ein Kommentar geöffnet, aber nicht geschlossen wird.

        Demnach dürfte unter PostgreSQL so etwas nicht funktionieren.
        SELECT name FROM tabelle /* where password=xxxx;

        Markus

        1. Hello,

          wenn ein Kommentar geöffnet, aber nicht geschlossen wird
          SELECT name FROM tabelle /* where password=xxxx;

          ach sorum meinst du das, des Kommentares wegen - sorry, ich war bei SELECT FROM ohne WHERE. Da hast du höchstwahrscheinlich Recht.

          MfG
          Rouven

          --
          -------------------
          sh:| fo:} ch:? rl:( br:& n4:{ ie:| mo:} va:) js:| de:] zu:| fl:( ss:) ls:& (SelfCode)
          When the only tool you've got is a hammer, all problems start to look like nails.
    2. echo $begrüßung;

      ich bin mir nicht ganz sicher, aber selbst bei MySQL und PostgreSQL mit PHP gibt es Prepared Statements. Setzt man diese ein, kann so gut wie nie eine SQL-Injection stattfinden.

      Bei Werten, die über den Bind-Mechanismus von Prepared Statements an das DBMS gelangen, ist die Quote prinzipbedingt bei 0.

      Desweiteren würde eine SQL-Injection bei PostgreSQL auch nicht so leicht wie bei MySQL funktionieren. MySQL - quasi der Internet Explorer unter den Datenbanken - meint, dass geöffnete Kommentare (SQL-Injection) automatisch geschlossen werden müssen, was die SQL-Injection ja erst ermöglicht.

      Das halte ich für einen Anwendungsfall, der wohl nur im Zusammenhang mit Stored Procedures auftreten kann. Ansonsten sind SQL-Statements wohl eher in anderem Programmcode zu finden, und da stelle ich mir es nicht als sinnvoll vor, Kommentare in SQL-Statements enthaltenden Strings abzulegen. Diese Kommentare müssten ja dann auch bei jeder Abfrage mit an das DBMS gesendet werden.

      echo "$verabschiedung $name";

    3. Moin!

      MySQL - quasi der Internet Explorer unter den Datenbanken - meint, dass geöffnete Kommentare (SQL-Injection) automatisch geschlossen werden müssen, was die SQL-Injection ja erst ermöglicht.

      Diese Aussage ist sachlich falsch hinsichtlich der Tatsache, dass es an der Kommentarinterpretation liegen würde.

      zB eine Passwortüberprüfung:
      SELECT name FROM tabelle where password=xxxx;

      Welche Teile dieses SQL-Strings werden wohl aus dynamischen Quellen stammen?

      Durch eien SQL-Injection in mySQL wird daraus
      SELECT name FROM tabelle /* where password=xxxx; */

      Das wird nie passieren, wenn nicht der gesamte WHERE-Teil dynamisch per Variable in das oben genannte Beispielstatement eingefügt würde. Sowas tut man aber in der Regel nicht.

      Realistisch ist:
      SELECT name FROM tabelle WHERE password=$userwert

      Dementsprechend kann auch erst hinter dem "password=" irgendeine SQL-Injection ansetzen.

      Dein Szenario ist also unzutreffend formuliert, und die Tatsache, dass die eine oder andere Datenbank eventuell auf das Prüfen des ordnungsgemäß geschlossenen Kommentars verzichtet, ist absolut kein Hinderungsgrund.

      PostgreSQL würde so etwas generieren (ohne abschließender Kommentarschließung)

      SELECT name FROM tabelle /* where password=xxxx;

      Wenn du erklärst, warum PostgreSQL sowas generieren würde... Wie kommt das Kommentarzeichen da vorne hinein?

      PostgreSQL würde das Statement als fehlerhaft werten und nichts liefern.

      PostgreSQL ist genauso mit Injections angreifbar, wie jede andere Datenbank auch. Wer es schafft, an der von dir postulierten Stelle das Öffnen eines Kommentars zu injecten, der schafft es ebenso, am Ende des Querys den Kommentar wieder zu schließen.

      - Sven Rautenberg

      1. Moin!

        PS: Der Klassiker unter den Injections... ;)

        - Sven Rautenberg

  2. Hallo,

    ich arbeite bisher mit MySQL und maskiere so meine aufgefangenen Variablen um SQL-Injection zu verhindern:

    jetzt muß ich das gleiche mit PostgreSQL realisieren. Wie kann ich hier vorgehen um SQL-Injection zu verhindern? (ich verwende PHP 5 mit ADODB)

    zum Beispiel könntest Du quote() verwenden.

    Freundliche Grüße

    Vinzenz