it-swarm.com.de

Wie deaktiviert Facebook die integrierten Entwicklertools des Browsers?

Offensichtlich werden die Entwickler-Tools aufgrund der jüngsten Betrügereien von Spam-Mails genutzt und sogar "gehackt". Facebook hat die Entwicklertools blockiert, und ich kann die Konsole nicht einmal verwenden.

Enter image description here

Wie haben sie das gemacht? Ein Stack Overflow-Beitrag behauptete, dass dies nicht möglich ist , aber Facebook hat sie als falsch erwiesen.

Gehen Sie einfach zu Facebook und öffnen Sie die Entwickler-Tools. Geben Sie einen Buchstaben in die Konsole ein. Diese Warnung wird angezeigt. Egal was Sie einsetzen, es wird nicht ausgeführt.

Wie ist das möglich?

Sie haben sogar die automatische Vervollständigung in der Konsole blockiert:

Enter image description here

1602

Ich bin ein Sicherheitsingenieur bei Facebook und das ist meine Schuld. Wir testen dies für einige Benutzer, um festzustellen, ob es einige Angriffe verlangsamen kann, bei denen Benutzer dazu verleitet werden, (böswilligen) JavaScript-Code in die Browserkonsole einzufügen.

Nur um klar zu sein: Der Versuch, Hacker clientseitig zu blockieren, ist eine schlechte Idee im Allgemeinen; Dies dient zum Schutz vor einem bestimmten Social-Engineering-Angriff .

Wenn Sie in der Testgruppe gelandet sind und sich darüber ärgern, entschuldigen Sie bitte. Ich habe versucht, die alte Opt-Out-Seite (jetzt Hilfeseite ) so einfach wie möglich zu gestalten, während ich immer noch beängstigend genug war, um mindestens einige der zu stoppen die Opfer.

Der eigentliche Code ist ziemlich ähnlich zu @ joeldixon66's link ; Unseres ist ohne guten Grund etwas komplizierter.

Chrome schließt den gesamten Konsolencode ein

with ((console && console._commandLineAPI) || {}) {
  <code goes here>
}

... so definiert die Seite console._commandLineAPI neu, um zu werfen:

Object.defineProperty(console, '_commandLineAPI',
   { get : function() { throw 'Nooo!' } })

Das ist nicht genug (probiere es aus!) , aber das ist der Haupttrick.


Nachwort: Das Team von Chrome entschied, dass das Besiegen der Konsole durch JS auf der Benutzerseite ein Fehler war und das Problem wurde behoben , wodurch diese Technik ungültig wurde. Anschließend wurde Benutzer vor self-xss schützen um zusätzlichen Schutz erweitert.

2384
Alf

Ich habe das Console Buster-Skript von Facebook mithilfe der Chrome-Entwicklertools gefunden. Hier ist das Skript mit geringfügigen Änderungen zur besseren Lesbarkeit. Ich habe die Teile entfernt, die ich nicht verstehen konnte:

Object.defineProperty(window, "console", {
    value: console,
    writable: false,
    configurable: false
});

var i = 0;
function showWarningAndThrow() {
    if (!i) {
        setTimeout(function () {
            console.log("%cWarning message", "font: 2em sans-serif; color: yellow; background-color: red;");
        }, 1);
        i = 1;
    }
    throw "Console is disabled";
}

var l, n = {
        set: function (o) {
            l = o;
        },
        get: function () {
            showWarningAndThrow();
            return l;
        }
    };
Object.defineProperty(console, "_commandLineAPI", n);
Object.defineProperty(console, "__commandLineAPI", n);

Dadurch schlägt die automatische Vervollständigung der Konsole automatisch fehl, während Anweisungen, die in Console eingegeben werden, nicht ausgeführt werden können (die Ausnahme wird protokolliert).

Verweise:

78
Salman A

Ich konnte es nicht auf jeder Seite auslösen. Eine robustere Version davon würde es tun:

window.console.log = function(){
    console.error('The developer console is temp...');
    window.console.log = function() {
        return false;
    }
}

console.log('test');

So gestalten Sie die Ausgabe: Farben in der JavaScript-Konsole

Edit Denken @ joeldixon66 hat die richtige Idee: JavaScript-Ausführung von Konsole aus deaktivieren «::: KSpace :::

38
Will

Neben der Neudefinition von console._commandLineAPI gibt es einige andere Möglichkeiten, um in InjectedScriptHost auf WebKit-Browsern einzudringen und die Auswertung von Ausdrücken zu verhindern oder zu ändern, die in die Entwicklerkonsole eingegeben wurden.

