Pregunta ¿Cómo deshabilita Facebook las herramientas de desarrollo integradas del navegador?


Aparentemente, debido a las estafas recientes, las personas explotan las herramientas de desarrollador para publicar correo no deseado e incluso para "piratear" cuentas. Facebook ha bloqueado las herramientas de desarrollador, y ni siquiera puedo usar la consola.

Enter image description here

¿Cómo hicieron eso? Una publicación de Stack Overflow afirmó que no es posible, pero Facebook ha demostrado que están equivocados.

Simplemente vaya a Facebook y abra las herramientas de desarrollador, escriba un carácter en la consola y aparecerá esta advertencia. No importa lo que pongas, no se ejecutará.

¿Cómo es esto posible?

Incluso bloquearon el autocompletado en la consola:

Enter image description here


1560
2018-02-11 03:42


origen


Respuestas:


Soy un ingeniero de seguridad en Facebook y esto es mi culpa. Estamos probando esto para algunos usuarios para ver si puede ralentizar algunos ataques en los que se engaña a los usuarios para que peguen (malicioso) el código JavaScript en la consola del navegador.

Para ser claros: tratar de bloquear a los hackers del lado del cliente es una mala idea en general; esto es para proteger contra un ataque específico de ingeniería social.

Si terminaste en el grupo de prueba y estás molesto por esto, lo siento. Traté de hacer la vieja página de exclusión (ahora pagina de ayuda) lo más simple posible sin dejar de ser lo suficientemente aterrador como para detener al menos algunos de las víctimas.

El código real es bastante similar a Enlace de @ joeldixon66; la nuestra es un poco más complicada sin una buena razón.

Chrome ajusta todo el código de la consola en

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

... por lo que el sitio redefine console._commandLineAPI tirar:

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

Esto es no es suficiente (¡pruébalo!), pero ese es el truco principal.


Epílogo: El equipo de Chrome decidió que derrotar a la consola de JS del lado del usuario era un error y corrigió el problema, haciendo que esta técnica no sea válida. Luego, se agregó protección adicional a proteger a los usuarios de self-xss.


2281
2018-02-11 05:33



Localicé la secuencia de comandos del buster de la consola de Facebook con las herramientas de desarrollo de Chrome. Aquí está la secuencia de comandos con cambios menores para la legibilidad. He eliminado los bits que no pude entender:

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);

Con esto, la autocompletación de la consola falla silenciosamente, mientras que las instrucciones escritas en la consola no se ejecutarán (la excepción se registrará).

Referencias


72
2018-02-15 08:16



No pude lograr que activara eso en ninguna página. Una versión más robusta de esto lo haría:

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

console.log('test');

Para diseñar el resultado: Colores en la consola de JavaScript

Editar Pensando @ joeldixon66 tiene la idea correcta: Deshabilitar la ejecución de JavaScript desde la consola «::: KSpace :::


36
2018-02-11 04:02



Además de redefinir console._commandLineAPI, hay otras formas de acceder a InjectedScriptHost en los navegadores WebKit, para evitar o modificar la evaluación de las expresiones ingresadas en la consola del desarrollador.

Editar:

Chrome ha solucionado esto en una versión anterior. - que debe haber sido antes de febrero de 2015, ya que creé la esencia en ese momento 

Entonces aquí hay otra posibilidad. Esta vez nos enganchamos, un nivel superior, directamente en InjectedScript más bien que InjectedScriptHost a diferencia de la versión anterior.

Lo cual es bueno, ya que puedes directamente el parche de mono InjectedScript._evaluateAndWrap en lugar de tener que depender de InjectedScriptHost.evaluate ya que eso te da un control más detallado sobre lo que debería suceder.

Otra cosa bastante interesante es que podemos interceptar el resultado interno cuando se evalúa una expresión y devolver eso para el usuario en lugar del comportamiento normal.

Aquí está el código, que hace exactamente eso, devuelve el resultado interno cuando un usuario evalúa algo en la consola.

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 un poco detallado, pero pensé en ponerle algunos comentarios

Entonces, normalmente, si un usuario, por ejemplo, evalúa [1,2,3,4] esperarías la siguiente salida:

enter image description here 

Después de monkeypatching InjectedScript._evaluateAndWrap evaluando la misma expresión, da el siguiente resultado:

enter image description here

Como puede ver, la pequeña flecha izquierda, que indica la salida, todavía está allí, pero esta vez tenemos un objeto. Donde el resultado de la expresión, la matriz [1,2,3,4] se representa como un objeto con todas sus propiedades descritas.

Recomiendo tratar de evaluar esta y esa expresión, incluidas las que generan errores. Es bastante interesante.

Además, eche un vistazo a la is  - InjectedScriptHost - objeto. Proporciona algunos métodos para jugar y obtener un poco de información sobre las funciones internas del inspector.

