web-dev-qa-db-ja.com

Facebookはどのようにブラウザの統合開発者ツールを無効にしますか?

だから最近の詐欺のせいで、開発者ツールはスパムを投稿するために人々によって悪用され、アカウントを「ハッキング」するためにさえ使用されています。 Facebookは開発者向けツールをブロックしています、そして私もコンソールを使用することができません。

Enter image description here

彼らはどのようにそれをしましたか? One Stack Overflowの投稿では不可能だと主張していた しかし、Facebookはそれらを間違って証明している。

Facebookにアクセスして開発者ツールを開き、コンソールに1文字入力すると、この警告が表示されます。何を入れても実行されません。

これはどのように可能ですか?

彼らはコンソールでオートコンプリートをブロックさえしました:

Enter image description here

1617

私はFacebookのセキュリティエンジニアです。これが私のせいです。ユーザーがブラウザコンソールに(悪意のある)JavaScriptコードを貼り付けようとする攻撃を遅らせることができるかどうかを確認するため、一部のユーザーに対してこれをテストしています。

明確に言うと、クライアント側でハッカーをブロックしようとするのは 悪い考えです ; これは 特定のソーシャルエンジニアリング攻撃から保護するためです

テストグループになってこれに悩まされているのであれば、すみません。古いオプトアウトページ(現在は ヘルプページ )をできるだけ単純にして、まだ怖いのですが。少なくとも犠牲者の some を止めてください。

実際のコードは @ joeldixon66のリンク によく似ています。私たちのものは正当な理由もなく少し複雑です。

Chromeはすべてのコンソールコードを

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

...そのため、サイトはconsole._commandLineAPIを次のように再定義します。

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

これは 十分ではありません(それを試してください!) 、しかしそれがの主なトリックです。


エピローグ:Chromeチームは、ユーザーサイドのJSからコンソールを無効にすることがバグであると判断し、 問題を解決しました このテクニックを無効にしました。その後、追加の保護が に追加され、ユーザーを自己xssから保護します 。 

2339
Alf

私はChrome開発者ツールを使ってFacebookのコンソールバスタースクリプトを見つけました。これは読みやすさのために小さな変更を加えたスクリプトです。私は理解できない部分を削除しました。

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

これにより、consoleでタイプされたステートメントが実行に失敗する間、コンソールのオートコンプリートは黙って失敗します(例外はログに記録されます)。

参考文献:

78
Salman A

どのページでもそれを引き起こすことはできませんでした。これのより堅牢なバージョンはそれをするでしょう:

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

console.log('test');

出力のスタイルを設定するには、次のようにします。 JavaScriptコンソールの色

編集 Thinking @ joeldixon66 は正しい考えを持っています: コンソールからのJavaScriptの実行を無効にする«::: KSpace :::

38
Will

console._commandLineAPIを再定義する以外に、WebKitブラウザーでInjectedScriptHostに侵入して、開発者のコ​​ンソールに入力された式の評価を防止または変更する方法がいくつかあります。

編集:

Chromeは過去のリリースでこれを修正しました。 -2015年2月より前である必要があります。その時点でGistを作成したためです

したがって、別の可能性があります。今回は、以前のバージョンとは異なり、InjectedScriptではなくInjectedScriptHostに直接接続します。

InjectedScript._evaluateAndWrapに依存する代わりにInjectedScriptHost.evaluateに直接パッチを当てることができるため、どのようなことが起こるかをよりきめ細かく制御できます。

別の非常に興味深いことは、式が評価されたときに内部結果をインターセプトし、通常の動作の代わりにをユーザーに返すことです

以下は、ユーザーがコンソールで何かを評価したときに内部結果を返すコードです。

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

少し冗長ですが、コメントを入れると思いました

したがって、通常、たとえばユーザーが[1,2,3,4]を評価すると、次の出力が期待されます。

enter image description here

InjectedScript._evaluateAndWrapと同じ式を評価した後、次の出力が得られます。

enter image description here

ご覧のように、出力を示す小さな左矢印がまだありますが、今回はオブジェクトを取得します。式の結果、配列[1,2,3,4]は、すべてのプロパティが記述されたオブジェクトとして表されます。

エラーを生成する式など、この式とその式を評価することをお勧めします。とても面白いです。

さらに、is-InjectedScriptHost-オブジェクトを見てください。それは、インスペクターの内部で遊んで少し洞察を得るいくつかの方法を提供します。

もちろん、すべての情報を傍受しても、元の結果をユーザーに返すことができます。

Elseパスのreturnステートメントを、return resに続くconsole.log (res)に置き換えるだけです。その後、次のようになります。

enter image description here

編集の終了


これは、Googleによって修正された以前のバージョンです。したがって、もはや可能な方法ではありません。

その1つはFunction.prototype.callにフックしています

