Yogilein: Verhindern, dass über die Adresszeile Variablen verändert werden

Folgendes Problem:

Ich habe unter Javascript ein paar Spiele geschrieben und habe (leider erst jetzt) bemerkt, dass man ganz einfach die Variablen über die Adresszeile des Browsers ändern kann. Man kann z.B. dadurch seine Punkte erhöhen.

Meine Frage nun: Kann man das irgendwie unterbinden?

  1. Hallo,

    habe (leider erst jetzt) bemerkt, dass man ganz einfach die Variablen über die Adresszeile des Browsers ändern kann.

    Meine Frage nun: Kann man das irgendwie unterbinden?

    Nur erschweren, z.B. durch Verschlüsseln und/oder übertragen der Daten auf anderem Weg als über die Adresszeile. Völlig sicher machen kann man reine JavaScript-Programme aber nicht.

    Gruß, Don P

  2. @@Yogilein:

    nuqneH

    Meine Frage nun: Kann man das irgendwie unterbinden?

    Meine Tips für Fragende nun: Kann man die irgendwie überbieten?

    Qapla'

    --
    Gut sein ist edel. Andere lehren, gut zu sein, ist noch edler. Und einfacher.
    (Mark Twain)
  3. [latex]Mae  govannen![/latex]

    Ich habe unter Javascript ein paar Spiele geschrieben und habe (leider erst jetzt) bemerkt, dass man ganz einfach die Variablen über die Adresszeile des Browsers ändern kann. Man kann z.B. dadurch seine Punkte erhöhen.

    Meine Frage nun: Kann man das irgendwie unterbinden?

    Du könntest deinen Code komplett in eine Funktion einlagern, die nach der Initialisierung direkt aufgerufen wird. Dies kapselt die Variablen nach außen.

    (function () {  
    // hier dein Code  
    })();
    

    Stur lächeln und winken, Männer!
    Kai

    --
    Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
    in Richtung "Mess up the Web".(suit)
    SelfHTML-Forum-Stylesheet
    1. Hallo,

      (function () {

      // hier dein Code
      })();

        
      Das wirkt doch aber nicht gegen Änderunegn der Adresszeile in z.B. http://spiel.example.org?punkte=99, wenn der Spieler dann so spielen darf. wird.  
        
      FireBug hat auch kein Problem, dem Benutzer solch gekapselten Code zu zeigen und ihn ändern zu lassen.  
        
      Gruß, Don P  
      
      
      1. [latex]Mae  govannen![/latex]

        Hallo,

        (function () {

        // hier dein Code
        })();

        
        >   
        > Das wirkt doch aber nicht gegen Änderunegn der Adresszeile in z.B. http://spiel.example.org?punkte=99, wenn der Spieler dann so spielen darf. wird.  
          
        Das gilt aber ausschließlich für Spiele, die explizit dafür ausgelegt sind, Werte per Adresszeile übergeben zu bekommen. Eine Variable 'punkte' ändert man ansonsten dadurch nicht.  
          
        ~~~javascript
        var foo = 3;  
        (function () {  
          var bar = 2;  
        })();
        

        nun gib mal in der Adresszeile ein:

        javascript:alert(foo);foo=6;alert(foo);
        javascript:alert(bar);bar=5;alert(bar);

        bar ist nicht zugänglich[1], also kann auch per javascript:bar=5 geändert werden. javascript:foo=9 hingegen ändert den Wert. Und ich vermute, daß es genau darum (Änderung globaler Variablen) ging.

        Stur lächeln und winken, Männer!
        Kai

        --
        Dank Hixies Idiotenbande geschieht grade eben wieder ein Umdenken
        in Richtung "Mess up the Web".(suit)
        SelfHTML-Forum-Stylesheet
        1. Hallo,

          Das gilt aber ausschließlich für Spiele, die explizit dafür ausgelegt sind, Werte per Adresszeile übergeben zu bekommen.

          So habe ich's auch verstanden. Die Tipps für fragende wurden ja bekanntlich nicht beachtet.

          var foo = 3;

          (function () {
            var bar = 2;
          })();

          
          >   
          > nun gib mal in der Adresszeile ein:  
          >   
          > javascript:alert(foo);foo=6;alert(foo);  
          > javascript:alert(bar);bar=5;alert(bar);  
            
          Weia, wer macht denn sowas? Ich bin entsetzt... ;)  
          Aber stimmt, in dem Fall würde eine Kapselung nützen.  
            
          Ist halt trotzdem nicht 100% sicher, weil es ja Tools gibt, die den ganzen Code offenbaren, wobei man auch beliebig Daten ändern kann. Ich habe selber so eine Anwendung, die ich gern schützen würde gegen unbefugte Benutzung, weiß aber nicht wie. Wenn das JavaScript erst mal im Browser ist, hat man keine Möglichkeit mehr, das Abspeichern und unbefugte Verbreiten zu verhindern :(.  
            
          Gruß, Don P  
          
          
          1. Bis jetzt erst einmal Danke für die Antworten.

            Die Tipps für Fragende habe ich sehr wohl beachtet und dachte, dass meine Frage präzise genug ist.

            Aber ich will sie gerne noch ein wenig mehr erläutern:

            Ich habe einige Spiele in Javascript geschrieben.

            Alle Variablen werden in den Scripten selbst gesetzt.
            Es gibt globale Variablen, da ich mehrere Funktionen nutze.
            Die Funktionen werden auch innerhalb HTML aufgerufen (z.B. mit onclick). Dabei kann ich keine Variable übergeben, da sie an dieser Stelle unbekannt ist. Z.B. onclick="Spielzug(1,Punkte)"; funktioniert nicht. In diesem Beispiel müsste die Funktion Spielzug mit dem Wert 1 für das angeklickte Feld und der Variablen Punkte versorgt werden, da diese ausgewertet werden. Also muss ich wohl bei den globalen Variablen bleiben.

            Ein Spieler kann jetzt aber (von mir absolut ungewollt) über die Adresszeile seines Browsers die (globale) Variable Punkte ändern und somit das Spiel manipulieren. Und genau das möchte ich verhindern, weiß aber absolut nicht wie.

            LG
            Yogilein

            1. Hi,

              Ein Spieler kann jetzt aber (von mir absolut ungewollt) über die Adresszeile seines Browsers die (globale) Variable Punkte ändern und somit das Spiel manipulieren. Und genau das möchte ich verhindern, weiß aber absolut nicht wie.

              egal was Du machst, spätestens mit Tools wie Firebug lässt sich clientseitig alles ändern, was der Nutzer will.

              Cheatah

              --
              X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
              X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
              X-Will-Answer-Email: No
              X-Please-Search-Archive-First: Absolutely Yes
              1. egal was Du machst, spätestens mit Tools wie Firebug lässt sich clientseitig alles ändern, was der Nutzer will.

                Nur um des Widerspruchs willens:

                ~~~javascript var storage = {}

                Object.defineProperty(storage, "foo", {
                      "value" : 42,
                      "writable" : false,
                      "configurable" : false
                  })

            2. Hallo,

              Die Tipps für Fragende habe ich sehr wohl beachtet und dachte, dass meine Frage präzise genug ist.

              Nicht wirklich. Ohne eine einzige Zeile Code kann man nur raten, worum es genau geht.

              Es gibt globale Variablen, da ich mehrere Funktionen nutze.

              Das ist genau das Problem, denn

              Ein Spieler kann jetzt aber [..] über die Adresszeile seines Browsers die (globale) Variable Punkte ändern und somit das Spiel manipulieren.

              Dann verzichte halt auf globale Variablen, siehe oben. Das geht auch, wenn man "mehrere Funktionen" nutzt. Globale Variablen müssen nicht sein und sind immer irgendwie problematisch.

              Die Funktionen werden auch innerhalb HTML aufgerufen (z.B. mit onclick). Dabei kann ich keine Variable übergeben, da sie an dieser Stelle unbekannt ist. Z.B. onclick="Spielzug(1,Punkte)"; funktioniert nicht.

              Statt die Eventhandlerfunktionen direkt in HTML-Tags zu notieren, wie z.B. <button onclick="...">, kann man sie auch per Script zuweisen, d.h. etwas wie myButton.onclick = Spielzug(1,Punkte); funktioniert dann problemlos.

              Aber wie schon gesagt, JavaScript ist immer relativ unsicher. Auch ohne globale Variablen kann man von außen Manipulieren und den Handler-Funktionen einfach andere Werte übergeben, sogar über die Adresszeile, wenn man weiß wie. Ob sich der Aufwand also lohnt, extra alles umzuprogrammieren? So als Übung um zum Dazulernen vielleicht schon.

              Beim Spiel schummeln ist ohnehin eine Kinderei. Macht ja nicht wirklich Spass. Wertvolle Preise aussetzen kannst du so natürlich nicht.

              Gruß, Don P

              1. Hi,

                Statt die Eventhandlerfunktionen direkt in HTML-Tags zu notieren, wie z.B. <button onclick="...">, kann man sie auch per Script zuweisen

                ja, kann man - und das ist auch in vielen Fällen vorteilhaft.

                d.h. etwas wie myButton.onclick = Spielzug(1,Punkte); funktioniert dann problemlos.

                Was verstehst du unter "funktioniert"? Dein Beispielcode jedenfalls ruft die Funktion Spielzug() mit zwei Parametern auf (einer Konstanten und einem zum Zeitpunkt der Zuweisung aktuellen Variablenwert) und weist dann das Funktionsergebnis als Eventhandler zu. Das kann nicht das sein, was du wolltest.

                Vielleicht meintest du myButton.onclick = function() {Spielzug(1,Punkte);} - aber das hat auch den in diesem Fall unerwünschten Nebeneffekt, dass der zum Zeitpunkt der Zuweisung aktuelle Wert der Variablen Punkte in einer Closure eingeschlossen wird, und der Eventhandler somit nicht mit dem zum Zeitpunkt des Events gültigen Variablenwerts aufgerufen wird.
                Man möge mich korrigieren, wenn ich Unsinn verzapfe; die Scopes in Javascript erzeugen regelmäßig auch immer wieder Knoten in meinem Hirn.

                Aber wie schon gesagt, JavaScript ist immer relativ unsicher. Auch ohne globale Variablen kann man von außen Manipulieren

                Definitiv, ja. Und das führt uns zu der einzigen Erkenntnis: Wenn irgendetwas manipulationssicher sein soll, ist Javascript der falsche Ansatz.

                So long,
                 Martin

                --
                Dieser Satz wurde in mühsamer Kleinstarbeit aus einzelnen Wörtern zusammengesetzt.
                  (Hopsel)
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                1. Hallo,

                  d.h. etwas wie myButton.onclick = Spielzug(1,Punkte); funktioniert dann problemlos.

                  Was verstehst du unter "funktioniert"? Dein Beispielcode jedenfalls [...] kann nicht das sein, was du wolltest.

                  Vieleicht doch ;) Nein, nicht wirklich. "Funktioniert problemlos" hab' ich nur geschrieben, weil es hieß "funktioniert nicht".

                  Vielleicht meintest du myButton.onclick = function() {Spielzug(1,Punkte);}

                  Sowas, ja. Auch das mit der Konstanten hab' ich zu spät gesehen. Leider kann man ja hier seine Beiträge nachträglich nicht mehr editieren, und deswegen extra einen neuen absetzen...

                  Wenn irgendetwas manipulationssicher sein soll, ist Javascript der falsche Ansatz.

                  Stimmt, leider. Ich habe immer noch die leise Hoffnung, dass ich ein umfangreiches JS-Programm doch noch irgendwie so hinbekomme, dass es nur autorisierte User nutzen können, vielleicht indem ich ein paar unverzichtbare Kernfunktionen in ein Java-Applet auslagere oder sowas. Das ganze Ding umschreiben will aber nicht. Es geht mir nicht um eventuelle Manipulationen, sondern nur darum, das es nicht unbefugt äh unbezahlt zu benutzen ist und nicht einfach weiterzuverbreit werden kann.

                  Gruß, Don P

                2. Vielleicht meintest du myButton.onclick = function() {Spielzug(1,Punkte);} - aber das hat auch den in diesem Fall unerwünschten Nebeneffekt, dass der zum Zeitpunkt der Zuweisung aktuelle Wert der Variablen Punkte in einer Closure eingeschlossen wird, und der Eventhandler somit nicht mit dem zum Zeitpunkt des Events gültigen Variablenwerts aufgerufen wird.

                  Nein, das genaue Gegenteil ist der Fall!

                  Zur Terminologie siehe http://molily.de/javascript-core/.

                  Eine Closure konserviert nicht den Wert, den eine Variable einer äußeren Funktion zum Zeitpunkt des Erzeugens der Closure hat. Sie konserviert die Ausführungskontexte und damit die Variablenobjekte der äußeren Funktionen über deren Ausführung hinaus. Konservieren heißt hier nicht Einfrieren der Werte, sondern dass die Verfügbarkeit erhalten bleibt, also die Scope Chain dieselbe bleibt.

                  Über die Scope Chain sind also immer ein und dieselben »freien« Variablen erreichbar. Nach dem Erzeugen der Closure kann diese oder eine andere Closure die freien Variablen ändern, sodass jede der Closures auf den *geänderten* Wert Zugriff hat.

                  Andernfalls würde folgendes nicht gehen:

                  var module = (function äußerefunktion () {  
                     var priv = 0;  
                     return {  
                        inc : function closure1 () {  
                           priv++  
                        },  
                        print : function closure2 () {  
                           alert(priv);  
                        }  
                     };  
                  })();  
                    
                  module.print(); // 0  
                  module.inc();  
                  module.print(); // 1
                  

                  Wenn die Closures hier den *Wert* konservieren würden, den die Variable priv aus der äußeren Funktion zum Zeitpunkt des Erzeugens der Closure hätte, müsste beide Male 0 herauskommen.

                  Dass nicht der Fall ist, ist kein »unerwünschter Nebeneffekt«, sondern i.d.R. der Grund, warum man eine Closure anlegt: Nämlich private Objekte, die zwischen verschiedenen Funktionen geteilt und verändert werden – oben am Beispiel des Module Patterns demonstriert.

                  Die beiden Closures inc und print teilen sich über ihre Scope Chain den Zugriff auf denselben Ausführungskontext von äußerefunktion und damit auf die Variable priv. Damit können sie beide auf dieselbe Variable zugreifen und so miteinander kommunizieren.

                  Das kann natürlich zu Problemen führen, etwa mit Schleifen, siehe http://molily.de/javascript-core/#closures.

                  (function () {  
                     var aElems = document.getElementByTagName('a');  
                     for (var i = 0, l = aElements.length; i < l; i++) {  
                        aElems.onclick = function () {  
                           alert(i);  
                        };  
                     }  
                  })();
                  

                  Egal welches Element man anklickt, es wird immer dieselbe Variable ausgegeben. Diese hat nur einen Wert, nämlich aElements.length - 1, also der des letzten Schleifendurchlaufs.

                  Es gibt verschiedene Ansätze, diese Aufgabe zu lösen. Die universellste ist, mit jedem Schleifendurchlauf zwei Funktionen zu erzeugen, eine individuelle äußere Funktion, welche einen Parameter bekommt, der sich später nicht mehr ändert, sowie darin eine Closure. Das nennt sich Currying und ist auch mit Function.prototype.bind (ECMAScript 5) möglich:

                  (function () {  
                     function handler (i) {  
                        alert(i);  
                     }  
                     var aElems = document.getElementByTagName('a');  
                     for (var i = 0, l = aElements.length; i < l; i++) {  
                        var a = aElems[i];  
                        a.onclick = handler.bind(a, i);  
                     }  
                  })();
                  

                  Mathias

  4. Hi,

    Ich habe unter Javascript ein paar Spiele geschrieben und habe (leider erst jetzt) bemerkt, dass man ganz einfach die Variablen über die Adresszeile des Browsers ändern kann.

    erstaunlich. Auf welche Weise erzeugst und befüllst Du denn Deine Variablen, genauer gefragt wie kommen URL-Parameter bei Deinen Variablen ins Spiel?

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes