Bagaimana cara Facebook menonaktifkan Alat Pengembang terintegrasi browser?

1685

Jadi rupanya karena penipuan baru-baru ini, alat pengembang dieksploitasi oleh orang-orang untuk mengirim spam dan bahkan digunakan untuk "meretas" akun. Facebook telah memblokir alat pengembang, dan saya bahkan tidak bisa menggunakan konsol.

Masukkan deskripsi gambar di sini

Bagaimana mereka melakukan itu ?? Satu pos Stack Overflow mengklaim bahwa itu tidak mungkin , tetapi Facebook telah membuktikan mereka salah.

Cukup buka Facebook dan buka alat pengembang, ketik satu karakter ke konsol, dan peringatan ini muncul. Apa pun yang Anda masukkan, itu tidak akan dieksekusi.

Bagaimana ini mungkin?

Mereka bahkan memblokir pelengkapan otomatis di konsol:

Masukkan deskripsi gambar di sini

Derek 朕 會 功夫
sumber
21
Hanya untuk bersenang-senang: console.log = function () {}
tnt-rox
Apakah Anda menemukan solusi untuk bagaimana mereka memblokir fitur
pelengkapan
1
@AkshayHegde Itu adalah efek samping yang disebabkan oleh pemblokiran setiap eksekusi kode dari devtools.
Derek 朕 會 功夫
@Derek 朕 會 功夫 bisakah kamu membagikan kode
Akshay Hegde
hanya fyi, itu tidak diblokir lagi di chrome.
John Lord

Jawaban:

2437

Saya seorang insinyur keamanan di Facebook dan ini adalah kesalahan saya. Kami sedang menguji ini untuk beberapa pengguna untuk melihat apakah itu dapat memperlambat beberapa serangan di mana pengguna ditipu untuk menempelkan kode JavaScript (jahat) ke konsol browser.

Untuk lebih jelasnya: mencoba memblokir peretas sisi klien adalah ide yang buruk secara umum; ini untuk melindungi terhadap serangan rekayasa sosial tertentu .

Jika Anda berakhir di kelompok uji dan terganggu dengan ini, maaf. Saya mencoba membuat halaman opt-out lama (sekarang halaman bantuan ) sesederhana mungkin tetapi masih cukup menakutkan untuk menghentikan setidaknya beberapa korban.

Kode aktual sangat mirip dengan tautan @ joeldixon66 ; milik kami sedikit lebih rumit tanpa alasan.

Chrome membungkus semua kode konsol

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

... jadi situs tersebut mendefinisikan ulang console._commandLineAPIuntuk membuang:

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

Ini tidak cukup (coba saja!) , Tapi itulah trik utamanya.


Epilog: Tim Chrome memutuskan bahwa mengalahkan konsol dari sisi pengguna JS adalah bug dan memperbaiki masalah , menjadikan teknik ini tidak valid. Setelah itu, perlindungan tambahan ditambahkan untuk melindungi pengguna dari self-xss .

Alf
sumber
10
Chrome memang membuat pembaruan tetapi orang ini melakukan perbaikan lagi: kspace.in/blog/2014/06/21/…
Roger Gajraj
3
@Alf, halaman opt-out Anda sekarang menampilkan halaman bantuan tanpa ada kemungkinan untuk mematikan perlindungan ini.
arm.localhost
168
Tolong jangan hancurkan alat pengembang karena kebodohan beberapa pengguna. "Solusi" seperti ini membuat saya terbakar dengan amarah sejuta matahari.
Jonathan Dunlap
85
Saya pikir Google perlu merilis versi Chrome "Aman", tanpa DevTools, dan memaksa siapa pun di pembaruan otomatis untuk beralih ke versi ini hanya sekali. Setiap pengembang yang benar-benar memperhatikan perbedaan dan membutuhkan DevTools harus mengunduh versi "menakutkan". Bahkan, label mereka sebagai "Menakutkan" dan "Aman" langsung di halaman unduhan dan mencegah orang Darwin dari membahayakan diri mereka sendiri dengan secara eksplisit menyatakan bahwa "Anda kemungkinan berada di sini karena serangan rekayasa sosial memberitahu Anda untuk mengunduh versi Scary; tolong jangan melakukan hal ini." Tuhan memberkati kalian para FB yang sangat kreatif!
MonkeyZeus
11
@ n00b Pesan peringatan itu hanya a console.log.
gcampbell
91