Bearbeiten:

Chrome hat dies in einer früheren Version behoben. - das muss vor Februar 2015 gewesen sein, als ich damals den Gist erstellt habe

Also hier ist eine andere Möglichkeit. Diesmal haken wir uns eine Ebene höher direkt in InjectedScript ein und nicht in InjectedScriptHost, im Gegensatz zur vorherigen Version.

Das ist ganz nett, denn Sie können den Affen-Patch InjectedScript._evaluateAndWrap direkt ausführen, anstatt sich auf InjectedScriptHost.evaluate verlassen zu müssen, da Sie so genauer steuern können, was passieren soll.

Eine weitere interessante Sache ist, dass wir das interne Ergebnis abfangen können, wenn ein Ausdruck ausgewertet wird, und anstelle des normalen Verhaltens das an den Benutzer zurückgeben.

Hier ist der Code, der genau das tut und das interne Ergebnis zurückgibt, wenn ein Benutzer etwas in der Konsole auswertet.

var is;
Object.defineProperty(Object.prototype,"_lastResult",{
   get:function(){
       return this._lR;
   },
   set:function(v){
       if (typeof this._commandLineAPIImpl=="object") is=this;
       this._lR=v;
   }
});
setTimeout(function(){
   var ev=is._evaluateAndWrap;
   is._evaluateAndWrap=function(){
       var res=ev.apply(is,arguments);
       console.log();
       if (arguments[2]==="completion") {
           //This is the path you end up when a user types in the console and autocompletion get's evaluated

           //Chrome expects a wrapped result to be returned from evaluateAndWrap.
           //You can use `ev` to generate an object yourself.
           //In case of the autocompletion chrome exptects an wrapped object with the properties that can be autocompleted. e.g.;
           //{iGetAutoCompleted: true}
           //You would then go and return that object wrapped, like
           //return ev.call (is, '', '({test:true})', 'completion', true, false, true);
           //Would make `test` pop up for every autocompletion.
           //Note that syntax as well as every Object.prototype property get's added to that list later,
           //so you won't be able to exclude things like `while` from the autocompletion list,
           //unless you wou'd find a way to rewrite the getCompletions function.
           //
           return res; //Return the autocompletion result. If you want to break that, return nothing or an empty object
       } else {
           //This is the path where you end up when a user actually presses enter to evaluate an expression.
           //In order to return anything as normal evaluation output, you have to return a wrapped object.

           //In this case, we want to return the generated remote object. 
           //Since this is already a wrapped object it would be converted if we directly return it. Hence,
           //`return result` would actually replicate the very normal behaviour as the result is converted.
           //to output what's actually in the remote object, we have to stringify it and `evaluateAndWrap` that object again.`
           //This is quite interesting;
           return ev.call (is, null, '(' + JSON.stringify (res) + ')', "console", true, false, true)
       }
   };
},0);

Es ist ein bisschen ausführlich, aber ich dachte, ich würde ein paar Kommentare hinzufügen

Wenn ein Benutzer beispielsweise [1,2,3,4] auswertet, wird normalerweise die folgende Ausgabe erwartet:

enter image description here

Nach dem Monkeypatching von InjectedScript._evaluateAndWrap, das denselben Ausdruck auswertet, wird die folgende Ausgabe ausgegeben:

enter image description here

Wie Sie sehen, ist der kleine linke Pfeil, der die Ausgabe anzeigt, noch vorhanden, aber diesmal erhalten wir ein Objekt. Als Ergebnis des Ausdrucks wird das Array [1,2,3,4] als Objekt mit allen beschriebenen Eigenschaften dargestellt.

Ich empfehle, diesen und jenen Ausdruck auszuwerten, einschließlich jener, die Fehler erzeugen. Das ist ziemlich interessant.

Schauen Sie sich außerdem das Objekt is - InjectedScriptHost - an. Es bietet einige Methoden, mit denen Sie spielen und sich einen Einblick in die Interna des Inspektors verschaffen können.

Natürlich können Sie alle diese Informationen abfangen und trotzdem das ursprüngliche Ergebnis an den Benutzer zurückgeben.

Ersetzen Sie einfach die return-Anweisung im else-Pfad durch eine console.log (res) nach einem return res. Dann würden Sie mit den folgenden enden.

enter image description here

Ende der Bearbeitung


Dies ist die vorherige Version, die von Google behoben wurde. Daher kein möglicher Weg mehr.

