marco: Variable wird gesetzt aber nicht in MySQL geschrieben

Hi,

ich verzweifel endgültig:

Über ein Formular lasse ich die Variablen $bw_ap und $bw_text setzen. Die soll dann in eine MySQL Datenbank geschrieben werden.

  
echo $bw_ap; // schreibt die Eingabe "pp"  
$bw_ap2 = "a".$bw_ap."a";  
echo $bw_ap2; // echo "appa";  
$do=mysql_query("UPDATE $tb_name SET bw_stat='1', bw_ap='$bw_ap2', bw_text='$bw_text' WHERE id='$ac_bw'") or die(mysql_error()); // setzt bw_stat = 1, bw_ap = aa (!), bw_text = _LEER_  

Wie kann $bw_ap2 richtig ge-echo-t werden aber dann falsch eingetragen?! Wenn ich den mysql_query einfach echo-e steht da auch korrekterweise "appa", gesetzt wird aber trotzdem "aa".

Da die selbe php-Datei noch weite Datenbankbefehle enhält, die Formularfelder in die Datenbank schreiben kann es auch nicht an der Formatierung der Datei (utf8 ohne BOM) liegen.

Gibt keine Fehlermeldungen.

Habt Ihr ne Idee, wie ich dem Fehler auf die Spur komme?