Saya menemukan skrip buster konsol Facebook menggunakan alat pengembang Chrome. Berikut adalah skrip dengan perubahan kecil untuk keterbacaan. Saya telah menghapus bit yang tidak bisa saya mengerti:

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

Dengan ini, konsol-otomatis gagal secara diam-diam sementara pernyataan yang diketik di konsol akan gagal dijalankan (pengecualian akan dicatat).

Referensi:

Salman A
sumber
48

Saya tidak dapat memicunya pada halaman mana pun. Versi yang lebih kuat dari ini akan melakukannya:

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

console.log('test');

Untuk memberi gaya keluaran: Warna dalam konsol JavaScript

Edit Thinking @ joeldixon66 memiliki ide yang tepat: Nonaktifkan eksekusi JavaScript dari konsol «::: KSpace :::

Akan
sumber
satu keren tapi masih kemudian menimpa yang sama window.console.log = function(){//empty}dan menggunakan console.log
super cool
32

Selain mendefinisikan ulang console._commandLineAPI , ada beberapa cara lain untuk membobol InjectedScriptHost di browser WebKit, untuk mencegah atau mengubah evaluasi ekspresi yang dimasukkan ke konsol pengembang.

Edit:

Chrome telah memperbaikinya dalam rilis sebelumnya. - yang pasti sebelum Februari 2015, saat saya menciptakan intinya pada saat itu

Jadi, inilah kemungkinan lain. Kali ini kami menghubungkan, level di atas, langsung ke InjectedScriptdaripada InjectedScriptHostsebagai lawan dari versi sebelumnya.

Yang agak menyenangkan, karena Anda bisa langsung menambal monyet InjectedScript._evaluateAndWrapdaripada harus bergantung InjectedScriptHost.evaluatekarena itu memberi Anda kontrol lebih baik atas apa yang harus terjadi.

Hal lain yang cukup menarik adalah, bahwa kita dapat mencegat hasil internal ketika ekspresi dievaluasi dan mengembalikannya kepada pengguna alih-alih perilaku normal.

Berikut adalah kode, yang melakukan hal itu, mengembalikan hasil internal ketika pengguna mengevaluasi sesuatu di konsol.

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

Ini agak bertele-tele, tapi saya pikir saya menaruh beberapa komentar di dalamnya

Jadi biasanya, jika pengguna, misalnya, mengevaluasi [1,2,3,4]Anda akan mengharapkan output berikut:

masukkan deskripsi gambar di sini

Setelah monkeypatching InjectedScript._evaluateAndWrapmengevaluasi ekspresi yang sama, berikan output berikut:

masukkan deskripsi gambar di sini

Seperti yang Anda lihat panah kiri-kecil, yang menunjukkan keluaran, masih ada di sana, tapi kali ini kita mendapatkan objek. Di mana hasil dari ekspresi, array [1,2,3,4]diwakili sebagai objek dengan semua propertinya dijelaskan.

Saya sarankan mencoba untuk mengevaluasi ekspresi ini dan itu, termasuk yang menghasilkan kesalahan. Cukup menarik.

Selain itu, kita lihat di is - InjectedScriptHost- objek. Ini memberikan beberapa metode untuk bermain dan mendapatkan sedikit wawasan tentang internal inspektur.

Tentu saja, Anda dapat mencegat semua informasi itu dan tetap mengembalikan hasil asli kepada pengguna.

Cukup ganti pernyataan pengembalian di jalur lain dengan console.log (res)mengikuti a return res. Maka Anda akan berakhir dengan yang berikut ini.

masukkan deskripsi gambar di sini

Akhir dari Edit


Ini adalah versi sebelumnya yang diperbaiki oleh Google. Karenanya bukan cara yang mungkin lagi.

Salah satunya adalah mengaitkan ke Function.prototype.call

Chrome mengevaluasi ekspresi yang dimasukkan dengan callmenggunakan fungsi eval-nya dengan InjectedScriptHostasthisArg

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

Mengingat ini, Anda dapat mendengarkan untuk thisArgdari callmakhluk evaluatedan mendapatkan referensi ke argumen pertama ( 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);  
        }
    };
}