Eine davon ist das Einhängen in Function.prototype.call

Chrome wertet den eingegebenen Ausdruck aus, indem call seine Bewertungsfunktion mit InjectedScriptHost als thisArg bewertet.

var result = evalFunction.call(object, expression);

Vor diesem Hintergrund können Sie auf das thisArg von call als evaluate warten und einen Verweis auf das erste Argument (InjectedScriptHost) erhalten.

if (window.URL) {
    var ish, _call = Function.prototype.call;
    Function.prototype.call = function () { //Could be wrapped in a setter for _commandLineAPI, to redefine only when the user started typing.
        if (arguments.length > 0 && this.name === "evaluate" && arguments [0].constructor.name === "InjectedScriptHost") { //If thisArg is the evaluate function and the arg0 is the ISH
            ish = arguments[0];
            ish.evaluate = function (e) { //Redefine the evaluation behaviour
                throw new Error ('Rejected evaluation of: \n\'' + e.split ('\n').slice(1,-1).join ("\n") + '\'');
            };
            Function.prototype.call = _call; //Reset the Function.prototype.call
            return _call.apply(this, arguments);  
        }
    };
}

Sie könnten z.B. Wirf einen Fehler, dass die Bewertung abgelehnt wurde.

enter image description here

Hier ist ein Beispiel , bei dem der eingegebene Ausdruck an einen CoffeeScript-Compiler übergeben wird, bevor er an die Funktion evaluate übergeben wird.

28
Moritz Roessler

Netflix implementiert auch diese Funktion

(function() {
    try {
        var $_console$$ = console;
        Object.defineProperty(window, "console", {
            get: function() {
                if ($_console$$._commandLineAPI)
                    throw "Sorry, for security reasons, the script console is deactivated on netflix.com";
                return $_console$$
            },
            set: function($val$$) {
                $_console$$ = $val$$
            }
        })
    } catch ($ignore$$) {
    }
})();

Sie überschreiben einfach console._commandLineAPI, um einen Sicherheitsfehler zu melden.

22
Fizer Khan

Dies ist tatsächlich möglich, da Facebook es konnte. Nun, nicht die eigentlichen Webentwickler-Tools, sondern die Ausführung von Javascript in der Konsole.

Siehe dazu: Wie deaktiviert Facebook die integrierten Entwicklertools des Browsers?

Dies macht jedoch nicht viel aus, da es andere Möglichkeiten gibt, diese Art von clientseitiger Sicherheit zu umgehen.

Wenn Sie sagen, dass es clientseitig ist, geschieht dies außerhalb der Kontrolle des Servers, sodass Sie nicht viel dagegen tun können. Wenn Sie sich fragen, warum Facebook dies immer noch tut, ist dies nicht unbedingt eine Sicherheitsmaßnahme, sondern um normale Benutzer, die kein Javascript kennen, vor dem Ausführen von Code (der nicht lesen kann) in der Konsole zu schützen. Dies ist bei Websites üblich, die einen Auto-Liker-Service oder andere Facebook-Funktions-Bots versprechen, nachdem Sie das getan haben, worauf Sie gebeten werden. In den meisten Fällen erhalten Sie einen kleinen Ausschnitt von Javascript, um die Konsole auszuführen.

Wenn Sie nicht so viele Nutzer wie Facebook haben, glaube ich nicht, dass Sie das tun müssen, was Facebook tut.

Selbst wenn Sie Javascript in der Konsole deaktivieren, ist es möglich, Javascript über die Adressleiste auszuführen.

 enter image description here

 enter image description here

und wenn der Browser Javascript in der Adressleiste deaktiviert (wenn Sie in Google Chrome Code in die Adressleiste einfügen, wird der Ausdruck "javascript:" gelöscht). Das Einfügen von Javascript in einen der Links über das inspect-Element ist weiterhin möglich.

Überprüfen Sie den Anker:

 enter image description here

Einfügen von Code in href:

 enter image description here

 enter image description here

 enter image description here

Das Endergebnis ist die serverseitige Validierung. Die Sicherheit sollte zuerst und dann die clientseitige Überprüfung erfolgen.

20
Jomar Sevillejo

Chrome hat sich sehr verändert, seit Facebook die Konsole deaktivieren konnte ... 

Seit März 2017 funktioniert das nicht mehr. 

Am besten können Sie einige der Konsolenfunktionen deaktivieren. Beispiel:

if(!window.console) window.console = {};
var methods = ["log", "debug", "warn", "info", "dir", "dirxml", "trace", "profile"];
for(var i=0;i<methods.length;i++){
    console[methods[i]] = function(){};
}
7
Alpha2k

Mein einfacher Weg, aber es kann für weitere Variationen dieses Themas hilfreich sein. Listen Sie alle Methoden auf und ändern Sie sie in nutzlos.

  Object.getOwnPropertyNames(console).filter(function(property) {
     return typeof console[property] == 'function';
  }).forEach(function (verb) {
     console[verb] =function(){return 'Sorry, for security reasons...';};
  });
6
Dusan Krstic

Devtools fügt intern ein IIFE mit dem Namen getCompletions in die Seite ein, das aufgerufen wird, wenn eine Taste in der Devtools-Konsole gedrückt wird. 

Betrachtet man die Quelle dieser Funktion , verwendet sie einige globale Funktionen, die überschrieben werden können.

Mit dem Konstruktor Error ist es möglich, den Aufrufstack abzurufen, der beim Aufruf von Devtools getCompletions enthält.


Beispiel:

const disableDevtools = callback => {
  const original = Object.getPrototypeOf;

  Object.getPrototypeOf = (...args) => {
    if (Error().stack.includes("getCompletions")) callback();
    return original(...args);
  };
};

disableDevtools(() => {
  console.error("devtools has been disabled");

  while (1);
});

3
samdd

eine einfache Lösung!

setInterval(()=>console.clear(),1500);

Ich würde den Weg gehen von:

Object.defineProperty(window, 'console', {
  get: function() {

  },
  set: function() {

  }
});
0
Zibri

Dies ist keine Sicherheitsmaßnahme, wenn schwacher Code unbeaufsichtigt gelassen werden soll. Sie sollten immer eine dauerhafte Lösung für schwachen Code erhalten und Ihre Websites ordnungsgemäß sichern, bevor Sie diese Strategie implementieren.

Meines Wissens nach wäre das beste Werkzeug das Hinzufügen mehrerer Javascript-Dateien, die die Integrität der Seite einfach durch Erneuern oder Ersetzen des Inhalts auf normale Werte zurückstellen. Das Deaktivieren dieses Entwicklertools wäre nicht die beste Idee, da das Umgehen immer in Frage gestellt wird, da der Code Teil des Browsers und kein Server-Rendering ist. Daher könnte er geknackt werden. 

Wenn Sie js file one nach <element>-Änderungen an wichtigen Elementen suchen und js file two und js file three prüfen, ob diese Datei pro Zeitraum vorhanden ist, haben Sie innerhalb der Periode eine vollständige Wiederherstellung der Integrität auf der Seite. 

Nehmen wir ein Beispiel der 4 Dateien und zeigen Ihnen, was ich meine. 

index.html

   <!DOCTYPE html>
   <html>
   <head id="mainhead">
   <script src="ks.js" id="ksjs"></script>
   <script src="mainfile.js" id="mainjs"></script>
   <link rel="stylesheet" href="style.css" id="style">
   <meta id="meta1" name="description" content="Proper mitigation against script kiddies via Javascript" >
   </head>
   <body>
   <h1 id="heading" name="dontdel" value="2">Delete this from console and it will refresh. If you change the name attribute in this it will also refresh. This is mitigating an attack on attribute change via console to exploit vulnerabilities. You can even try and change the value attribute from 2 to anything you like. If This script says it is 2 it should be 2 or it will refresh. </h1>
   <h3>Deleting this wont refresh the page due to it having no integrity check on it</h3>

   <p>You can also add this type of error checking on meta tags and add one script out of the head tag to check for changes in the head tag. You can add many js files to ensure an attacker cannot delete all in the second it takes to refresh. Be creative and make this your own as your website needs it. 
   </p>

   <p>This is not the end of it since we can still enter any tag to load anything from everywhere (Dependent on headers etc) but we want to prevent the important ones like an override in meta tags that load headers. The console is designed to edit html but that could add potential html that is dangerous. You should not be able to enter any meta tags into this document unless it is as specified by the ks.js file as permissable. <br>This is not only possible with meta tags but you can do this for important tags like input and script. This is not a replacement for headers!!! Add your headers aswell and protect them with this method.</p>
   </body>
   <script src="ps.js" id="psjs"></script>
   </html>

