Facebook, tarayıcının entegre Geliştirici Araçlarını nasıl devre dışı bırakır?


1685

Görünüşe göre son dolandırıcılık nedeniyle, geliştirici araçları spam göndermek için insanlar tarafından sömürülür ve hatta hesapları "kesmek" için kullanılır. Facebook geliştirici araçlarını engelledi ve konsolu bile kullanamıyorum.

Resim açıklamasını buraya girin

Bunu nasıl yaptılar?? Bir Yığın Taşması gönderisi bunun mümkün olmadığını iddia etti , ancak Facebook bunların yanlış olduğunu kanıtladı.

Sadece Facebook'a gidin ve geliştirici araçlarını açın, konsola bir karakter yazın ve bu uyarı açılır. Ne koyarsanız koyun, idam edilmeyecektir.

Bu nasıl mümkün olabilir?

Konsolda otomatik tamamlamayı bile engellediler:

Resim açıklamasını buraya girin


21
Sadece eğlence için: console.log = function () {}
tnt-rox

Konsolda otomatik tamamlama özelliğini nasıl engelledikleri için çözüm buldunuz mu
Akshay Hegde

1
@AkshayHegde Devtools'tan herhangi bir kod yürütülmesinin engellenmesinden kaynaklanan bir yan etkiydi.
Derek 朕 會 功夫

@Derek 朕 會 功夫 lütfen kodu paylaşır mısınız
Akshay

sadece fyi, artık kromda engellenmiyor.
John Lord

Yanıtlar:


2437

Facebook'ta bir güvenlik mühendisiyim ve bu benim hatam. Bazı kullanıcıların, tarayıcı koduna yapıştırıcı (kötü amaçlı) JavaScript kodu yapıştırdığı bazı saldırıları yavaşlatabileceğini görmek için bunu bazı kullanıcılar için test ediyoruz.

Açık olmak gerekirse: bilgisayar korsanlarının istemci tarafını engellemeye çalışmak genel olarak kötü bir fikirdir ; bu, belirli bir sosyal mühendislik saldırısına karşı korumak içindir .

Test grubuna ulaştıysanız ve bundan rahatsız olduysanız özür dileriz. En azından bazı kurbanları durduracak kadar korkutucu olurken , eski devre dışı bırakma sayfasını (şimdi yardım sayfası ) mümkün olduğunca basit hale getirmeye çalıştım .

Gerçek kod @ joeldixon66'nın bağlantısına oldukça benzer ; bizimki iyi bir sebep olmadan biraz daha karmaşık.

Chrome, tüm konsol kodunu sarar

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

... böylece site console._commandLineAPIatmayı yeniden tanımlıyor:

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

Bu yeterli değil (deneyin!) , Ama ana hile bu.


Epilog: Chrome ekibi, konsolu kullanıcı tarafı JS'den yenmenin bir hata olduğuna karar verdi ve sorunu düzelterek bu tekniği geçersiz kıldı. Daha sonra, kullanıcıları self-xss'den korumak için ek koruma eklendi .


10
Chrome bir güncelleme yaptı, ancak bu adam tekrar bir düzeltme yaptı: kspace.in/blog/2014/06/21/…
Roger Gajraj

3
@Af, çıkış sayfanız artık bu korumayı kapatma imkanı olmadan yardım sayfasını gösteriyor.
arm.localhost

168
Lütfen bazı kullanıcıların aptallığından dolayı geliştirici araçlarını kırmayın. Bunun gibi "çözümler" bir milyon güneşin öfkesi ile beni yakıyor.
Jonathan Dunlap