Anda dapat misalnya membuat kesalahan, bahwa evaluasi ditolak.

masukkan deskripsi gambar di sini

Berikut adalah contoh di mana ekspresi yang dimasukkan akan diteruskan ke kompiler CoffeeScript sebelum meneruskannya ke evaluatefungsi.

Moritz Roessler
sumber
25

Netflix juga mengimplementasikan fitur ini

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

Mereka hanya mengganti console._commandLineAPIuntuk membuang kesalahan keamanan.

Fizer Khan
sumber
24

Ini sebenarnya mungkin karena Facebook bisa melakukannya. Yah, bukan alat pengembang web yang sebenarnya tetapi eksekusi Javascript di konsol.

Lihat ini: Bagaimana cara Facebook menonaktifkan Alat Pengembang terintegrasi browser?

Ini benar-benar tidak akan berbuat banyak karena ada cara lain untuk memotong jenis keamanan sisi klien ini.

Ketika Anda mengatakan itu adalah sisi klien, itu terjadi di luar kendali server, jadi tidak banyak yang dapat Anda lakukan. Jika Anda bertanya mengapa Facebook masih melakukan ini, ini bukan untuk keamanan tetapi untuk melindungi pengguna normal yang tidak tahu javascript dari menjalankan kode (bahwa mereka tidak tahu cara membaca) ke konsol. Ini umum untuk situs yang menjanjikan layanan auto-liker atau bot fungsionalitas Facebook lainnya setelah Anda melakukan apa yang mereka minta Anda lakukan, di mana dalam kebanyakan kasus, mereka memberi Anda potongan javascript untuk dijalankan di konsol.

Jika Anda tidak memiliki pengguna sebanyak Facebook, maka saya rasa tidak perlu melakukan apa yang dilakukan Facebook.

Bahkan jika Anda menonaktifkan Javascript di konsol, menjalankan javascript melalui bilah alamat masih dimungkinkan.

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

dan jika browser menonaktifkan javascript di bilah alamat, (Saat Anda menempelkan kode ke bilah alamat di Google Chrome, itu menghapus frasa 'javascript:') menempelkan javascript ke salah satu tautan melalui elemen periksa masih dimungkinkan.

Periksa jangkar:

masukkan deskripsi gambar di sini

Tempel kode dalam href:

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Intinya adalah validasi sisi server dan keamanan harus menjadi yang pertama, kemudian lakukan sisi klien.

Jomar Sevillejo
sumber
11

Chrome banyak berubah sejak facebook dapat menonaktifkan konsol ...

Per Maret 2017 ini tidak berfungsi lagi.

Yang terbaik yang dapat Anda lakukan adalah menonaktifkan beberapa fungsi konsol, misalnya:

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

Cara sederhana saya, tetapi dapat membantu untuk variasi lebih lanjut tentang hal ini. Daftar semua metode dan ubah menjadi tidak berguna.

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

getCompletionsDevtools internal menyuntikkan IIFE yang dinamai ke dalam halaman, disebut ketika tombol ditekan di dalam konsol Devtools.

Melihat sumber fungsi itu, ia menggunakan beberapa fungsi global yang dapat ditimpa.

