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


1685

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

ここに画像の説明を入力してください

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

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

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

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

ここに画像の説明を入力してください


21
ただの楽しみ:console.log = function(){}
tnt-rox '20

コンソールでオートコンプリート機能をブロックする方法の解決策を見つけましたか
Akshay Hegde

1
@AkshayHegdeこれは、開発ツールからのコード実行をブロックすることによって引き起こされた副作用でした。
デレク━會功夫

コードを共有していただけますか
Akshay Hegde

ただファイ、それはもはやクロームでブロックされていません。
John Lord

回答:


2437

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

はっきりさせておきますが、クライアント側でハッカーをブロックしようとすることは、一般的に悪い考えです。これは、特定のソーシャルエンジニアリング攻撃から保護するためです。

あなたがテストグループになってしまい、これに悩まされている場合は、申し訳ありません。私は、古いオプトアウトページ(現在はヘルプページ)をできるだけシンプルにして、少なくとも一部の犠牲者を阻止するのに十分なほど怖いままにしました。

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

Chromeはすべてのコンソールコードをラップします

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

...したがって、サイトはconsole._commandLineAPIスローするように再定義します。

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

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


エピローグ:Chromeチームは、ユーザー側のJSからコンソールを無効にすることはバグであると判断し、問題修正してこの手法を無効にしました。その後、ユーザーをself-xssから保護するために追加の保護が追加されました。


10
Chromeはアップデートを行いましたが、この男は、再び修正をした:kspace.in/blog/2014/06/21/...
ロジャーGajraj

3
@Alf、オプトアウトページにヘルプページが表示され、この保護をオフにすることはできません。
arm.localhost 2015年

168
一部のユーザーの愚かさのために開発者ツールを壊さないでください。このような「解決策」は、私を百万の太陽の怒りで燃やすようにします。
ジョナサンダンラップ

85
GoogleはChromeの「安全な」バージョンをリリースする必要があると思います。DevToolsは必要ありません。自動更新を強制的に実行して、このバージョンに一度だけ切り替える必要があります。実際に違いに気づき、DevToolsを必要とする開発者は、「怖い」バージョンをダウンロードする必要があります。実際、ダウンロードページで直接「怖い」と「安全」のラベルを付け、「ソーシャルエンジニアリングの攻撃により怖いバージョンをダウンロードするよう指示されたため、ここにいる可能性があります。しないでください。これを行う。" FBの開発者がクリエイティブであることを祝福してください!
MonkeyZeus 2016年

11
@ n00bその警告メッセージは単なるconsole.logです。
gcampbell

91

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

これにより、コンソールのオートコンプリートは警告なしに失敗しますが、コンソールに入力されたステートメントは実行に失敗します(例外がログに記録されます)。

参照:


48

どのページでもそれをトリガーすることができませんでした。これのより堅牢なバージョンはそれを行います:

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

console.log('test');

出力のスタイルを設定するには:JavaScriptコンソールの色

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


1を冷却するが、それでも、同じ上書きwindow.console.log = function(){//empty}し、使用にconsole.logを
超クール

32

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

編集:

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

これが別の可能性です。今回は、直接に、上のレベルにフック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]場合、次の出力が予想されます。

ここに画像の説明を入力してください

InjectedScript._evaluateAndWrapまったく同じ式をモンキーパッチで評価すると、次の出力が得られます。

ここに画像の説明を入力してください

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

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

また、見とるis - InjectedScriptHost-オブジェクトを。これは、インスペクターを操作し、インスペクターの内部を少し洞察するいくつかのメソッドを提供します。

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

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

ここに画像の説明を入力してください

編集の終わり


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

そのうちの1つは Function.prototype.call

Chromeは、次のようにcalleval関数を使用InjectedScriptHostして入力された式を評価しますthisArg

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

これを考えると、あなたがのために聞くことができるthisArgcallであることevaluateと、最初の引数(への参照を取得します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);  
        }
    };
}

たとえば、評価が拒否されたというエラーをスローできます。

ここに画像の説明を入力してください

ここで例として入力された式はに渡す前のCoffeeScriptのコンパイラに渡されるevaluate関数が。


25

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セキュリティエラーをスローするためにオーバーライドするだけです。


24

Facebookがそれを行うことができたので、これは実際に可能です。まあ、実際のWeb開発ツールではなく、コンソールでのJavaScriptの実行です。

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

ただし、このタイプのクライアント側セキュリティをバイパスする他の方法があるため、これは実際にはあまり効果がありません。

それがクライアント側であると言うとき、それはサーバーの制御外で発生するので、それについてあなたができることはほとんどありません。Facebookがなぜこれを行うのかを尋ねている場合、これは実際にはセキュリティのためではありませんが、JavaScriptを知らない通常のユーザーがコンソールでコードを実行する(読む方法がわからない)ことを防ぐためです。これは、自動ライカーサービスや他のFacebook機能ボットが要求することを実行した後、ほとんどの場合、コンソールで実行するJavaScriptの一部を提供することを約束するサイトでは一般的です。

Facebookほど多くのユーザーがいない場合は、Facebookが行っていることを実行する必要はないと思います。

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

ここに画像の説明を入力してください

ここに画像の説明を入力してください

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

アンカーを検査します。

ここに画像の説明を入力してください

コードをhrefに貼り付け:

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ここに画像の説明を入力してください

結論は、サーバー側の検証であり、セキュリティを最初にしてから、クライアント側で検証する必要があります。


11

フェイスブックがコンソールを無効にすることができた時代以来、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(){};
}

9

私の簡単な方法ですが、このテーマのさらなるバリエーションに役立ちます。すべてのメソッドをリストし、それらを役に立たないものに変更します。

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

5

内部的にdevtoolsは名前付きのIIFEを挿入します getCompletionsは、ページに挿入します。これは、Devtoolsコンソール内でキーが押されたときに呼び出されます。

その機能源を見る上書きできるいくつかのグローバル関数が使用されています。

Errorコンストラクターを使用することでgetCompletions、Devtoolsから呼び出されたときに含まれるコールスタックを取得できます。


例:

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


それはかなり素晴らしいですが、それはまたページをクラッシュさせます。
Derek━會功夫

これ以上のユーザー入力を抑制する唯一の方法(私は見つけた)
samdd

無限ループを使用する代わりにエラーをスローできるかどうか疑問に思います。編集:テスト済み、機能しません。
Derek━會功夫

これは、トライキャッチブロックです。おそらく、ブロックの上の関数をオーバーライドできますが、自動補完が妨げられるだけです(評価ではありません)
samdd

2

簡単な解決策!

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

1
これはどのように無効にしconsole.log()ますか?
Red

1
console.log()コンソールが常にクリーンアップされていても問題ではなくなりました:)
Mohmmad Ebrahimi Aval

これは悪い考えです。ハッカーは端末からトレースしてすべてのログを見ることができます。
GFxJamal 2018年

4
ログの保持にフラグを付けた場合、console.clear()は何もしません:P
Zibri

0

私は次の方法で行きます:

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

  },
  set: function() {

  }
});

-2

これは、弱いコードを放置するためのセキュリティ対策ではありません。この戦略を実装する前に、脆弱なコードの永続的な解決策を常に入手し、ウェブサイトを適切に保護してください

私の知る限り、これまでのところ最高のツールは、コンテンツを更新または置換することによってページの整合性を通常に戻すだけの複数の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秒間隔は、訪問者が使用している古いコンピューターに大きな影響を与える可能性があるため、秒を適切な量に設定します


これ...これは良いアプローチではありません。
RozzA
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.