it-swarm-vi.com

Facebook vô hiệu hóa Công cụ dành cho nhà phát triển tích hợp của trình duyệt như thế nào?

Vì vậy, rõ ràng vì những trò gian lận gần đây, các công cụ dành cho nhà phát triển bị mọi người khai thác để đăng spam và thậm chí được sử dụng để "hack" tài khoản. Facebook đã chặn các công cụ dành cho nhà phát triển và tôi thậm chí không thể sử dụng bảng điều khiển.

Enter image description here

Làm thế nào mà họ làm điều đó ?? Bài đăng One Stack Overflow tuyên bố rằng điều đó là không thể , nhưng Facebook đã chứng minh họ sai.

Chỉ cần truy cập Facebook và mở các công cụ dành cho nhà phát triển, nhập một ký tự vào bảng điều khiển và cảnh báo này bật lên. Không có vấn đề gì bạn đặt vào, nó sẽ không được thực thi.

Sao có thể như thế được?

Họ thậm chí đã chặn tự động hoàn thành trong bảng điều khiển:

Enter image description here

1602
Derek 朕會功夫

Tôi là một kỹ sư bảo mật tại Facebook và đây là lỗi của tôi. Chúng tôi đang thử nghiệm điều này cho một số người dùng để xem liệu nó có thể làm chậm một số cuộc tấn công mà người dùng bị lừa để dán mã JavaScript (độc hại) vào bảng điều khiển trình duyệt hay không.

Nói rõ hơn: cố gắng chặn tin tặc phía khách hàng là một ý tưởng tồi nói chung; Đây là để bảo vệ chống lại một tấn công kỹ thuật xã hội cụ thể .

Nếu bạn đã kết thúc trong nhóm thử nghiệm và cảm thấy khó chịu vì điều này, xin lỗi . Tôi đã cố gắng tạo trang từ chối cũ (bây giờ trang trợ giúp ) đơn giản nhất có thể trong khi vẫn đủ đáng sợ để dừng lại ít nhất một số của các nạn nhân.

Mã thực tế khá giống với @ joeldixon66's link ; chúng ta phức tạp hơn một chút không có lý do chính đáng.

Chrome kết thúc tất cả mã bảng điều khiển trong

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

... để trang web xác định lại console._commandLineAPI để ném:

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

Đây là không hoàn toàn đủ (hãy thử!) , Nhưng đó là Thủ thuật chính.


Phần kết: Nhóm Chrome đã quyết định rằng việc đánh bại bảng điều khiển từ JS phía người dùng là một lỗi và đã khắc phục sự cố , khiến kỹ thuật này không hợp lệ. Sau đó, bảo vệ bổ sung đã được thêm vào bảo vệ người dùng khỏi tự xss

2339
Alf

Tôi đã định vị tập lệnh buster console của Facebook bằng các công cụ dành cho nhà phát triển Chrome. Đây là kịch bản với những thay đổi nhỏ cho khả năng đọc. Tôi đã loại bỏ các bit mà tôi không thể hiểu:

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

Với điều này, tự động hoàn thành giao diện điều khiển thất bại trong khi các câu lệnh được nhập trong bàn điều khiển sẽ không thực thi (ngoại lệ sẽ được ghi lại).

Tài liệu tham khảo:

78
Salman A

Tôi không thể lấy nó để kích hoạt nó trên bất kỳ trang nào. Một phiên bản mạnh mẽ hơn của điều này sẽ làm điều đó:

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

console.log('test');

Để định kiểu đầu ra: Màu sắc trong bảng điều khiển JavaScript

Chỉnh sửa Suy nghĩ @ joeldixon66 có ý tưởng đúng: Vô hiệu hóa thực thi JavaScript từ bảng điều khiển "::: KSpace :: :

40
Will

Bên cạnh việc xác định lại console._commandLineAPI, có một số cách khác để xâm nhập vào In tiêmScripthost trên trình duyệt WebKit, để ngăn chặn hoặc thay đổi việc đánh giá các biểu thức được nhập vào bảng điều khiển của nhà phát triển.

Chỉnh sửa:

Chrome đã sửa lỗi này trong một bản phát hành trước đây. - phải có trước tháng 2 năm 2015, khi tôi tạo Gist tại thời điểm đó

Vì vậy, đây là một khả năng khác. Lần này chúng tôi nối vào, một cấp độ ở trên, trực tiếp vào InjectedScript chứ không phải InjectedScriptHost trái ngược với phiên bản trước.

