本文深入解析JavaScript函数劫持(Hijacking)技术,通过替换原生函数实现逻辑控制。文章展示了如何劫持alert、eval等核心API,并详细列举了四大实战场景:构建简易JS Debugger、部署XSS测试陷阱、自动化扫描DOM XSS漏洞以及辅助解密加密脚本。通过具体代码示例,阐述该技术在安全测试与防御中的灵活应用。
JavaScript函数劫持概述
一、概述 JavaScript函数劫持,即业界所称的JavaScript Hijacking技术。这一概念最初源于与开发者讨论时偶然发现的一段代码,其核心逻辑为: window.alert = function(s) {}; 这种通过重写函数实现来拦截调用的方式,与系统级的API Hook有着异曲同工之妙,因此可将其定义为JavaScript Function Hook(函数劫持)。其本质是通过替换JS函数的内部实现,从而完全掌控该函数的调用行为。以下是一个完整的劫持alert函数的示例代码: <!--1.htm-->
代码如下:
<script type="text/javascript">
<!--
var _alert = alert;
window.alert = function(s) {
if (confirm("是否要弹框框,内容是\"" + s + "\"?")) {
_alert(s);
}
}
//-->
</script>
<html>
<body>
<input type="button" onclick="javascript: alert('Hello World!')" value="test" />
</body>
</html> 熟悉API Hook的开发者看到上述代码会感到熟悉:首先保存原函数的引用,然后将其替换为自定义函数。在自定义函数中,我们可以添加额外的处理逻辑,最后再调用原始函数。这样,alert函数就被成功劫持。原理虽简单,但其应用场景广泛。下文将通过几个典型案例,展示如何利用这一技术解决实际问题。
函数劫持的典型应用场景
二、应用举例
构建简易JavaScript Debugger
1. 实现一个简易的JavaScript Debugger 这里所谓的“Debugger”略显夸张,实际上它仅具备类似断点调试的功能。主要利用函数劫持来设置函数的Break Point。以下是一个简单的示例:
代码如下:
<script type="text/javascript">
<!--
var _eval = eval;
eval = function(s) {
if (confirm("eval被调用\n\n调用函数\n" + eval.caller + "\n\n调用参数\n" + s)) {
_eval(s);
}
}
//-->
</script>
<html>
<head>
</head>
<body>
<script type="text/javascript">
<!--
function test() {
var a = "alert(1)";
eval(a);
}
function t() {
test();
}
t();
//-->
</script>
</body>
</html> 通过劫持JS函数来中断执行,并显示调用参数及调用者代码。以下是完整示例的运行效果:
>help
debug commands:
bp <function name> - set a breakpoint on a function, e.g. "bp window.alert".
bl - list all breakpoints.
bc <breakpoint number> - remove a breakpoint by specified number, e.g. "bc 0".
help - help information.
>bp window.alert
* breakpoint on function "window.alert" added successfully.
>bl
* 1 breakpoints:
0 - window.alert
>bc 0
* breakpoint on function "window.alert" deleted successfully.
上述演示展示了如何设置断点、查看断点列表以及删除指定编号的断点。完整代码见本文附录[1]。
部署XSS测试陷阱与防御
2. 设置陷阱实时捕捉跨站测试者 进行跨站脚本(XSS)测试时,测试人员常习惯使用alert来确认漏洞是否存在。若需监控网站是否遭受XSS测试,可在目标页面中劫持alert函数,并记录其调用情况:
代码如下:
<script type="text/javascript">
<!--
function log(s) {
var img = new Image();
img.style.width = img.style.height = 0;
img.src = "http://yousite.com/log.php?caller=" + encodeURIComponent(s);
}
var _alert = alert;
window.alert = function(s) {
log(alert.caller);
_alert(s);
}
//-->
</script> 需要注意的是,该脚本必须插入到页面最前端,且尽量保持隐蔽。此外,可以修改行为使其不弹出对话框,或弹出误导性警告框,以此干扰测试人员。
DOM XSS自动化扫描实现
3. 实现DOM XSS自动化扫描 目前主流的XSS自动化扫描方法主要通过搜索HTTP响应中的特征字符串来判断漏洞存在与否。然而,这种方法无法有效扫描DOM XSS,因为DOM XSS是由客户端脚本逻辑触发的。例如,剑心此前发现的Google跨站漏洞(见附录[2])原理如下:
document.write(document.location.hash);
此类漏洞不会反映在HTTP响应中,因此传统扫描器无法检测。但如果受到前述示例的启发,我们可以采用“设置陷阱”的思路:DOM XSS最终往往导致alert执行,因此通过劫持alert函数设置陷阱,一旦XSS成功触发alert,即可记录结果。从而实现DOM XSS的自动化扫描,陷阱代码逻辑与前述示例类似。
辅助解密与代码分析工具
4. 灵活使用JS劫持辅助页面代码分析 在分析网页木马时,常遇到通过eval或document.write进行代码加密的情况。为此,我们可以编写一个劫持eval和document.write的小工具,辅助解密过程:
代码如下:
<script type="text/javascript">
<!--
var _eval = eval;
eval = window.execScript = window.document.write = window.document.writeln = function(s) {
document.getElementById("output").value = s;
}
//-->
</script>
<html>
<body>
input:
<textarea id="input" cols="80" rows="10"></textarea>
<input type="button" onclick="javascript: _eval(document.getElementById('input').value);" value="decode" />
<br />
output:
<textarea id="output" cols="80" rows="10"></textarea>
</body>
</html> 在input框中输入加密代码:
eval(unescape("%61%6C%65%72%74%28%31%29%3B"));
在output框中即可输出解码后的代码:
alert(1);
当然,读者还可以发掘更多灵活的应用场景。
23下一页阅读全文