Jak Facebook wyłącza zintegrowane narzędzia programistyczne przeglądarki?

Więc najwyraźniej z powodu ostatnich oszustw, narzędzia programistyczne są wykorzystywane przez ludzi do publikowania spamu, a nawet używane do "hakowania" kont. Facebook zablokował narzędzia programistyczne, a ja nie mogę nawet korzystać z konsoli.

Tutaj wpisz opis obrazka

Jak oni to zrobili?? jeden post o przepełnieniu stosu twierdził, że nie jest to możliwe , ale Facebook udowodnił, że się myli.

Wystarczy wejść na Facebook i otworzyć narzędzia programistyczne, wpisać jedną postać do konsoli, a to pojawia się Ostrzeżenie. Bez względu na to, co włożysz, nie zostanie stracony.

Jak to możliwe?

Zablokowali nawet autouzupełnianie w konsoli:

Tutaj wpisz opis obrazka

Author: Community, 2014-02-11

12 answers

Jestem inżynierem bezpieczeństwa w Facebook i to moja wina. Testujemy to dla niektórych użytkowników, aby sprawdzić, czy może to spowolnić niektóre ataki, w których użytkownicy są oszukiwani w wklejaniu (złośliwego) kodu JavaScript do konsoli przeglądarki.

Żeby było jasne: próba zablokowania hakerów po stronie klienta jest ogólnie złym pomysłem; ma to na celu ochronę przed specyficznym atakiem inżynierii społecznej .

Jeśli skończyłeś w grupie testowej i jesteś tym zdenerwowany, przepraszam. Próbowałem zrobić stara strona opt-out (teraz strona pomocy) tak prosta, jak to możliwe, a jednocześnie wystarczająco przerażająca, aby zatrzymać przynajmniej niektóre ofiar.

Rzeczywisty kod jest dość podobny do @joeldixon66 ' s link ; nasz jest trochę bardziej skomplikowany bez dobrego powodu.

Chrome otacza cały kod konsoli

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

... więc strona redefiniuje console._commandLineAPI do wyrzucenia:

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

To jest za mało (spróbuj!) , ale to główna trick.


Epilogue: zespół Chrome zdecydował, że pokonanie konsoli od strony użytkownika JS było błędem i Naprawiono problem , przez co ta technika była nieważna. Następnie dodano dodatkową ochronę do chroniącą użytkowników przed self-xss .

 2465
Author: Alf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:29

Zlokalizowałem skrypt Facebook console buster przy użyciu narzędzi programistycznych Chrome. Oto skrypt z niewielkimi zmianami czytelności. Usunąłem bity, których nie mogłem zrozumieć:

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

W tym przypadku autouzupełnianie konsoli nie powiedzie się po cichu, podczas gdy polecenia wpisane w konsoli nie będą wykonywane (wyjątkiem będzie zalogowany).

Bibliografia:

 95
Author: Salman A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-15 14:58:35

Nie mogłem tego uruchomić na żadnej stronie. Bardziej solidna wersja tego by to zrobiła:

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

console.log('test');

Aby wystylizować wyjście: kolory w konsoli JavaScript

Edit Thinking @ joeldixon66 has the right idea: Disable JavaScript execution from console"::: KSpace :::

 48
Author: Will,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:59

Poza przedefiniowaniem console._commandLineAPI, istnieje kilka innych sposobów włamania się do InjectedScriptHost w przeglądarkach WebKit, aby zapobiec lub zmienić ocenę wyrażeń wprowadzonych do konsoli dewelopera.

Edit:

Chrome naprawił to w poprzednim wydaniu. - który musiał być przed lutym 2015 roku, jak stworzyłem gist w tym czasie

Więc jest jeszcze jedna możliwość. Tym razem wpinamy się, poziom wyżej, bezpośrednio do InjectedScript, a nie InjectedScriptHost w przeciwieństwie do poprzedniej wersji.

Co jest całkiem miłe, ponieważ można bezpośrednio monkey patch InjectedScript._evaluateAndWrap zamiast polegać na InjectedScriptHost.evaluate, ponieważ daje to bardziej drobnoziarnistą kontrolę nad tym, co powinno się wydarzyć.