Điều này thật tuyệt, vì bạn có thể trực tiếp vá khỉ InjectedScript._evaluateAndWrap thay vì phải dựa vào InjectedScriptHost.evaluate vì điều đó giúp bạn kiểm soát tốt hơn những gì sẽ xảy ra.

Một điều khá thú vị là, chúng ta có thể chặn kết quả bên trong khi một biểu thức được ước tính và trả lại cho người dùng thay vì hành vi thông thường.

Đây là mã, thực hiện chính xác điều đó, trả về kết quả bên trong khi người dùng đánh giá một cái gì đó trong bảng điều khiển.

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

Hơi dài dòng một chút, nhưng tôi nghĩ tôi đã đặt một số bình luận vào đó

Vì vậy, thông thường, nếu người dùng, ví dụ, đánh giá [1,2,3,4] bạn sẽ mong đợi kết quả đầu ra sau:

enter image description here

Sau khi kết nối InjectedScript._evaluateAndWrap đánh giá biểu thức rất giống nhau, đưa ra kết quả sau:

enter image description here

Như bạn thấy mũi tên nhỏ bên trái, biểu thị đầu ra, vẫn ở đó, nhưng lần này chúng ta có một đối tượng. Trong đó kết quả của biểu thức, mảng [1,2,3,4] được biểu diễn dưới dạng một đối tượng với tất cả các thuộc tính được mô tả.

Tôi khuyên bạn nên cố gắng đánh giá biểu thức này và biểu thức đó, bao gồm cả những biểu hiện tạo ra lỗi. Nó khá thú vị.

Ngoài ra, hãy xem đối tượng is - InjectedScriptHost - . Nó cung cấp một số phương pháp để chơi và có được một chút cái nhìn sâu sắc về nội bộ của thanh tra.

Tất nhiên, bạn có thể chặn tất cả thông tin đó và vẫn trả lại kết quả ban đầu cho người dùng.

Chỉ cần thay thế câu lệnh return trong đường dẫn khác bằng một console.log (res) theo sau return res. Sau đó, bạn sẽ kết thúc với những điều sau đây.

enter image description here

Kết thúc chỉnh sửa


Đây là phiên bản trước được Google sửa. Do đó không phải là một cách có thể nữa.

Một trong số đó được nối vào Function.prototype.call

Chrome đánh giá biểu thức đã nhập bằng calling chức năng eval của nó với InjectedScriptHostthisArg

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

Vì điều này, bạn có thể lắng nghe thisArg of callevaluate và nhận được tham chiếu đến đối số đầu tiên (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);  
        }
    };
}

Bạn có thể ví dụ: ném một lỗi, rằng đánh giá đã bị từ chối.

enter image description here

Đây là một ví dụ trong đó biểu thức đã nhập được chuyển đến trình biên dịch CoffeeScript trước khi chuyển nó sang hàm evaluate.

28
Moritz Roessler

Netflix cũng thực hiện tính năng này

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

Họ chỉ ghi đè console._commandLineAPI để ném lỗi bảo mật.

22
Fizer Khan

Điều này thực sự khả thi vì Facebook đã có thể làm điều đó . Chà, không phải các công cụ phát triển web thực tế mà là việc thực thi Javascript trong bảng điều khiển.

Xem điều này: Facebook vô hiệu hóa Công cụ dành cho nhà phát triển tích hợp của trình duyệt như thế nào?

Điều này thực sự sẽ không làm được gì nhiều vì có nhiều cách khác để vượt qua loại bảo mật phía máy khách này.

Khi bạn nói nó ở phía máy khách, nó sẽ xảy ra ngoài tầm kiểm soát của máy chủ, vì vậy bạn không thể làm gì nhiều về nó. Nếu bạn đang hỏi tại sao Facebook vẫn làm điều này, thì điều này không thực sự bảo mật mà là để bảo vệ người dùng bình thường không biết javascript chạy mã (mà họ không biết cách đọc) vào bảng điều khiển. Điều này là phổ biến đối với các trang web hứa hẹn dịch vụ tự động thích hoặc các bot chức năng khác của Facebook sau khi bạn làm những gì họ yêu cầu bạn làm, trong hầu hết các trường hợp, họ cung cấp cho bạn một đoạn javascript để chạy trong bảng điều khiển.

Nếu bạn không có nhiều người dùng như Facebook, thì tôi không nghĩ rằng Facebook cần phải làm gì.

Ngay cả khi bạn tắt Javascript trong bảng điều khiển, việc chạy javascript qua thanh địa chỉ vẫn có thể.

 enter image description here

 enter image description here