85
Google'ın, Chrome'un "Güvenli" bir sürümünü yayınlaması gerekiyor, DevTools yok ve otomatik güncellemelerdeki herkesi bu sürüme yalnızca bir kez geçmeye zorlaması gerektiğini düşünüyorum. Farkı fark eden ve DevTools'a ihtiyaç duyan herhangi bir geliştirici "korkunç" sürümü indirmelidir. Aslında, bunları doğrudan indirme sayfasında "Korkunç" ve "Güvenli" olarak etiketleyin ve Darwinistlerin açıkça "Sosyal medya saldırısı size Korkunç sürümü indirmenizi söylediğinden dolayı buradasınız demektir; Bunu yap." Tanrı seni çok yaratıcı olduğu için FB geliştiricileri korusun!
MonkeyZeus

11
@ n00b Bu uyarı mesajı sadece a console.log.
gcampbell

91

Facebook'un konsol buster komut dosyasını Chrome geliştirici araçlarını kullanarak buldum. İşte okunabilirlik için küçük değişiklikler içeren komut dosyası. Anlayamadığım bitleri kaldırdım:

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

Bununla, konsolda yazılan ifadeler yürütülemezken (özel durum günlüğe kaydedilir) konsol otomatik tamamlama sessizce başarısız olur.

Referanslar:


48

Bunu herhangi bir sayfada tetikleyemedim. Bunun daha sağlam bir sürümü bunu yapardı:

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

console.log('test');

Çıktıya stil eklemek için: JavaScript konsolundaki renkler

Edit Thinking @ joeldixon66 doğru fikre sahip: Konsoldan JavaScript yürütmeyi devre dışı bırak «::: KSpace :::


serin bir ama yine de aynı geçersiz kılın window.console.log = function(){//empty}ve console.log kullanın
süper serin

32

Yeniden tanımlamanın yanı sıra console._commandLineAPI, geliştirici konsoluna girilen ifadelerin değerlendirilmesini önlemek veya değiştirmek için WebKit tarayıcılarında InjectedScriptHost'a girmenin başka yolları da vardır.

Düzenle:

Chrome bunu geçmiş bir sürümde düzeltti. - o zaman gist'i oluşturduğum için Şubat 2015'ten önce olmalıydı

İşte başka bir olasılık. Bu kez doğrudan içine, bir seviye yukarıda, oltaya InjectedScriptyerine InjectedScriptHostönceki sürüm aksine.

Hangi tür hoş, çünkü InjectedScript._evaluateAndWrapgüvenmek yerine doğrudan maymun yaması olabilir, çünkü InjectedScriptHost.evaluatene olması gerektiği üzerinde daha ince kontrol sağlar.

Bir başka ilginç şey, bir ifade değerlendirildiğinde dahili sonucu kesebileceğimiz ve bunu normal davranış yerine kullanıcıya geri döndürebileceğimizdir .

İşte tam olarak bunu yapan kod, kullanıcı konsolda bir şey değerlendirdiğinde iç sonucu döndürür.

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

Biraz ayrıntılı, ama içine bazı yorumlar koyduğumu düşündüm

Normalde, örneğin bir kullanıcı [1,2,3,4]aşağıdaki çıktıyı beklediğinizi değerlendirirse :

resim açıklamasını buraya girin

InjectedScript._evaluateAndWrapAynı ifadeyi değerlendiren maymun-denemeden sonra aşağıdaki çıktıyı verir:

resim açıklamasını buraya girin

Gördüğünüz gibi, çıktıyı gösteren küçük sol ok hala orada, ama bu sefer bir nesne alıyoruz. İfadenin sonucu, dizi [1,2,3,4], açıklanan tüm özellikleri ile bir nesne olarak temsil edilir.

Hata oluşturanlar da dahil olmak üzere bu ifadeyi ve bu ifadeyi değerlendirmeye çalışmanızı öneririm. Oldukça ilginç.

Ayrıca, is - InjectedScriptHost- nesnesine bir göz atın . Müfettişin içleriyle oynamak ve biraz içgörü elde etmek için bazı yöntemler sunar.

Tabii ki, tüm bu bilgileri ele geçirebilir ve yine de orijinal sonucu kullanıcıya geri döndürebilirsiniz.

Diğer yoldaki return deyimini console.log (res)aşağıdaki a ile değiştirin return res. Sonra aşağıdaki ile sonuçlanır.

resim açıklamasını buraya girin

Düzenleme Sonu


Bu, Google tarafından düzeltilen önceki sürümdür. Dolayısıyla artık olası bir yol değil.

Bunlardan biri Function.prototype.call

Chrome, girilen ifadeyi calleval işlevini aşağıdaki InjectedScriptHostgibi kullanarak değerlendirir:thisArg

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

Bu göz önüne alındığında thisArg, callvarlığını dinleyebilir evaluateve ilk argümana referans alabilirsiniz ( 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);  
        }
    };
}