Kolejną ciekawą rzeczą jest to, że możemy przechwycić wewnętrzny wynik podczas oceniania wyrażenia i zwrócić je użytkownikowi zamiast normalnego zachowania.

Oto kod, który robi dokładnie to, zwraca wewnętrzny wynik, gdy użytkownik ocenia coś w konsoli.

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

to trochę gadatliwe, ale myślałem, że dodałem do niego kilka komentarzy

Więc normalnie, jeśli użytkownik, na przykład, ocenia [1,2,3,4] można oczekiwać następującego wyniku:

Tutaj wpisz opis obrazka

Po ocenie monkeypatchingu InjectedScript._evaluateAndWrap to samo wyrażenie daje następujące wyjście:

Tutaj wpisz opis obrazka

Jak widzisz mała strzałka w lewo, wskazująca wyjście, nadal tam jest, ale tym razem mamy obiekt. Gdzie wynik wyrażenia, tablica [1,2,3,4] jest reprezentowana jako obiekt z opisanymi wszystkimi jego właściwościami.

Zalecam próbę oceny tego i tamtego wyrażenia, w tym tych, które generują błędy. To dość interesujące.

Dodatkowo, spójrz na is - InjectedScriptHost - obiekt. Zapewnia kilka metod zabawy i trochę wglądu w wewnętrzne funkcje Inspektora.

Oczywiście, można przechwycić wszystkie te informacje i nadal zwraca oryginalny wynik do użytkownika.

Po prostu zamień instrukcję return w ścieżce else na console.log (res) po return res. Wtedy skończyłbyś z następującymi.

Tutaj wpisz opis obrazka

koniec edycji


To jest poprzednia wersja, która została naprawiona przez Google. Stąd już nie jest to możliwe.

jednym z nich jest podłączenie do Function.prototype.call

Chrome ocenia wprowadzone wyrażenie przez call w jego funkcji eval z InjectedScriptHost jako thisArg

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

Biorąc to pod uwagę, możesz wysłuchać thisArg z call bycia evaluate i uzyskać odniesienie do pierwszego argumentu (InjectedScriptHost)

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

Można np. wyrzucić błąd, że ocena została odrzucona.

Tutaj wpisz opis obrazka

Oto przykład gdzie wprowadzone wyrażenie jest przekazywane do kompilatora CoffeeScript przed przekazaniem go do evaluate funkcja.

 32
Author: Moritz Roessler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-13 05:33:21

Netflix również implementuje tę funkcję

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

Po prostu nadpisują console._commandLineAPI, aby wyrzucić błąd bezpieczeństwa.

 25
Author: Fizer Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-06 06:20:42

Jest to możliwe, ponieważ Facebook był w stanie to zrobić. Cóż, nie rzeczywiste narzędzia programistyczne, ale wykonanie Javascript w konsoli.

Zobacz to: jak Facebook wyłącza zintegrowane narzędzia programistyczne przeglądarki?

To naprawdę wiele nie zrobi, ponieważ istnieją inne sposoby na obejście tego typu zabezpieczeń po stronie klienta.

Kiedy mówisz, że jest po stronie klienta, dzieje się to poza kontrolą serwera, więc niewiele możesz z tym zrobić. Jeśli pytasz, dlaczego Facebook nadal to robi, nie jest to tak naprawdę dla bezpieczeństwa, ale dla ochrony zwykłych Użytkowników, którzy nie znają javascript przed uruchomieniem kodu (którego nie wiedzą, jak czytać) w konsoli. Jest to powszechne w przypadku witryn, które obiecują usługę auto-liker lub inne boty funkcjonalności Facebook po zrobieniu tego, o co Cię proszą, gdzie w większości przypadków dają Ci wycinek javascript do uruchomienia w konsoli.

Jeśli nie masz tylu użytkowników Co Facebook, to chyba nie ma trzeba robić to, co robi Facebook.

Nawet jeśli wyłączysz Javascript w konsoli, uruchomienie javascript za pomocą paska adresu jest nadal możliwe.

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

I jeśli przeglądarka wyłącza javascript na pasku adresu, (gdy wklejasz kod do paska adresu w Google Chrome, usuwa frazę " javascript:") wklejanie javascript do jednego z linków za pomocą elementu inspect jest nadal możliwe.