Danke
Marco

  1. Hi there,

    ich verzweifel endgültig:

    zu früh...

    echo $bw_ap; // schreibt die Eingabe "pp"
    $bw_ap2 = "a".$bw_ap."a";
    echo $bw_ap2; // echo "appa";
    $do=mysql_query("UPDATE $tb_name SET bw_stat='1', bw_ap='$bw_ap2', bw_text='$bw_text' WHERE id='$ac_bw'") or die(mysql_error()); // setzt bw_stat = 1, bw_ap = aa (!), bw_text = LEER

      
      
    '$bw\_ap2' wird von PHP als String betrachtet, der den Wert '$bw\_ap2' hat. "Richtig" wäre "$bw\_ap2", da nur der als Variable substituiert wird, was zwischen doppelten Anführungszeichen steht. Und "Richtig" hab ich persönlich unter Anführungszeichen gesetzt, weil das setzen von Variablen innerhalb von Anführungszeichen ohnehin ein hundsmiserabler Stil ist; wirklich richtig wäre als ...'".$bw\_ap2."'... (von diversen möglichen Sicherheitsproblemen mit dieser Konstruktion an sich einmal abgesehen, aber das ist ein anderes Problem. Zumindest technisch müsste es jetzt gehen)...  
      
    
    
    1. zu früh...

      war ich zu früh, zu schnell überflogen, sorry, hat mit Deinem Problem nix zu tun...

      1. zu früh...

        war ich zu früh, zu schnell überflogen, sorry, hat mit Deinem Problem nix zu tun...

        ;-) Hab ich mir schon gedacht.. Kein Problem.

    2. wirklich richtig wäre als ...'".$bw_ap2."'

      genauso hab ichs auch schon probiert. Macht aber theoretisch keinen Unterschied, weil es in beiden Varianten schon innerhalb der selben Datei funktioniert.

      Den Rest habe ich leider nicht verstanden. DU meinst, dass ich statt '$bw_ap2' lieber "$bw_ap2" schreiben sollte?
      Falls ja: daran liegt es auch nicht.

      Und bei PHP ist es doch absichtlich so, dass wenn der gesamte Befehl in "..." steht, dass man $vars direkt reinschreiben kann, und man nur bei '...' unterbrechen muss (durch '.$var.').

      Außerdem schreibt er ja "aa" in die DB, die var wird also erkannt, nur der Inhalt wird nur teilweise reingeschrieben (ABER vorher richtig im echo dargestellt "appa").

    3. Hi!

      '$bw_ap2' wird von PHP als String betrachtet, der den Wert '$bw_ap2' hat. "Richtig" wäre "$bw_ap2", da nur der als Variable substituiert wird, was zwischen doppelten Anführungszeichen steht.

      Abgesehen davon - was du schon selbst erkannt hast - dass die Variable innerhalb von "" steht ...

      Und "Richtig" hab ich persönlich unter Anführungszeichen gesetzt, weil das setzen von Variablen innerhalb von Anführungszeichen ohnehin ein hundsmiserabler Stil ist; wirklich richtig wäre als ...'".$bw_ap2."'...

      ... das ist nicht "wirklich richtig" sondern umständlich. Viel mehr Zeichen zu lesen, zu tippen, sich zu vertippen und bringt am Ende keine Punkte.

      von diversen möglichen Sicherheitsproblemen mit dieser Konstruktion an sich einmal abgesehen, aber das ist ein anderes Problem.

      Das ist genau eines der Hauptprobleme, das zu SQL-Injection-Lücken führt. Diese sind sehr beliebt, unwissende Programmierer bauen sie in großer Zahl ein, wissende Cracker nutzen sie aus. Die Zeitungen sind grad voll von Einbruchsnachrichten, und ein guter Teil wird auch wegen solchen Lücken erfolgreich gewesen sein.

      Wie auch immer, "wirklich richtig" beachtet den Kontextwechsel. Und dann stellt sich das Problem der Variablensubstitution gar nicht mehr, weil man entweder Prepared Statements mit Platzhaltern verwendet, beim Verwenden von Maskierfunktionen wie mysql_real_escape_string() sowieso den String unterbrechen muss oder mit Platzhalterfunktionen wie sprintf() nebst Maskierfunktion arbeitet.

      Lo!

  2. Hi,

    Wenn ich den mysql_query einfach echo-e steht da auch korrekterweise "appa",

    Copy&Paste, Test über phpMyAdmin - Klarheit, ob Query korrekt oder nicht, und ob PEBKAC.

    gesetzt wird aber trotzdem "aa".

    Das hast du wie kontrolliert?
    Ob das UPDATE-Statement erfolgreich war, wie viele Datensätze es betroffen hat, hast du überprüft?

    MfG ChrisB

    --
    RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
    1. Copy&Paste, Test über phpMyAdmin - Klarheit, ob Query korrekt oder nicht, und ob PEBKAC.

      Korrekt und ja.

      Das hast du wie kontrolliert?
      Ob das UPDATE-Statement erfolgreich war, wie viele Datensätze es betroffen hat, hast du überprüft?

      Hab in phpMyAdmin den Datensatz angeschaut. Der Status (bw_stat=1) wird von 0 auf 1 geändert. Das query kommt also an und wird verarbeitet.

      Da es nach ID geht wird nur der eine Datensatz betroffen (UNIQUE).

      1. Hi!

        Copy&Paste, Test über phpMyAdmin - Klarheit, ob Query korrekt oder nicht, und ob PEBKAC.
        Korrekt und ja.

        Du hast also das zusammengesetzte Statement nicht so wie in deinem gezeigten Code direkt dem mysql_query() übergeben, sondern einer weiteren Variable zugewiesen, die du zur Kontrolle ausgegeben hast und dem mysql_query() übergeben hast?

        Hab in phpMyAdmin den Datensatz angeschaut. Der Status (bw_stat=1) wird von 0 auf 1 geändert. Das query kommt also an und wird verarbeitet.

        Unterbrich mal das Script hart nach dem Update und schau dir dann das Ergebnis im DBMS an. Alternativ kannst du auch eine Abfrage mit Werteausgabe einfügen. Nicht dass weiter hinten eine andere Script-Stelle eine weitere Änderung vornimmt.

        Es wäre auch möglich im DBMS eine Log-Tabelle anzulegen und einen Update-Trigger auf $tb_name zu setzen, der einen Eintrag in der Log-Tabelle vornimmt. Auch so kannst du sehen, ob nur ein Update oder noch weitere erfolgen. (Das ist aber etwas umständlicher zu implementieren als die zuvor genannte Methode.)

        Da es nach ID geht wird nur der eine Datensatz betroffen (UNIQUE).

        Und das ist nicht nur eine Vermutung sondern nachgeprüft (z.B. mit mysql_affected_rows())?

        Allgemeiner Tipp: Prüfe alles, verlass dich auf nichts, besonders bei solchen sich versteckenden Fehlern.

        Lo!

        1. Du hast also das zusammengesetzte Statement nicht so wie in deinem gezeigten Code direkt dem mysql_query() übergeben, sondern einer weiteren Variable zugewiesen, die du zur Kontrolle ausgegeben hast und dem mysql_query() übergeben hast?

          ja.

          Zum Rest:

          • Hab ID im PHP angegeben (WHERE id='4982')
          • Hab den Rest des Codes aus der Datei komplett raus genommen (sodass nichts mehr danach passiert).
          • Wenn ich die Var-Inhalte per Get in der URL übergebe funktioniert das Skript. Habe zu Beginn des Skirpts immer folgenden Aufruf:
            
          foreach ($_POST as $key => $val) {  
          	$$key = $val;  
          }  
            
          foreach ($_GET as $key => $val) {  
          	$$key = $val;  
          }  
          
          
          1. Moin!

            foreach ($_POST as $key => $val) {
            $$key = $val;
            }

            foreach ($_GET as $key => $val) {
            $$key = $val;
            }

              
            Großartig! Dann kann man dir in dein Skript ja problemlos jegliche Variable einschmuggeln. Wenn das in Kombination mit uninitialisierten Variablen passiert, ist das eine weitere, gravierend klaffende Sicherheitslücke.  
              
            Sprich: Diese Vorgehensweise ist absolut nicht sinnvoll! Das Umkopieren ist sinnlose Speicherverschwendung und verschleiert die Herkunft des Variableninhalts.  
              
             - Sven Rautenberg
            
            1. das ist absicht.
              der server ist eh nur intern. aber register globals muss an anderer stelle aus sein, daher hab ichs nachgebaut.

              1. Moin!

                das ist absicht.
                der server ist eh nur intern. aber register globals muss an anderer stelle aus sein, daher hab ichs nachgebaut.

                Das heißt, du findest es in Ordnung, dir einen unsicheren Programmierstil anzugewöhnen, weil "man's für Intern ja machen kann". Obwohl du die korrekte Vorgehensweise kennst.

                Die meisten Angriffe auf Computerinfrastruktur gehen von Insidern aus - also genau auf die Systeme, die "nur" intern sind.

                Und obendrein kannst du nicht abschätzen, ob dieser "interne" Server durch irgendeine von dir nicht verursachte Lücke nicht doch plötzlich von "außen" sichtbar ist. Wäre ja nicht das erste Mal, dass ein Angreifer durch eine Lücke in einem als eher gering eingeschätzten externen System Zugriff auf das interne Netzwerk erhält.

                - Sven Rautenberg

                1. stimme dir zu, aber wir schweifen vom thema ab.

          2. Hi!

            • Wenn ich die Var-Inhalte per Get in der URL übergebe funktioniert das Skript. Habe zu Beginn des Skirpts immer folgenden Aufruf:

            Das kann nicht weiter relevant sein, wenn dabei nicht noch andere Nebenwirkungen auftreten.

            • Hab den Rest des Codes aus der Datei komplett raus genommen (sodass nichts mehr danach passiert).

            Dann sollte es also nichts mehr geben, das unbemerkt anschließend ein weiteres Update ausführt. Wenn es doch noch passiert, dann schau auch mal ins Webserver-Logfile, wie oft das Script aufgerufen wird.

            Hmm, aber wenn nichts mehr drin ist als nur noch die Ausführung des Update, dann muss doch was mit dem Update schieflaufen. In dem Fall würde ich klein anfangen. Erst das Update mit festem Statement - das sollte problemlos gehen. Alles nachprüfen: Funktionsrückgabewerte, besonders die der mysql_*-Funktionen. (Nimm dazu immer var_dump(), das zeigt dir im Gegensatz zum echo alles genau an.) Anschließend schrittweise erweitern, Variablen statt fester Werte (Kontextwechsel beachten), noch mehr Code hinzufügen, bis der Fehler wieder auftritt.

            foreach ($_POST as $key => $val) {

            $$key = $val;
            }

            foreach ($_GET as $key => $val) {
            $$key = $val;
            }

              
            Diesen Unsinn bitte komplett streichen und direkt mit dem $\_GET/$\_POST-Array arbeiten. Du bildest sonst die Funktionalität von register\_globals nach. Zusammen mit nachlässiger Programmierung holst du dir mehr Probleme als die Tippersparnis wieder rausholen kann. Du legst damit ungeprüft, alles was irgendwer als Parameter an dein Script sendet, als Variable an. Und wenn du deine eigenen Variablen vor der Erstverwendung nicht definitiv initialisert, arbeitet dein Script mit von dir nicht vorgesehenen Werten.  
              
              
            Lo!
            
            1. alles  schon gemacht. register_globals nachbilden ist absicht.

              1. Hi!

                alles  schon gemacht.

                Nun, dann musst du ja den Fehler oder zumindest eine Unregelmäßigkeit schon gefunden haben. Ich bin kein Hellseher und kann weder wissen, was schief läuft, noch was überhaupt läuft. Du musst dich schon selbst auf die Suche begeben und genau beobachten und dann das berichten, was du nicht verstehst, so dass wir™ eine Chance haben, dir Erklärungen und/oder Vermutungen zu liefern.

                Lo!

  3. Moin!

    [code lang=php]
    echo $bw_ap; // schreibt die Eingabe "pp"
    $bw_ap2 = "a".$bw_ap."a";
    echo $bw_ap2; // echo "appa";

    echo ("UPDATE $tb_name SET bw_stat='1', bw_ap='$bw_ap2', bw_text='$bw_text' WHERE id='$ac_bw'")

    Das ergibt ne Ausgabe des Query mit 'appa', kopiert und über phpmyadmin ausgeführt gibts aber 'aa'?

    Anonsten wird dein Script 2x ausgeführt... (includiert?)

    --
    Vergesst Chuck Norris.
    Sponge Bob kann unter Wasser grillen!