Dengan menggunakan Errorkonstruktor dimungkinkan untuk mendapatkan tumpukan panggilan, yang akan termasuk getCompletionsketika dipanggil oleh Devtools.


Contoh:

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

samdd
sumber
Itu cukup rapi, tetapi juga merusak halaman.
Derek 朕 會 功夫
@Derek 朕 會 功夫 Satu-satunya cara (saya telah menemukan) untuk menekan input pengguna lebih lanjut
samdd
Saya ingin tahu apakah Anda dapat melempar kesalahan alih-alih menggunakan infinite loop. Sunting: Diuji, tidak berfungsi.
Derek 朕 會 功夫
@Derek 朕 會 功夫 ada di blok coba tangkap. Anda mungkin dapat mengesampingkan fungsi-fungsi di atas blok, tetapi itu hanya akan mencegah penyelesaian otomatis (bukan evaluasi)
samdd
2

solusi sederhana!

setInterval(()=>console.clear(),1500);
Mohmmad Ebrahimi Aval
sumber
1
Bagaimana ini menonaktifkan console.log()?
Merah
1
console.log()tidak ada lagi masalah ketika konsol terus-menerus dibersihkan :)
Mohmmad Ebrahimi Aval
ini ide yang buruk. hacker dapat melacak dari terminal mereka dan melihat semua log.
GFxJamal
4
dan jika Anda menandai Preserve Logs, console.clear () tidak melakukan apa-apa: P
Zibri
0

Saya akan mengikuti:

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

  },
  set: function() {

  }
});
Zibri
sumber
-2

Ini bukan langkah keamanan agar kode lemah dibiarkan tanpa pengawasan. Selalu dapatkan solusi permanen untuk kode lemah dan amankan situs web Anda dengan benar sebelum menerapkan strategi ini

Alat terbaik sejauh ini menurut pengetahuan saya adalah menambahkan beberapa file javascript yang hanya mengubah integritas halaman kembali normal dengan menyegarkan atau mengganti konten. Menonaktifkan alat pengembang ini bukan ide terbaik karena mem-bypass selalu dipertanyakan karena kode merupakan bagian dari browser dan bukan rendering server, sehingga bisa di-crack.

Jika Anda telah js file onememeriksa <element>perubahan pada elemen penting dan js file twodan js file threememeriksa apakah file ini ada per periode, Anda akan memiliki integritas penuh memulihkan pada halaman dalam periode tersebut.

Mari kita ambil contoh dari 4 file dan menunjukkan kepada Anda apa yang saya maksud.

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

Sekarang ini hanya untuk menunjukkan itu berfungsi pada semua file dan tag juga

   #heading {
   background-color:red;
   }

Jika Anda meletakkan semua file ini bersama-sama dan membangun contoh Anda akan melihat fungsi dari ukuran ini. Ini akan mencegah beberapa suntikan yang tidak terduga jika Anda menerapkannya dengan benar pada semua elemen penting dalam file indeks Anda terutama ketika bekerja dengan PHP.

Mengapa saya memilih memuat ulang daripada mengubah kembali ke nilai normal per atribut adalah kenyataan bahwa beberapa penyerang dapat memiliki bagian lain dari situs web yang sudah dikonfigurasi dan siap dan mengurangi jumlah kode. Muat ulang akan menghapus semua kerja keras penyerang dan dia mungkin akan bermain di tempat yang lebih mudah.

Catatan lain: Ini bisa menjadi banyak kode jadi tetap bersih dan pastikan untuk menambahkan definisi di mana mereka membuat pengeditan menjadi mudah di masa depan. Juga atur detik ke jumlah pilihan Anda karena interval 1 detik pada halaman besar dapat memiliki efek drastis pada komputer lama yang mungkin digunakan pengunjung Anda


sumber
ini ... ini bukan pendekatan yang baik.
RozzA