Inspect the anchor:

Tutaj wpisz opis obrazka

Wklej kod w href:

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

Najważniejsze jest to, że Walidacja po stronie serwera i bezpieczeństwo powinny być pierwsze, a następnie po stronie klienta.

 25
Author: Jomar Sevillejo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-02 08:52:04

Chrome bardzo się zmienił od czasu, gdy facebook mógł wyłączyć konsolę...

Według stanu na Marzec 2017 to już nie działa.

Najlepsze, co możesz zrobić, to wyłączyć niektóre funkcje konsoli, przykład:

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(){};
}
 12
Author: Alpha2k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-12 12:44:22

Mój prosty sposób, ale może pomóc w dalszych wariantach na ten temat. Wymień wszystkie metody i zmień je na bezużyteczne.

  Object.getOwnPropertyNames(console).filter(function(property) {
     return typeof console[property] == 'function';
  }).forEach(function (verb) {
     console[verb] =function(){return 'Sorry, for security reasons...';};
  });
 9
Author: Dusan Krstic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-18 22:29:59

Wewnętrznie devtools wstrzykuje do strony program IIFE o nazwie getCompletions, wywoływany po naciśnięciu klawisza wewnątrz konsoli Devtools.

Patrząc na źródło tej funkcji , używa ona kilku globalnych funkcji, które można nadpisać.

Za pomocą Error konstruktor możliwe jest uzyskanie stosu wywołań, który będzie zawierał getCompletions gdy zostanie wywołany przez Devtools.


Przykład:

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);
});
 5
Author: Sam Denty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-13 18:24:47

Proste rozwiązanie!

setInterval(()=>console.clear(),1500);
 3
Author: Mohmmad Ebrahimi Aval,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-04 06:54:09

Poszedłbym drogą:

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

  },
  set: function() {

  }
});
 0
Author: Zibri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-14 11:17:07

Nie jest to środek bezpieczeństwa pozwalający na pozostawienie słabego kodu bez nadzoru. Zawsze uzyskaj stałe rozwiązanie dla słabego kodu i odpowiednio zabezpiecz swoje strony internetowe przed wdrożeniem tej strategii

Najlepszym narzędziem według mojej wiedzy byłoby dodanie wielu plików javascript, które po prostu zmieniają integralność strony z powrotem do normy, odświeżając lub zastępując zawartość. Wyłączenie tego narzędzia programisty nie byłoby najlepszym pomysłem, ponieważ omijanie jest zawsze kwestionowane ponieważ kod jest częścią przeglądarki, a nie renderowania serwera, więc może być pęknięty.

Jeśli masz js file one sprawdzanie zmian <element> na ważnych elementach oraz js file two i js file three sprawdzanie, czy ten plik istnieje na okres, będziesz miał pełną integralność na stronie w tym okresie.

Weźmy przykład z 4 plików i pokaż, co mam na myśli.

Indeks.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

Styl.css

Teraz jest to tylko po to, aby pokazać, że działa na wszystkich plikach i tagach jak również

   #heading {
   background-color:red;
   }

Jeśli połączysz wszystkie te pliki i zbudujesz przykład, zobaczysz funkcję tej miary. Zapobiegnie to niektórym niewymuszonym zastrzykom, jeśli prawidłowo wdrożysz go we wszystkich ważnych elementach Twój plik indeksu szczególnie podczas pracy z PHP.

Dlaczego wybrałem reload zamiast zmienić z powrotem na normalną wartość na atrybut jest fakt, że niektórzy atakujący mogą mieć inną część strony już skonfigurowaną i gotową, a to zmniejsza ilość kodu. Przeładowanie usunie całą ciężką pracę atakującego i prawdopodobnie pójdzie grać w łatwiejsze miejsce.

Kolejna uwaga: to może stać się dużo kodu, więc zachowaj go w czystości i upewnij się, że dodasz definicje do miejsca, do którego należą łatwe wprowadzanie zmian w przyszłości. Ustaw także sekundy na preferowaną ilość, ponieważ interwały 1 sekundowe na dużych stronach mogą mieć drastyczne skutki na starszych komputerach, z których mogą korzystać użytkownicy

 -2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-04 04:55:35