一、概述
今天接触到了一个陌生的名词:函数劫持,查了一些资料记录一下。
函数劫持的意思是在一个函数运行之前把它劫持下来,添加我们想要的功能,然后再调用原来的函数执行。这也是常见的钩子函数的原理之一。
举一个简单的例子:
var _alert = alert;
window.alert = function(s) {
console.log('alert:', s);
_alert(s);
}
二、应用
- XSS攻击经常使用
alert
测试是否存在跨站,所以可以通过劫持alert
函数来监测是否有人在攻击你的网站。在监测的页面劫持alert
函数,记录调用情况。function report(caller) { var img=new Image(); img.src=`http://www.site.com/getReport.php?caller=${encodeURIComponent(caller)}`; } var _alert = window.alert window.alert = function(s) { report(alert.caller) _alert(s) }
- 自定义业务功能。业务代码经常会有新需求的加入,对原代码进行修改匹配,常常比较耗费时间,这个时候就可以使用函数劫持,在不修改原业务逻辑的前提下,增加新功能。
三、劫持与反劫持
- 判断某个函数是否被劫持?
对于native代码内置函数如function foo() {console.log(foo);} alert.toString() // "function alert() { [native code] }" foo.toString() // "function foo() {console.log(foo);}"
alert
,输出打印时会显示为[native code]
,而自定义的函数会显示函数定义的内容,通过这个方法可以检查函数是否被劫持。
注意到有一种伪装成native function的方式如下:var fakeAlert = (function(){}).bind(null); console.log(window.alert.toString()); // function alert() { [native code] } console.log(fakeAlert.toString()); // function () { [native code] }
bind(null)
伪装后的函数不带函数名,所以更严格的检查需要检查函数名是否为空。 - 如何反劫持?
通常劫持的都是一些可以向用户反馈信息的API,如alert
、eval
、console.log
等。这些native代码通常难以还原,所以可以通过还原出一个纯净的环境iframe
,在iframe
中调用相关函数。
举个例子,对于涉及到反馈信息的API可以封装到函数中,调用方法在iframe中执行:function createIframe(w) { var d = w.document; var newIframe = d.createElement("iframe"); newIframe.style.width = 0; newIframe.style.height = 0; d.body.appendChild(newIframe); newIframe.contentWindow.document.write("<html><body></body></html>"); return newIframe; } function injectScriptIntoIframe(f, proc) { var d = f.contentWindow.document; var s = "<script>\n(" + proc.toString() + ")();\n</script>"; d.write(s); }
// 将信息相关封装到函数中,在iframe中调用 function payload() { // your code goes here } var f = createIframe(top); injectScriptIntoIframe(f, payload);
四、参考
广告时间
飞书是字节跳动旗下办公套件产品,其将即时沟通、在线协作、音视频会议、日历、云盘、工作台等功能进行了深度整合,为用户提供一站式协作体验。目前,飞书服务的客户已经覆盖了科技互联网、信息技术、制造、建筑地产、企业服务、教育、媒体等多个领域。欢迎投递字节跳动飞书团队,有海量前端后端HC~扫描二维码或者点击链接投递,认准飞书团队👍~
【校招】内推码: HZNVPHS,投递链接: job.toutiao.com/s/JaeUCoc
【社招】投递链接: job.toutiao.com/s/JaevUNo