Chromeは、callとしてその評価関数をInjectedScriptHostとしてthisArgすることにより、入力された式を評価します

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

これにより、thisArgcallevaluateであることをリッスンし、最初の引数(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);  
        }
    };
}

あなたは例えば評価が拒否されたことを示すエラーをスローします。

enter image description here

は、入力された式がevaluate関数に渡される前にCoffeeScriptコンパイラーに渡されます。

28
Moritz Roessler

Netflixもこの機能を実装しています

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

セキュリティエラーをスローするためにconsole._commandLineAPIをオーバーライドするだけです。

22
Fizer Khan

これはFacebookが可能だったので実際に可能である。まあ、実際のウェブ開発者ツールではなくコンソールでのJavascriptの実行。

これを参照してください: Facebookはどのようにブラウザの統合開発者ツールを無効にしますか?

ただし、この種のクライアント側のセキュリティを回避する方法は他にもあるため、これはあまり役に立ちません。

それがクライアント側であると言うとき、それはサーバの制御の外で起こるので、あなたがそれについてできることはあまりありません。なぜFacebookがまだこれをしているのかを尋ねるなら、これは本当にセキュリティのためではなく、javascriptを知らない一般ユーザをコードをコンソールから実行することから守るためです。これは、あなたが彼らにあなたに求めていることをした後にオートライバーサービスまたは他のFacebook機能ボットを約束するサイトのために一般的です、そこで、彼らはコンソールで走るためにあなたにジャバスクリプトの断片をあなたに与えます。

Facebookほど多くのユーザーがいないのであれば、Facebookがしていることをする必要はないと思います。

コンソールでJavascriptを無効にしても、アドレスバーからJavascriptを実行することは可能です。

enter image description here

enter image description here

ブラウザがアドレスバーのJavaScriptを無効にしている場合(Google Chromeのアドレスバーにコードを貼り付けると、フレーズ「javascript:」が削除されます)、inspect要素を介してJavaScriptをリンクの1つに貼り付けることもできます。

アンカーを調べます。

enter image description here

hrefにコードを貼り付けます。

enter image description here

enter image description here

enter image description here

要点はサーバー側の検証であり、セキュリティを最初にしてからクライアント側をしてください。

20
Jomar Sevillejo

時代遅れのFacebookがコンソールを無効にすることができるので、Chromeは大きく変わりました... 

2017年3月の時点で、これはもう機能しません。 

あなたができる最善はコンソール機能のいくつかを無効にすることです、例:

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

私の簡単な方法、しかしそれはこの主題に関する更なる変化のために役立つことができる。

  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はgetCompletionsという名前のIIFEをページに挿入します。これはDevtoolsコンソール内でキーが押されたときに呼び出されます。 

その関数の ソース を見ると、上書きできるいくつかの大域関数が使われています。

Error コンストラクタを使用することで、Devtoolsによって呼び出されたときにgetCompletionsを含む呼び出しスタックを取得することができます。


例:

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

簡単な解決策!

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

私は次のように進むでしょう

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

  },
  set: function() {

  }
});
0
Zibri

これは、弱いコードを無人のままにしておくためのセキュリティ対策ではありません。この戦略を実行する前に、常に脆弱なコードの恒久的な解決策を講じてWebサイトを適切に保護してください

私の知るところでは、これまでのところ最良のツールは、コンテンツを更新または置換することによってページの整合性を通常の状態に戻す単純な複数のJavaScriptファイルを追加することです。コードはブラウザの一部でありサーバーのレンダリングではないため、この開発者向けツールを無効にすることは迂回が常に問題となるため、最善の方法ではありません。 

js file oneで重要な要素の<element>の変更をチェックし、js file twojs file threeで期間ごとにこのファイルが存在することをチェックする必要がある場合は、その期間内にページの完全性を回復します。 

4つのファイルの例を見てみましょう。 

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

これは、すべてのファイルとタグで同様に機能することを示すためのものです。

   #heading {
   background-color:red;
   }

これらすべてのファイルをまとめて例を作成すると、この対策の機能がわかります。これにより、特にPHPを使用している場合に、インデックスファイル内のすべての重要な要素に正しく実装されていると思われる予期せぬインジェクションが防止されます。

属性ごとに通常の値に戻すのではなく再ロードを選択したのは、一部の攻撃者がWebサイトの別の部分を既に構成して準備ができているため、コード量が少なくなるためです。リロードすると、攻撃者の大変な作業がすべて削除され、おそらくどこかで簡単に遊ぶことになるでしょう。

もう1つの注意: これは多くのコードになる可能性があるので、きれいにしておき、将来的に編集を容易にするためにそれらが属する場所に定義を追加してください。また、大きいページでは1秒の間隔をあなたの訪問者が使用しているかもしれない古いコンピュータに劇的な影響を与える可能性があるので、秒をあなたの好みの量に設定してください

0
user9374996