Örneğin, değerlendirmenin reddedildiğine dair bir hata atabilirsiniz.

resim açıklamasını buraya girin

Girilen ifadenin işleve geçmeden önce bir CoffeeScript derleyicisine aktarıldığı bir örnek aşağıdadır evaluate.


25

Netflix de bu özelliği uygular

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

Onlar sadece console._commandLineAPIgüvenlik hatası atmak için geçersiz kılar .


24

Bu aslında Facebook bunu yapabildiğinden mümkün. Eh, gerçek web geliştirici araçları değil, konsolda Javascript yürütülmesi.

Şuna bakın: Facebook, tarayıcının entegre Geliştirici Araçlarını nasıl devre dışı bırakır?

Bu tür istemci tarafı güvenliği atlamanın başka yolları olduğundan, bu gerçekten çok şey yapmayacak.

İstemci tarafı olduğunu söylediğinizde, sunucunun denetiminin dışında gerçekleşir, bu nedenle bu konuda yapabileceğiniz çok şey yoktur. Facebook'un bunu neden hala yaptığını soruyorsanız, bu gerçekten güvenlik için değil, javascript bilmeyen normal kullanıcıları konsola kod çalıştırmadan (nasıl okuyacaklarını bilmedikleri) korumak içindir. Bu, sizden istediklerini yaptıktan sonra otomatik liker hizmeti veya diğer Facebook işlevsellik botları vaat eden siteler için yaygındır, burada çoğu durumda size konsolda çalıştırmak için bir javascript ipucu verir.

Facebook kadar kullanıcınız yoksa, Facebook'un yaptıklarını yapmanın bir gereği olduğunu düşünmüyorum.

Konsolda Javascript'i devre dışı bıraksanız bile, javascript'i adres çubuğu üzerinden çalıştırmak hala mümkündür.

resim açıklamasını buraya girin

resim açıklamasını buraya girin

ve tarayıcı adres çubuğunda javascript'i devre dışı bırakırsa (Google Chrome'daki adres çubuğuna kod yapıştırdığınızda, javascript'i inspect öğesi yoluyla bağlantılardan birine yapıştırmak hala mümkündür.

Çapayı inceleyin:

resim açıklamasını buraya girin

Kodu href'e yapıştır:

resim açıklamasını buraya girin

resim açıklamasını buraya girin

resim açıklamasını buraya girin

Alt satırda sunucu tarafı doğrulama ve güvenlik ilk olmalı, daha sonra istemci tarafı yapın.


11

Facebook'un konsolu devre dışı bırakabilmesi nedeniyle Chrome çok değişti ...

Mart 2017'ye göre bu artık çalışmıyor.

Yapabileceğiniz en iyi konsol işlevlerinden bazılarını devre dışı bırakmaktır, örneğin:

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

9

Benim basit yolum, ama bu konuda daha fazla varyasyon için yardımcı olabilir. Tüm yöntemleri listeleyin ve işe yaramaz hale getirin.

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

5

Dahili olarak devtools getCompletions, Devtools konsolunun içinde bir tuşa basıldığında çağrılan sayfaya bir IIFE enjekte eder .

Bu işlevin kaynağına bakıldığında, üzerine yazılabilecek birkaç küresel işlev kullanır.

