Der*_*會功夫 1652 javascript facebook google-chrome-devtools
显然,由于最近的骗局,开发人员工具被人们利用来发布垃圾邮件,甚至用来"破解"帐户.Facebook已经阻止了开发人员工具,我甚至无法使用控制台.
他们是怎么做到的??One Stack Overflow帖子声称这是不可能的,但Facebook证明他们错了.
只需转到Facebook并打开开发人员工具,在控制台中键入一个字符,然后弹出此警告.无论你投入什么,它都不会被执行.
这怎么可能?
他们甚至在控制台中阻止了自动完成:
Alf*_*Alf 2397
我是Facebook的安全工程师,这是我的错.我们正在为一些用户测试这一点,看看它是否可以减慢用户被欺骗将(恶意)JavaScript代码粘贴到浏览器控制台中的一些攻击.
需要明确的是:一般来说,试图阻止黑客客户端是一个坏主意 ; 这是为了防止特定的社会工程攻击.
如果你最终进入测试组并对此感到恼火,抱歉.我试图让旧的退出页面(现在的帮助页面)尽可能简单,同时仍然可怕到至少阻止一些受害者.
实际代码与@ joeldixon66的链接非常相似; 没有充分理由,我们的情况要复杂得多.
Chrome包含所有控制台代码
with ((console && console._commandLineAPI) || {}) {
<code goes here>
}
Run Code Online (Sandbox Code Playgroud)
...所以网站重新定义console._commandLineAPI
:
Object.defineProperty(console, '_commandLineAPI',
{ get : function() { throw 'Nooo!' } })
Run Code Online (Sandbox Code Playgroud)
这还不够(试试吧!),但那是主要的伎俩.
结语:Chrome团队决定从用户端JS中取消控制台是一个错误并修复了问题,导致此技术无效.之后,添加了额外的保护以保护用户免受自我xss的侵害.
Sal*_*n A 83
我使用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);
Run Code Online (Sandbox Code Playgroud)
这样,控制台自动完成将无声地失败,而在控制台中键入的语句将无法执行(将记录异常).
参考文献:
Wil*_*ill 43
我无法在任何页面上触发它.一个更强大的版本可以做到这一点:
window.console.log = function(){
console.error('The developer console is temp...');
window.console.log = function() {
return false;
}
}
console.log('test');
Run Code Online (Sandbox Code Playgroud)
设置输出样式:JavaScript控制台中的颜色
编辑思考@ joeldixon66有正确的想法:从控制台«::: KSpace :::禁用JavaScript执行
Mor*_*ler 30
除了重新定义之外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);
Run Code Online (Sandbox Code Playgroud)
它有点冗长,但我想我对它提出了一些意见
通常情况下,例如,如果用户评估[1,2,3,4]
您希望得到以下输出:
在monkeypatching InjectedScript._evaluateAndWrap
评估相同的表达式后,给出以下输出:
当你看到指示输出的小左箭头仍然存在时,但这次我们得到一个对象.在表达式的结果中,数组[1,2,3,4]
表示为描述其所有属性的对象.
我建议尝试评估此表达式,包括那些产生错误的表达式.这很有趣.
此外,看一看的is
- InjectedScriptHost
-对象.它提供了一些方法,可以深入了解检查员的内部情况.
当然,您可以拦截所有信息并仍然将原始结果返回给用户.
只需用console.log (res)
以下a 替换else路径中的return语句即可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);
}
};
}
Run Code Online (Sandbox Code Playgroud)
你可以抛出一个错误,评价被拒绝了.
下面是一个示例,其中输入的表达式在传递给evaluate
函数之前传递给CoffeeScript编译器.
Fiz*_*han 23
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$$) {
}
})();
Run Code Online (Sandbox Code Playgroud)
他们只是覆盖console._commandLineAPI
以抛出安全错误.
Jom*_*ejo 23
这实际上是可能的,因为Facebook能够做到这一点.好吧,不是实际的Web开发人员工具,而是在控制台中执行Javascript.
这真的不会做太多,因为有其他方法可以绕过这种类型的客户端安全性.
当你说它是客户端时,它发生在服务器的控制之外,因此你无能为力.如果你问为什么Facebook仍然这样做,这不是为了安全,而是为了保护那些不知道javascript的普通用户运行代码(他们不知道如何阅读)进入控制台.这对于承诺自动播放器服务或其他Facebook功能机器人的网站来说很常见,在您执行他们要求您执行的操作之后,在大多数情况下,他们会为您提供在控制台中运行的javascript片段.
如果你没有Facebook那样多的用户,那么我认为没有必要去做Facebook正在做的事情.
即使你在控制台中禁用Javascript,仍然可以通过地址栏运行javascript.
如果浏览器在地址栏中禁用了javascript,(当您将代码粘贴到Google Chrome中的地址栏时,它会删除短语'javascript:')将javascript粘贴到其中一个链接中仍然可以通过inspect元素.
检查锚:
在href中粘贴代码:
底线是服务器端验证,安全应该是第一个,然后是客户端.
我的简单方法,但它可以帮助进一步改变这个主题.列出所有方法并将其更改为无用.
Object.getOwnPropertyNames(console).filter(function(property) {
return typeof console[property] == 'function';
}).forEach(function (verb) {
console[verb] =function(){return 'Sorry, for security reasons...';};
});
Run Code Online (Sandbox Code Playgroud)
自从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(){};
}
Run Code Online (Sandbox Code Playgroud)
在内部,devtools 注入了一个命名getCompletions
为页面的 IIFE ,当在 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);
});
Run Code Online (Sandbox Code Playgroud)