ChatGPT解决这个技术问题 Extra ChatGPT

Facebook 如何禁用浏览器的集成开发者工具?

显然,由于最近的骗局,开发人员工具被人们利用来发布垃圾邮件,甚至被用来“破解”帐户。 Facebook已经屏蔽了开发者工具,我什至不能使用控制台。

https://i.stack.imgur.com/Wiatp.png

他们是怎么做到的?? One Stack Overflow post claimed that it is not possible,但 Facebook 已经证明他们错了。

只需去 Facebook 并打开开发者工具,在控制台中输入一个字符,就会弹出此警告。无论你输入什么,它都不会被执行。

这怎么可能?

他们甚至阻止了控制台中的自动完成功能:

https://i.stack.imgur.com/j0Zmx.png

只是为了好玩:console.log = function() {}
您是否找到解决他们如何阻止控制台中的自动完成功能的解决方案
@AkshayHegde 这是阻止来自开发工具的任何代码执行引起的副作用。
@Derek朕会功夫 可以分享一下代码吗
仅供参考,它不再被 chrome 阻止。

C
Community

我是 Facebook 的安全工程师,这是我的错。我们正在为一些用户进行测试,看看它是否可以减缓一些攻击,这些攻击会诱使用户将(恶意)JavaScript 代码粘贴到浏览器控制台中。

需要明确的是:试图阻止黑客客户端通常是bad idea;这是为了防止出现specific social engineering attack

如果你最终进入了测试组并且对此感到恼火,对不起。我试图使旧的退出页面(现在是 help page)尽可能简单,同时仍然足够可怕以阻止至少 一些 的受害者。

实际代码与 @joeldixon66's link 非常相似;我们的有点复杂,没有充分的理由。

Chrome 将所有控制台代码封装在

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

...因此该网站将 console._commandLineAPI 重新定义为抛出:

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

这是 not quite enough (try it!),但这是主要技巧。

结语:Chrome 团队认为从用户端 JS 击败控制台是一个错误,fixed the issue,导致该技术无效。之后,为 protect users from self-xss 添加了额外的保护。


Chrome 确实进行了更新,但这个人再次进行了修复:kspace.in/blog/2014/06/21/…
@Alf,您的选择退出页面现在显示帮助页面,不可能关闭此保护。
请不要因为某些用户的愚蠢而破坏开发者工具。像这样的“解决方案”让我愤怒地燃烧着一百万个太阳。
我认为谷歌需要发布一个“安全”版本的 Chrome,没有 DevTools,并强制任何自动更新的人只切换到这个版本一次。任何真正注意到差异并需要 DevTools 的开发人员都应该下载“可怕”版本。事实上,直接在下载页面上将它们标记为“可怕”和“安全”,并通过明确说明“你很可能在这里,因为社会工程攻击告诉你下载可怕版本;请不要做这个。”上帝保佑你们 FB 开发者如此有创意!
@n00b 该警告消息只是一个 console.log
S
Salman A

我使用 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);

有了这个,控制台自动完成会静默失败,而在控制台中键入的语句将无法执行(将记录异常)。

参考:

对象.defineProperty

Object.getOwnPropertyDescriptor

Chrome 的 console.log 函数(关于格式化输出的提示)


C
Community

我无法让它在任何页面上触发它。一个更强大的版本可以做到这一点:

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

console.log('test');

要设置输出样式:Colors in JavaScript console

编辑 认为 @joeldixon66 有正确的想法:Disable JavaScript execution from console « ::: KSpace :::


很酷,但仍然覆盖相同的 window.console.log = function(){//empty} 并使用 console.log
F
Farzad Karimi

除了重新定义 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],您会期望以下输出:

https://i.stack.imgur.com/FLAnR.png

在monkeypatching InjectedScript._evaluateAndWrap 评估相同的表达式后,给出以下输出:

https://i.stack.imgur.com/1fOfj.png

如您所见,指示输出的小左箭头仍然存在,但这次我们得到了一个对象。在表达式的结果中,数组 [1,2,3,4] 表示为一个对象,并描述了它的所有属性。

我建议尝试评估这个和那个表达式,包括那些产生错误的表达式。这很有趣。

此外,请查看 is - InjectedScriptHost - 对象。它提供了一些方法来使用并深入了解检查器的内部结构。

当然,您可以截获所有这些信息并仍然将原始结果返回给用户。

只需将 else 路径中的 return 语句替换为 return res 后的 console.log (res)。然后你会得到以下结果。

https://i.stack.imgur.com/4X4Ep.png

编辑结束

这是由 Google 修复的先前版本。因此不再是一种可能的方式。

其中一个正在连接到 Function.prototype.call

Chrome 通过 call 将其 eval 函数与 InjectedScriptHost 作为 thisArg 来计算输入的表达式

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

鉴于此,您可以侦听 callthisArgevaluate 并获取对第一个参数 (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);  
        }
    };
}

例如,您可以抛出一个错误,即评估被拒绝。

https://i.imgur.com/YYDovbt.png

这是一个 example,其中输入的表达式在传递给 evaluate 函数之前先传递给 CoffeeScript 编译器。


F
Fizer Khan

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 以引发安全错误。


A
Ashraf.Shk786

这实际上是可能的,因为 Facebook 能够做到。好吧,不是实际的 Web 开发人员工具,而是在控制台中执行 Javascript。

看到这个:How does Facebook disable the browser's integrated Developer Tools?