Por supuesto, puede interceptar toda esa información y aún así devolver el resultado original al usuario.

Simplemente reemplace la declaración return en la ruta else por un console.log (res) siguiendo un return res. Entonces terminarías con lo siguiente.

enter image description here 

Fin de Editar 


Esta es la versión anterior que fue corregida por Google. Por lo tanto, no es una forma posible más.

Uno de ellos está enganchándose en Function.prototype.call

Chrome evalúa la expresión ingresada por calling su función eval con InjectedScriptHost como thisArg


25
2018-02-19 14:49



Netflix también implementa esta característica

(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$$) {
    }
})();

Ellos simplemente anulan console._commandLineAPI lanzar un error de seguridad


19
2018-03-06 06:20



Esto es realmente posible ya que Facebook fue capaz de hacerlo. Bueno, no las herramientas reales de desarrollo web sino la ejecución de Javascript en la consola.

Mira esto: ¿Cómo deshabilita Facebook las herramientas de desarrollo integradas del navegador?

Esto realmente no hará mucho, ya que hay otras formas de eludir este tipo de seguridad del lado del cliente.

Cuando dice que es del lado del cliente, sucede fuera del control del servidor, por lo que no hay mucho que pueda hacer al respecto. Si se pregunta por qué Facebook todavía hace esto, esto no es realmente para seguridad, sino para proteger a los usuarios normales que no saben javascript de ejecutar código (que no saben cómo leer) en la consola. Esto es común para los sitios que prometen un servicio de autosuficiencia u otros bots de funcionalidades de Facebook después de hacer lo que le piden que haga, donde en la mayoría de los casos, le dan un fragmento de javascript para ejecutar en la consola.

Si no tienes tantos usuarios como Facebook, entonces no creo que haya necesidad de hacer lo que Facebook está haciendo.

Incluso si deshabilita Javascript en la consola, aún es posible ejecutar javascript a través de la barra de direcciones.

enter image description here

enter image description here

y si el navegador deshabilita javascript en la barra de direcciones, (cuando pega código en la barra de direcciones en Google Chrome, elimina la frase 'javascript:') aún es posible pegar javascript en uno de los enlaces mediante el elemento de inspección.

Inspeccione el anclaje:

enter image description here

Pegar el código en href:

enter image description here

enter image description here

enter image description here

La línea de fondo es la validación del lado del servidor y la seguridad debe ser primero, luego hacer después del lado del cliente.


18
2017-11-05 00:57



Chrome ha cambiado mucho desde los tiempos en que Facebook podía deshabilitar la consola ...

Según marzo de 2017, esto ya no funciona.

Lo mejor que puede hacer es desactivar algunas de las funciones de la consola, por ejemplo:

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(){};
}

5
2018-03-12 12:44



Mi manera simple, pero puede ayudar a otras variaciones sobre este tema. Enumera todos los métodos y cámbialos por inútiles.

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

3
2017-11-18 22:29



Esta no es una medida de seguridad para que el código débil quede desatendido. Siempre obtenga una solución permanente al código débil y asegure sus sitios web de manera adecuada antes de implementar esta estrategia

La mejor herramienta, de acuerdo con mi conocimiento, sería agregar varios archivos de JavaScript que simplemente cambien la integridad de la página a normal al actualizar o reemplazar el contenido. Deshabilitar esta herramienta de desarrollador no sería la mejor idea, ya que la derivación siempre está en cuestión, ya que el código es parte del navegador y no una representación del servidor, por lo tanto, se podría descifrar.

En caso tuvieses js file one verificando para <element> cambios en elementos importantes y js file two y js file three verificando que este archivo exista por período, se restaurará la integridad completa en la página dentro del período.

Tomemos un ejemplo de los 4 archivos y le mostraremos lo que quiero decir.

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

Ahora esto es solo para mostrar que también funciona en todos los archivos y etiquetas

   #heading {
   background-color:red;
   }

Si junta todos estos archivos y crea el ejemplo, verá la función de esta medida. Esto evitará algunas inyecciones imprevistas si las implementa correctamente en todos los elementos importantes en su archivo de índice, especialmente cuando trabaja con PHP.

Por qué elegí volver a cargar en lugar de cambiar de nuevo al valor normal por atributo es el hecho de que algunos atacantes podrían tener otra parte del sitio web ya configurada y lista, y disminuye el monto del código. La recarga eliminará todo el trabajo duro del atacante y es probable que vaya a jugar a un lugar más fácil.

Otra nota: Esto podría convertirse en una gran cantidad de código, así que mantenlo limpio y asegúrate de agregar definiciones al lugar al que pertenecen para facilitar las modificaciones en el futuro. También configure los segundos en su cantidad preferida ya que los intervalos de 1 segundo en páginas grandes podrían tener efectos drásticos en computadoras más antiguas que sus visitantes podrían estar usando


0
2018-03-04 03:16