Kullanarak Erroryapıcısı içereceğini çağrı yığını almak mümkündür getCompletionsDevTools'un tarafından çağrıldığında.


Misal:

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


Bu oldukça düzenli, ama aynı zamanda sayfayı da çökertiyor.
Derek 朕 會 功夫

@Derek 朕 會 功夫 Daha fazla kullanıcı girişini bastırmanın tek yolu (buldum)
samdd

Sonsuz bir döngü kullanmak yerine hata gönderebilir misiniz acaba? Düzenleme: Test edildi, çalışmıyor.
Derek 朕 會 功夫

@Derek 朕 會 功夫 bir try catch bloğunda. Büyük olasılıkla bloğun üstündeki işlevleri geçersiz kılabilirsiniz, ancak yalnızca otomatik tamamlamayı önleyebilir (değerlendirme değil)
samdd

2

basit bir çözüm!

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

1
Bu nasıl devre dışı bırakır console.log()?
Kırmızı

1
console.log()konsol sürekli temizlendiğinde artık önemli değil :)
Mohmmad Ebrahimi Aval

bu kötü bir fikir. bilgisayar korsanı kendi terminalinden izleyebilir ve tüm günlükleri görebilir.
GFxJamal

4
ve Günlükleri Koru'yu işaretlerseniz, console.clear () hiçbir şey yapmaz: P
Zibri

0

Yol boyunca giderdim:

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

  },
  set: function() {

  }
});

-2

Bu, zayıf kodun gözetimsiz bırakılması için bir güvenlik önlemi değildir. Bu stratejiyi uygulamadan önce her zaman zayıf kodlara kalıcı bir çözüm edinin ve web sitelerinizi güvenli bir şekilde koruyun

Bildiğim kadarıyla en iyi araç, içeriği yenileyerek veya değiştirerek sayfanın bütünlüğünü normale döndüren birden fazla javascript dosyası eklemek olacaktır. Bu geliştirici aracının devre dışı bırakılması en iyi fikir değildir çünkü baypas yapmak her zaman söz konusudur, çünkü kod bir sunucu oluşturma değil tarayıcının bir parçası olduğundan, çatlayabilir.

Önemli öğelerdeki değişiklikleri js file onekontrol ettiyseniz ve bu dosyanın dönem başına var olup olmadığını kontrol ederseniz, dönem içinde sayfada tam bütünlük geri yüklemesine sahip olursunuz.<element>js file twojs file three

4 dosyaya bir örnek verelim ve ne demek istediğimi gösterelim.

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

Şimdi bu sadece tüm dosyalar ve etiketler üzerinde çalıştığını göstermek için

   #heading {
   background-color:red;
   }

Tüm bu dosyaları bir araya getirir ve örnek oluşturursanız, bu önlemin işlevini görürsünüz. Bu, özellikle PHP ile çalışırken dizin dosyanızdaki tüm önemli öğelere doğru bir şekilde uygulamanız durumunda bazı beklenmedik enjeksiyonları önleyecektir.

Neden öznitelik başına normal değerine değiştirmek yerine yeniden yüklemeyi seçtim, bazı saldırganların web sitesinin önceden yapılandırılmış ve hazır başka bir bölümüne sahip olabileceği ve kod miktarını azaltacağı gerçeğidir. Yeniden yükleme saldırganın tüm zor işlerini kaldıracak ve muhtemelen daha kolay bir yerde oynamaya gidecek.

Başka bir not: Bu çok fazla kod olabilir, bu yüzden temiz tutun ve gelecekte düzenlemeleri kolaylaştırmak için ait oldukları yere tanımları eklediğinizden emin olun. Ayrıca, büyük sayfalardaki 1 saniyelik aralıkların ziyaretçilerinizin kullanıyor olabileceği eski bilgisayarlarda önemli etkileri olabileceği için saniyeleri tercih ettiğiniz tutara ayarlayın


bu ... bu iyi bir yaklaşım değil.
RozzA
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.