Konstantin: Forensuche - Mysqlabfrage

Habe mit mein erstes kleines Forum geschrieben und stehe gerade bei der
Forensuche vor einem kleinen Problemchen.

Zunächst meine Tabellen(vereinfacht):

  • thread (id, titel, beschreibung, closed, forum_id, wichtig)
  • beitrag (id, thread_id, von_id, edit_time, edit_von, kommentar, time)

Meine SQL-Abfrage für die Suche:

[code lang]
SELECT
  thread.id,thread.forum_id,thread.titel,thread.beschreibung
FROM
  thread,beitrag WHERE thread.id=beitrag.thread_id AND thread.forum_id="$auswahl"
 AND MATCH(beitrag.kommentar) AGAINST('" . $suchen . "')
LIMIT 0,10
[/code]

Das Problem: Die Forensuche funktioniert zwar, aber es werden Threads in denen jetzt z.B. das Suchwort "test" mehrfach vorkommt, auch mehrfach gelistet.

Gehe ich die Suche falsch an? Wie kann ich das lösen?

danke im vorraus

  1. Das Problem: Die Forensuche funktioniert zwar, aber es werden Threads in denen jetzt z.B. das Suchwort "test" mehrfach vorkommt, auch mehrfach gelistet.

    Gehe ich die Suche falsch an? Wie kann ich das lösen?

    danke im vorraus

    Mir hat bereits jemand geholfen: Lösung DISTINCT ALSO "SELECT DISTINCT...."

    Ist die Abfrage ansonsten in Ordnung? performancemäßig? Habe dahinter noch eine mit LIKE Falls kein ergebnis geliefert wird

    1. Hallo,

      die Abfrage ist "ansonsten" sicherheitsbezüglich schlecht. Durch die direkte Verwendung von PHP Variablen in deinem dynamisch aufgebauten SQL Statement erlaubst du "bösen" Benutzern eine Tätigkeit, die unter dem Begriff "SQL Injection" bekannt ist.

      Sie könnten durch geschickte Wahl der Eingabewerte quasi alles mit deiner Datenbank machen.

        
      WHERE thread.id=beitrag.thread_id AND thread.forum_id=\"$auswahl\"  
      
      

      $auswahl könnte z.b. folgenden Inhalt haben:

      0; DROP ... ; --

      was bewirkt, dass der erste Teil des SQL mit forum_id=0; zu ende ist, dann beliebiges SQL ausgeführt werden kann und alles was danach kommt, durch -- auskommentiert wurde.

      Lösungsvorschläge zum Thema SQL Injection solltest du im Archiv dieses Forums ausreichend finden.

      Cheers,
      Frank

      1. echo $begrüßung;

        die Abfrage ist "ansonsten" sicherheitsbezüglich schlecht. Durch die direkte Verwendung von PHP Variablen in deinem dynamisch aufgebauten SQL Statement erlaubst du "bösen" Benutzern eine Tätigkeit, die unter dem Begriff "SQL Injection" bekannt ist.

        Soweit so richtig.

        Sie könnten durch geschickte Wahl der Eingabewerte quasi alles mit deiner Datenbank machen.

        Hier fängt es an, nicht mehr ganz richtig zu werden.

        WHERE thread.id=beitrag.thread_id AND thread.forum_id=\"$auswahl\"
        $auswahl könnte z.b. folgenden Inhalt haben:
        0; DROP ... ; --

        was bewirkt, dass der erste Teil des SQL mit forum_id=0; zu ende ist, dann beliebiges SQL ausgeführt werden kann und alles was danach kommt, durch -- auskommentiert wurde.

        Diese Möglichkeit wurde schon seit langem von PHP unterbunden. Multiple Statements werden nur noch von mysqli_multi_query() ausgeführt, wofür PHP5 und die mysqli-Extension notwendig ist.

        Nichtsdestotrotz kann man aber auch ein einzelnes Statement so erweitern, dass man damit etwas anderes als vorgesehen erreicht. Z.B. könnte eine WHERE-Klausel so erweitert werden, dass sie immer wahr ist, so dass bei einem Passwortvergleich das zur Kennung nötige Passwort nicht benötigt wird.

        Lösungsvorschläge zum Thema SQL Injection solltest du im Archiv dieses Forums ausreichend finden.

        Ja, und auch das PHP-Handbuch bietet dafür ein eigenes Kapitel an: Database Security

        echo "$verabschiedung $name";

        1. Danke, ich werde mich zu SQL-Injections informieren

          1. Hi,

            ich hab mich jetzt ein wenig informiert und bin auf die Funktion

            mysql_real_escape_string() gestoßen. Diese soll SQL-Injections verhindern. Hab ich mir gedacht wunderbar...bastel ich die überall rein. Nächstes problem...Bei jedem Formularfeld wo ich sie einsetze und der Benutzer sagen wir mal " bzw. < ... verwenden will werden da backslashs vorgehängt und in die DB eingetragen.

            ist ja auch nicht der sinn eines Forums :( Wie bekomme ich die weg?

            1. echo $begrüßung;

              ich hab mich jetzt ein wenig informiert und bin auf die Funktion mysql_real_escape_string() gestoßen. Diese soll SQL-Injections verhindern. Hab ich mir gedacht wunderbar...bastel ich die überall rein. Nächstes problem...Bei jedem Formularfeld wo ich sie einsetze und der Benutzer sagen wir mal " bzw. < ... verwenden will werden da backslashs vorgehängt und in die DB eingetragen.

              Bei den < hast du dich eventuell verguckt. Es gibt ein Feature in PHP namens Magic Quotes, das eine gewisse Sicherheit vor SQL-Injections bieten soll.

              Eine bewährte Vorgehensweise zur Datenverarbeitung ist, Eingabedaten gleich nach der Entgegennahme (wenn nötig) zu dekodiert bzw. in ein internes Format zu bringen. Weitere interne Bearbeitungsschritte erfolgen nur mit diesen "reinen" Daten. Wenn Daten ausgegeben werden sollen, werden sie, möglichst als letzter Schritt vor dieser Ausgabe, gemäß den Regeln dieser Ausgabeschnittstelle maskiert.

              Magic Quotes maskiert aber gleich die Eingabedaten, und zwar unabhängig von der wirklich verwendeten Ausgabeschnittstelle. Es behandelt auch nur die Zeichen ' (single-quote), " (double quote), \ (backslash) und NULL. Magic Quotes hilft schon mal im Groben, kennt aber die Feinheiten der verwendeten Datenbanken nicht. Es behandelt einfach zu wenig Zeichen. Außerdem behandelt es die Eingabedaten immer, und das auch, wenn man es nicht braucht. Wenn du beispielsweise ein Formuler mit Vorschau-Funktion erstellst (Stichwort Affenformular), gibst du die Eingabedaten zur Kontrolle noch einmal aus, bevor du sie der Datenbank übergibst. Doch für HTML gelten andere Maskierungsregeln. Magic Quotes sind hier also auch noch kontraproduktiv.

              Da du nun mit mysql_real_escape_sting() selbst gegen SQL-Injection vorgehst, kannst du Magic Quotes deaktivieren bzw. die ebenfalls auf der verlinkten Seite zu findende Gegenmaßnahme verwenden, falls der Provider ein Deaktivieren nicht zulässt.

              echo "$verabschiedung $name";

        2. Hi dedlfix,

          Diese Möglichkeit wurde schon seit langem von PHP unterbunden. Multiple Statements werden nur noch von mysqli_multi_query() ausgeführt, wofür PHP5 und die mysqli-Extension notwendig ist.

          Oh, wurde sie? Darüber kann ich nicht wirklich was wissen, da ich PHP/MySQL meide wie Satan das Weihwasser ;)   Es gibt aber noch andere SQL DBMS'se und Programmierwelten, die Batches mit ;-Separierung erlauben.

          Nichtsdestotrotz kann man aber auch ein einzelnes Statement so erweitern, dass man damit etwas anderes als vorgesehen erreicht. Z.B. könnte eine WHERE-Klausel so erweitert werden, dass sie immer wahr ist, so dass bei einem Passwortvergleich das zur Kennung nötige Passwort nicht benötigt wird.

          Ab und zu landet man damit einen netten Glückstreffer, ja. *<:)

          Danke für die Ergänzung :)
          Frank