[javascript] Facebook은 브라우저의 통합 개발자 도구를 어떻게 비활성화합니까?
최근의 사기로 인해 개발자 도구는 사람들이 스팸을 게시하고 계정을 “해킹”하는 데 사용됩니다. Facebook에서 개발자 도구를 차단했으며 콘솔을 사용할 수도 없습니다.
그들은 어떻게 했습니까? 하나의 스택 오버플로 게시물은 불가능하다고 주장 했지만 Facebook은 그것들을 잘못 입증했습니다.
Facebook으로 이동하여 개발자 도구를 열고 콘솔에 한 문자를 입력하면이 경고가 나타납니다. 무엇을 넣더라도 실행되지 않습니다.
이것이 어떻게 가능한지?
그들은 콘솔에서 자동 완성을 차단했습니다.
답변
나는 페이스 북의 보안 엔지니어이고 이것이 내 잘못이다. 우리는 사용자가 (악의적 인) JavaScript 코드를 브라우저 콘솔에 붙여 넣도록 속이는 공격을 느리게 할 수 있는지 확인하기 위해 일부 사용자에 대해 이것을 테스트하고 있습니다.
해커를 클라이언트 측에서 차단하는 것은 일반적으로 나쁜 생각 입니다. 이것은 특정 사회 공학 공격 으로부터 보호하는 것 입니다.
테스트 그룹에 들어가서 이것에 대해 화가났다면 죄송합니다. 나는 적어도 일부 희생자들을 막을만큼 무서워하면서 오래된 옵트 아웃 페이지 (현재 도움말 페이지 )를 가능한 한 단순 하게 만들려고 노력했습니다 .
실제 코드는 @ joeldixon66의 링크 와 매우 유사합니다 . 우리는 아무 이유없이 조금 더 복잡합니다.
Chrome은 모든 콘솔 코드를
with ((console && console._commandLineAPI) || {}) {
<code goes here>
}
… 그래서 사이트는 다시 console._commandLineAPI
던지기를 재정의 합니다.
Object.defineProperty(console, '_commandLineAPI',
{ get : function() { throw 'Nooo!' } })
이것으로는 충분하지 않습니다 (시도하십시오!) , 이것이 주된 속임수입니다.
에필로그 : 크롬 팀은 사용자 측 JS에서 콘솔을 격파하는 버그라고 결정 및 문제 해결 이 기술의 무효를 렌더링. 그 후 self-xss로부터 사용자 를 보호하기 위해 추가 보호 기능이 추가되었습니다 .
답변
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);
이를 통해 콘솔 자동 완성은 자동으로 실패하지만 콘솔에 입력 된 명령문은 실행되지 않습니다 (예외는 기록됨).
참고 문헌 :
답변
어느 페이지에서나 트리거 할 수 없었습니다. 이것의 더 강력한 버전은 그것을 할 것입니다 :
window.console.log = function(){
console.error('The developer console is temp...');
window.console.log = function() {
return false;
}
}
console.log('test');
출력 스타일을 지정하려면 : JavaScript 콘솔의 색상
편집 생각 @ joeldixon66 은 올바른 아이디어를 가지고 있습니다 : 콘솔에서 JavaScript 실행 비활성화«::: KSpace :::
답변
재정의 외에도 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
매우 동일한 표현을 평가하는 monkeypatching 후 다음과 같은 결과가 나타납니다.
보시다시피 출력을 나타내는 작은 왼쪽 화살표가 여전히 있지만 이번에는 객체를 얻습니다. 식의 결과에서 배열 [1,2,3,4]
은 모든 속성이 설명 된 개체로 나타납니다.
오류를 생성하는 표현식을 포함하여이 표현식과 해당 표현식을 평가하는 것이 좋습니다. 꽤 흥미 롭습니다.
또한, 한 번 봐 걸릴 is
– InjectedScriptHost
– 객체. 인스펙터의 내부를 가지고 약간의 통찰력을 얻는 방법을 제공합니다.
물론 모든 정보를 가로 채어 원래 결과를 사용자에게 반환 할 수 있습니다.
else 경로의 return 문을 console.log (res)
다음으로 대체하십시오 return res
. 그런 다음 다음과 같이 끝납니다.
편집 끝
이것은 Google에서 수정 한 이전 버전입니다. 따라서 더 이상 가능한 방법은 아닙니다.
그중 하나가 Function.prototype.call
Chrome은 다음 call
과 InjectedScriptHost
같이 eval 함수를 사용 하여 입력 한 표현식을 평가합니다.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);
}
};
}
예를 들어, 평가가 거부되었다는 오류가 발생할 수 있습니다.
다음은 입력 한 표현식이 함수에 전달되기 전에 CoffeeScript 컴파일러에 전달 되는 예evaluate
입니다.
답변
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
보안 오류가 발생하도록 무시 합니다.
답변
페이스 북이 그것을 할 수 있었기 때문에 이것은 실제로 가능합니다. 실제 웹 개발자 도구가 아니라 콘솔에서 Javascript를 실행하는 것입니다.
다음을 참조하십시오 : Facebook은 브라우저의 통합 개발자 도구를 어떻게 비활성화합니까?
이 유형의 클라이언트 측 보안을 우회하는 다른 방법이 있기 때문에 실제로는 그렇게하지 않습니다.
클라이언트 측이라고 말하면 서버의 제어 외부에서 발생하므로 할 수있는 일이 많지 않습니다. Facebook에서 여전히이 작업을 수행하는 이유를 묻는 경우 이는 실제로 보안을위한 것이 아니라 Javascript를 모르는 일반 사용자가 코드를 읽는 방법 (알지 못하는)을 콘솔로 실행하지 못하도록 보호하는 것입니다. 이는 자동 요청 서비스 나 다른 Facebook 기능 봇을 요구하는 사이트가 대부분의 경우 콘솔에서 실행할 자바 스크립트를 제공하는 사이트에서 일반적입니다.
Facebook만큼 많은 사용자가 없다면 Facebook 이하는 일을 할 필요가 없다고 생각합니다.
콘솔에서 자바 스크립트를 비활성화하더라도 주소 표시 줄을 통해 자바 스크립트를 실행할 수 있습니다.
브라우저가 주소 표시 줄에서 자바 스크립트를 비활성화하면 (Chrome의 주소 표시 줄에 코드를 붙여 넣을 때 ‘javascript :’구문을 삭제합니다) inspect 요소를 통해 링크 중 하나에 javascript를 붙여 넣을 수 있습니다.
앵커를 점검하십시오.
href에 코드 붙여 넣기 :
결론은 서버 측 유효성 검사이며 보안이 먼저 수행 된 다음 클라이언트 측에서 수행해야합니다.
답변
페이스 북이 콘솔을 비활성화 할 수있는 시간 이후 크롬이 많이 바뀌 었습니다 …
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(){};
}