javascript كيف يقوم Facebook بتعطيل أدوات المطور المتكاملة للمتصفح؟





4 Answers

لقد حددت البرنامج النصي لـ buster في وحدة تحكم Facebook باستخدام أدوات مطوري برامج Chrome. هنا هو البرنامج النصي مع تغييرات طفيفة لسهولة القراءة. لقد أزلت وحدات البت التي لم أتمكن من فهمها:

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

مع هذا ، تفشل عملية الإكمال التلقائي لوحدة التحكم بدون مطالبة أثناء فشل عبارات الكتابة في وحدة التحكم في تنفيذ (سيتم تسجيل الاستثناء).

المراجع:

javascript facebook google-chrome-devtools

لذا على ما يبدو بسبب عمليات الاحتيال الأخيرة ، يتم استغلال أدوات المطور من قبل الأشخاص لنشر رسائل غير مرغوب فيها ، بل واستخدامها أيضًا في "الاختراق". لقد حظر Facebook أدوات المطور ، ولا يمكنني حتى استخدام وحدة التحكم.

كيف فعلوا ذلك؟؟ ادعت إحدى المشاركات في أنه غير ممكن ، لكن Facebook أثبت أنه خطأ.

ما عليك سوى الانتقال إلى Facebook وفتح أدوات المطورين ، وكتابة حرف واحد في وحدة التحكم ، وينبثق هذا التحذير. بغض النظر عن ما وضعت فيه ، لن يتم تنفيذه.

كيف يكون هذا ممكنا؟

حتى أنها حظرت الإكمال التلقائي في وحدة التحكم:




إلى جانب إعادة تعريف console._commandLineAPI ، هناك بعض الطرق الأخرى لاقتحام InjectedScriptHost على متصفحات WebKit ، لمنع أو تغيير تقييم التعبيرات المدخلة في وحدة تحكم المطور.

تصحيح:

قام Chrome بإصلاح هذا في إصدار سابق. - التي يجب أن تكون قبل فبراير 2015 ، حيث أنني خلقت جوهر في ذلك الوقت

إذن هناك احتمال آخر. هذه المرة نحن ربط في ، مستوى أعلاه ، مباشرة في 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] كنت تتوقع الإخراج التالي:

بعد monkeypatching InjectedScript._evaluateAndWrap بتقييم نفس التعبير ، يعطي الإخراج التالي:

وكما ترى فإن السهم الصغير إلى اليسار ، والذي يشير إلى الخرج ، لا يزال موجودًا ، لكن هذه المرة نحصل على شيء. حيث يتم التعبير عن نتيجة المصفوفة [1,2,3,4] ككائن مع جميع خصائصه الموضحة.

أوصي بمحاولة تقييم هذا وهذا التعبير ، بما في ذلك تلك التي تولد الأخطاء. انها مثيرة للاهتمام للغاية.

بالإضافة إلى ذلك ، إلقاء نظرة على كائن - InjectedScriptHost - . يوفر بعض الأساليب للعب مع الحصول على نظرة ثاقبة في الداخلية المفتش.

بالطبع ، يمكنك اعتراض كل هذه المعلومات وما زالت ترجع النتيجة الأصلية إلى المستخدم.

فقط استبدال عبارة الإرجاع في مسار آخر بواسطة console.log (res) بعد return res . ثم ينتهي بك الأمر مع ما يلي.

نهاية التحرير

هذه هي النسخة السابقة التي تم إصلاحها بواسطة Google. وبالتالي لم يعد ممكنًا.

واحدة من ذلك هو ربط في Function.prototype.call

يقيّم Chrome التعبير الذي تم إدخاله عن طريق call وظيفة eval الخاصة به مع InjectedScriptHost as thisArg

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

بالنظر إلى ذلك ، يمكنك الاستماع إلى هذا thisArg من call الجاري 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);  
        }
    };
}

هل يمكن على سبيل المثال رمي خطأ ، تم رفض التقييم.

في ما يلي example حيث يتم تمرير التعبير الذي تم إدخاله إلى مترجم CoffeeScript قبل تمريره إلى وظيفة evaluate .




هذا ممكن فعلاً منذ أن تمكن الفيس بوك من القيام بذلك. حسنا ، ليس أدوات مطور الويب الفعلي ولكن تنفيذ جافا سكريبت في وحدة التحكم.

انظر هذا: كيف يقوم Facebook بتعطيل أدوات المطور المتكاملة للمتصفح؟

هذا حقا لن تفعل الكثير على الرغم من أن هناك طرق أخرى لتجاوز هذا النوع من الأمن جانب العميل.

عندما تقول أنه من جانب العميل ، فإنه يحدث خارج سيطرة الخادم ، لذلك ليس هناك الكثير الذي يمكنك فعله حيال ذلك. إذا كنت تسأل لماذا لا يزال فيس بوك يفعل ذلك ، فهذا ليس بالأمر الأمني ​​ولكن لحماية المستخدمين العاديين الذين لا يعرفون جافا سكريبت من تشغيل الكود (أنهم لا يعرفون القراءة) في وحدة التحكم. هذا أمر شائع بالنسبة للمواقع التي تعد بتقديم خدمة تلقائية أو برامج تتبع وظائف أخرى في Facebook بعد قيامك بما تطلب منك القيام به ، وفي معظم الحالات ، تعطيك قصاصة من جافا سكريبت لتشغيلها في وحدة التحكم.

إذا لم يكن لديك الكثير من المستخدمين مثل Facebook ، فلا أعتقد أن هناك حاجة للقيام بما يفعله Facebook.

حتى إذا قمت بتعطيل Javascript في وحدة التحكم ، فسيظل تشغيل javascript عبر شريط العناوين ممكنًا.

وإذا عطّل المستعرض جافا سكريبت في شريط العنوان ، (عندما تقوم بلصق الكود على شريط العنوان في Google Chrome ، فإنه يحذف عبارة "javascript: ') اللصيقة بجافا سكريبت إلى أحد الروابط عبر عنصر الفحص ما زال ممكنًا.

تفقد المرساة:

رمز اللصق في href:

الخط الأساسي هو التحقق من جانب الخادم ويجب أن يكون الأمان أولاً ، ثم القيام بعد ذلك العميل.




طريقي البسيط ، لكنه يمكن أن يساعد في إجراء مزيد من الاختلافات حول هذا الموضوع. قائمة جميع الأساليب وتغييرها إلى عديمة الفائدة.

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



Related