JavaScript 函數(shù)劫持,也就是老外提到的 javascript hijacking 技術。最早還是和劍心同學討論問題時偶然看到的一段代碼,大概這樣寫的:
window.alert = function(s) {};
覺得這種用法很巧妙新穎,和 API Hook 異曲同工,索性稱之為 javascript function hook,也就是函數(shù)劫持。通過替換 js 函數(shù)的實現(xiàn)來達到劫持這個函數(shù)調用的目的,一個完整的 hook alert 函數(shù)例子如下:
<!--1.htm-->
[js] view plaincopy
<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 的同學們看到這個代碼一定會心的一笑,先保存原函數(shù)實現(xiàn),然后替換為我們自己的函數(shù)實現(xiàn),添加我們自己的處理邏輯后最終再調用原來的函數(shù)實現(xiàn),這樣這個 alert 函數(shù)就被我們劫持了。原理非常簡單,下面舉些典型的應用來看看我們能利用它來做些什么。
1.實現(xiàn)一個簡易的 javascript debugger,這里說是 debugger 比較標題黨,其實只是有點類似于 debugger 的功能,主要利用 js 函數(shù)劫持來實現(xiàn)函數(shù)的 break point,來看看個簡單的例子:
<script type="text/javascript">
<!--
var _eval = eval;
eval = function(s) {
if (confirm("eval 被調用 \ n\n 調用函數(shù) \ n" + eval.caller + "\n\n 調用參數(shù) \ 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 函數(shù)劫持中斷函數(shù)執(zhí)行,并顯示參數(shù)和函數(shù)調用者代碼,來看一個完整例子的效果:
>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]給出。
2.設置陷阱實時捕捉跨站測試者,搞跨站的人總習慣用 alert 來確認是否存在跨站,如果你要監(jiān)控是否有人在測試你的網(wǎng)站 xss 的話,可以在你要監(jiān)控的頁面里 hook alert 函數(shù),記錄 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>
當然,你這個函數(shù)要加到頁面的最開始,而且還要比較隱蔽一些,赫赫,你甚至可以使 alert 不彈框或者彈個警告框,讓測試者抓狂一把。
3.實現(xiàn) DOM XSS 自動化掃描,目前一般的 XSS 自動化掃描的方法是從 http 返回結果中搜索特征來確定是否存在漏洞,但是這種方法不適用于掃描 DOM XSS,因為 DOM XSS 是由客戶端腳本造成的,比如前段時間劍心發(fā)現(xiàn)的 google 的跨站 (見附錄 [2]) 原理如下:
document.write(document.location.hash);
這樣的跨站無法反映在 http response 里,所以傳統(tǒng)掃描方法沒法掃描出來。但是如果你從上個例子里受到啟發(fā)的話,一定會想到設置陷阱的辦法,DOM XSS 最終導致 alert 被執(zhí)行,所以我們 hook alert 函數(shù)設置陷阱,如果 XSS 成功則會去調用 alert 函數(shù),觸發(fā)我們的陷阱記錄結果,這樣就可以實現(xiàn) DOM XSS 的自動化掃描,陷阱代碼類似于上面。
4.靈活的使用 js 劫持輔助你的頁面代碼分析工作,比如分析網(wǎng)頁木馬時,經(jīng)常會有通過 eval 或者 document.write 來進行加密的情況,于是我們編寫段 hook 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);
當然你還能想到更多的靈活應用。