và nếu trình duyệt vô hiệu hóa javascript tại thanh địa chỉ, (Khi bạn dán mã vào thanh địa chỉ trong Google Chrome, nó sẽ xóa cụm từ 'javascript:') để dán javascript vào một trong các liên kết thông qua phần tử kiểm tra.

Kiểm tra mỏ neo:

 enter image description here

Dán mã trong href:

 enter image description here

 enter image description here

 enter image description here

Điểm mấu chốt là xác thực phía máy chủ và bảo mật phải là đầu tiên, sau đó thực hiện phía máy khách sau.

20
Jomar Sevillejo

Chrome đã thay đổi rất nhiều kể từ khi facebook có thể vô hiệu hóa bảng điều khiển ... 

Theo tháng 3 năm 2017, điều này không còn hoạt động nữa. 

Điều tốt nhất bạn có thể làm là vô hiệu hóa một số chức năng của bàn điều khiển, ví dụ:

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

Cách đơn giản của tôi, nhưng nó có thể giúp các biến thể tiếp theo về chủ đề này . Liệt kê tất cả các phương pháp và thay đổi chúng thành vô dụng.

  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

Các devtools nội bộ đưa một IIFE có tên getCompletions vào trang, được gọi khi nhấn một phím bên trong bảng điều khiển Devtools. 

Nhìn vào nguồn của hàm đó , nó sử dụng một vài hàm toàn cục có thể được ghi đè.

Bằng cách sử dụng Error constructor, có thể nhận được ngăn xếp cuộc gọi, sẽ bao gồm getCompletions khi được gọi bởi Devtools.


Thí dụ:

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

một giải pháp đơn giản!

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

Tôi sẽ đi dọc theo con đường:

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

  },
  set: function() {

  }
});
0
Zibri

Đây không phải là biện pháp bảo mật cho mã yếu không được giám sát. Luôn nhận được giải pháp lâu dài cho mã yếu và bảo mật trang web của bạn đúng cách trước khi thực hiện chiến lược này

Theo tôi, công cụ tốt nhất sẽ là thêm nhiều tệp javascript chỉ đơn giản là thay đổi tính toàn vẹn của trang trở lại bình thường bằng cách làm mới hoặc thay thế nội dung. Vô hiệu hóa công cụ dành cho nhà phát triển này sẽ không phải là ý tưởng lớn nhất vì việc bỏ qua luôn được đặt ra vì mã là một phần của trình duyệt và không phải là kết xuất máy chủ, do đó nó có thể bị bẻ khóa. 

Nếu bạn có js file one kiểm tra thay đổi <element> trên các yếu tố quan trọng và js file twojs file three kiểm tra xem tệp này có tồn tại trong mỗi khoảng thời gian bạn sẽ khôi phục toàn vẹn trên trang trong khoảng thời gian đó không. 

Hãy lấy một ví dụ về 4 tệp và cho bạn biết ý tôi là gì. 

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

Bây giờ điều này chỉ để hiển thị nó hoạt động trên tất cả các tệp và thẻ là tốt

   #heading {
   background-color:red;
   }

Nếu bạn đặt tất cả các tệp này lại với nhau và xây dựng ví dụ, bạn sẽ thấy chức năng của biện pháp này. Điều này sẽ ngăn chặn một số lần tiêm không cần thiết nếu bạn triển khai chính xác trên tất cả các yếu tố quan trọng trong tệp chỉ mục của mình, đặc biệt là khi làm việc với PHP.

Tại sao tôi chọn tải lại thay vì quay lại giá trị bình thường trên mỗi thuộc tính là thực tế là một số kẻ tấn công có thể có một phần khác của trang web đã được định cấu hình và sẵn sàng và nó làm giảm số lượng mã. Việc tải lại sẽ loại bỏ tất cả công việc khó khăn của kẻ tấn công và anh ta có thể sẽ đi chơi ở đâu đó dễ dàng hơn.

Một lưu ý khác: Điều này có thể trở thành rất nhiều mã vì vậy hãy giữ nó sạch sẽ và đảm bảo thêm các định nghĩa vào nơi chúng thuộc về để chỉnh sửa dễ dàng trong tương lai. Đồng thời đặt giây thành số tiền bạn muốn là khoảng thời gian 1 giây trên các trang lớn có thể có tác động mạnh mẽ đến các máy tính cũ mà khách truy cập của bạn có thể đang sử dụng

0
user9374996