mainfile.js

   setInterval(function() {
   // check for existence of other scripts. This part will go in all other files to check for this file aswell. 
   var ksExists = document.getElementById("ksjs"); 
   if(ksExists) {
   }else{ location.reload();};

   var psExists = document.getElementById("psjs");
   if(psExists) {
   }else{ location.reload();};

   var styleExists = document.getElementById("style");
   if(styleExists) {
   }else{ location.reload();};


   }, 1 * 1000); // 1 * 1000 milsec

ps.js

   /*This script checks if mainjs exists as an element. If main js is not existent as an id in the html file reload!You can add this to all js files to ensure that your page integrity is perfect every second. If the page integrity is bad it reloads the page automatically and the process is restarted. This will blind an attacker as he has one second to disable every javascript file in your system which is impossible.

   */

   setInterval(function() {
   // check for existence of other scripts. This part will go in all other files to check for this file aswell. 
   var mainExists = document.getElementById("mainjs"); 
   if(mainExists) {
   }else{ location.reload();};

   //check that heading with id exists and name tag is dontdel.
   var headingExists = document.getElementById("heading"); 
   if(headingExists) {
   }else{ location.reload();};
   var integrityHeading = headingExists.getAttribute('name');
   if(integrityHeading == 'dontdel') {
   }else{ location.reload();};
   var integrity2Heading = headingExists.getAttribute('value');
   if(integrity2Heading == '2') {
   }else{ location.reload();};
   //check that all meta tags stay there
   var meta1Exists = document.getElementById("meta1"); 
   if(meta1Exists) {
   }else{ location.reload();};

   var headExists = document.getElementById("mainhead"); 
   if(headExists) {
   }else{ location.reload();};

   }, 1 * 1000); // 1 * 1000 milsec

ks.js

   /*This script checks if mainjs exists as an element. If main js is not existent as an id in the html file reload! You can add this to all js files to ensure that your page integrity is perfect every second. If the page integrity is bad it reloads the page automatically and the process is restarted. This will blind an attacker as he has one second to disable every javascript file in your system which is impossible.

   */

   setInterval(function() {
   // check for existence of other scripts. This part will go in all other files to check for this file aswell. 
   var mainExists = document.getElementById("mainjs"); 
   if(mainExists) {
   }else{ location.reload();};
   //Check meta tag 1 for content changes. meta1 will always be 0. This you do for each meta on the page to ensure content credibility. No one will change a meta and get away with it. Addition of a meta in spot 10, say a meta after the id="meta10" should also be covered as below.
   var x = document.getElementsByTagName("meta")[0];
   var p = x.getAttribute("name");
   var s = x.getAttribute("content");
   if (p != 'description') {
   location.reload();
   }
   if ( s != 'Proper mitigation against script kiddies via Javascript') {
   location.reload();
   }
   // This will prevent a meta tag after this meta tag @ id="meta1". This prevents new meta tags from being added to your pages. This can be used for scripts or any tag you feel is needed to do integrity check on like inputs and scripts. (Yet again. It is not a replacement for headers to be added. Add your headers aswell!)
   var lastMeta = document.getElementsByTagName("meta")[1];
   if (lastMeta) {
   location.reload();
   }
   }, 1 * 1000); // 1 * 1000 milsec

style.css

Jetzt wird gezeigt, dass es auch für alle Dateien und Tags funktioniert

   #heading {
   background-color:red;
   }

Wenn Sie alle diese Dateien zusammenstellen und das Beispiel erstellen, wird die Funktion dieser Maßnahme angezeigt. Dies verhindert einige unvorhergesehene Injektionen, falls Sie es bei allen wichtigen Elementen in Ihrer Indexdatei korrekt implementieren, insbesondere wenn Sie mit PHP arbeiten.

Warum ich Reload gewählt habe, anstatt auf den normalen Wert pro Attribut zurückzukehren, ist die Tatsache, dass einige Angreifer einen anderen Teil der Website bereits konfiguriert haben und bereit sind, wodurch der Code verringert wird. Durch das Nachladen wird die harte Arbeit des Angreifers entfernt, und er wird wahrscheinlich irgendwo leichter spielen.

Noch ein Hinweis: Dies kann zu einer Menge Code werden, halten Sie ihn also sauber und fügen Sie Definitionen hinzu, um sie in Zukunft leichter zu bearbeiten. Stellen Sie auch die Sekunden auf Ihre bevorzugte Menge ein, wie dies 1-Sekunden-Intervalle auf großen Seiten bedeuten könnten haben drastische Auswirkungen auf ältere Computer, die Ihre Besucher möglicherweise verwenden

0
user9374996