这真的不会做太多,因为还有其他方法可以绕过这种类型的客户端安全性。

当您说它是客户端时,它发生在服务器的控制之外,因此您无能为力。如果你问为什么 Facebook 仍然这样做,这并不是为了安全,而是为了保护不知道 javascript 的普通用户不会在控制台中运行代码(他们不知道如何阅读)。这对于承诺自动点赞服务或其他 Facebook 功能机器人的网站来说很常见,在您完成他们要求您执行的操作后,他们会在大多数情况下为您提供一段 javascript 以在控制台中运行。

如果你没有 Facebook 那么多的用户,那么我认为没有必要做 Facebook 正在做的事情。

即使您在控制台中禁用了 Javascript,仍然可以通过地址栏运行 javascript。

https://i.stack.imgur.com/pCtTk.png

https://i.stack.imgur.com/QxDLs.png

如果浏览器在地址栏禁用了 javascript,(当您将代码粘贴到 Google Chrome 中的地址栏时,它会删除短语“javascript:”)仍然可以通过检查元素将 javascript 粘贴到其中一个链接中。

检查锚:

https://i.stack.imgur.com/VHXyy.png

在href中粘贴代码:

https://i.stack.imgur.com/hwmKo.png

https://i.stack.imgur.com/UTUFH.png

https://i.stack.imgur.com/kwLjP.png

底线是服务器端验证和安全性应该是第一位的,然后是客户端。


A
Alpha2k

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

D
Dusan Krstic

我的简单方法,但它可以帮助这个主题的进一步变化。列出所有方法并将它们更改为无用。

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

S
Sam Denty

在内部,devtools 将一个名为 getCompletions 的 IIFE 注入到页面中,当在 Devtools 控制台内按下一个键时调用该 IIFE。

查看 source of that function,它使用了一些可以被覆盖的全局函数。

通过使用 Error 构造函数,可以获得调用堆栈,当被 Devtools 调用时,它将包括 getCompletions

例子:

const disableDevtools = callback => { const original = Object.getPrototypeOf; Object.getPrototypeOf = (...args) => { if (Error().stack.includes("getCompletions")) callback();返回原始(...args); }; }; disableDevtools(() => { console.error("devtools 已被禁用"); while (1); });


这很整洁,但它也会使页面崩溃。
@Derek朕会功夫唯一的方法(我发现)来抑制进一步的用户输入
我想知道您是否可以抛出错误而不是使用无限循环。编辑:经过测试,不起作用。
@Derek朕会功夫它在一个try catch块中。您可能会覆盖块上方的功能,但它只会阻止自动完成(而不是评估)
可悲的是不起作用。我仍然可以通过按 -> chrome 上的三点 -> 更多工具 -> 开发人员工具来使用开发工具。
M
Mohmmad Ebrahimi Aval

一个简单的解决方案!

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

这如何禁用 console.log()
console.log() 当控制台不断被清理时不再重要:)
这是一个坏主意。黑客可以从他们的终端追踪并查看所有日志。
如果你标记 Preserve Logs,console.clear() 什么都不做:P
Z
Zibri

我会沿着这条路走:

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

  },
  set: function() {

  }
});

D
Dile

我这里有一个简单的方法:window.console = function () {}


R
Rupert M-M

在 Firefox 中它不会这样做,因为 Firefox 是一个开发者浏览器,我认为因为命令 WEBGL_debug_renderer_info is deprecated in Firefox and will be removed. Please use RENDERER 和错误 Referrer Policy: Less restricted policies, including ‘no-referrer-when-downgrade’, ‘origin-when-cross-origin’ and ‘unsafe-url’, will be ignored soon for the cross-site request: https://static.xx.fbcdn.net/rsrc.php/v3/yS/r/XDDAHSZfaR6.js?_nc_x=Ij3Wp8lg5Kz


佚名

这不是让弱代码无人看管的安全措施。在实施此策略之前,始终获得弱代码的永久解决方案并正确保护您的网站

据我所知,目前最好的工具是添加多个 javascript 文件,这些文件通过刷新或替换内容来简单地将页面的完整性更改为正常。禁用这个开发工具并不是最好的主意,因为绕过总是存在问题,因为代码是浏览器的一部分,而不是服务器渲染,因此它可能会被破解。

如果您有 js file one 检查重要元素的 <element> 更改,并且 js file twojs file three 检查此文件在每个周期内是否存在,您将在该周期内对页面进行完整的完整性恢复。

让我们以这 4 个文件为例,向您展示我的意思。

索引.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>

主文件.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

样式.css

现在这只是为了表明它也适用于所有文件和标签

   #heading {
   background-color:red;
   }

如果将所有这些文件放在一起并构建示例,您将看到此度量的功能。如果您在索引文件中的所有重要元素上正确实现它,尤其是在使用 PHP 时,这将防止一些不可预见的注入。

为什么我选择重新加载而不是更改回每个属性的正常值是因为一些攻击者可能已经配置并准备好网站的另一部分并且它减少了代码量。重装将消除攻击者的所有辛勤工作,他可能会去更轻松的地方玩耍。

另一个注意事项:这可能会变成很多代码,因此请保持干净,并确保将定义添加到它们所属的位置,以便将来轻松编辑。还将秒数设置为您喜欢的数量,因为大页面上的 1 秒间隔可能会对访问者可能使用的旧计算机产生巨大影响