Home >Web Front-end >JS Tutorial >A brief discussion on javascript function hijacking [reprinted from xfocus]_javascript skills
1. Overview
javascript function hijacking, which is the javascript mentioned by foreigners
hijacking technology. The earliest I saw was a piece of code when I was discussing a problem with Kenshin. It was roughly written like this:
window.alert = function(s) {};
I think this usage is very clever and novel. It is similar to API Hook, so I simply call it javascript function.
Hook, that is, function hijacking. The purpose of hijacking this function call is achieved by replacing the implementation of the js function. A complete hook alert function example is as follows:
ef293dd28e50c56deda8416c7d1c5781
<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>
Have done API
Hook students will definitely smile knowingly when they see this code. We first save the original function implementation, then replace it with our own function implementation, add our own processing logic, and finally call the original function implementation, so that the alert function is We hijacked. The principle is very simple. Here are some typical applications to see what we can do with it.
2. Application examples
1. Implement a simple javascript
Debugger, here it is said that debugger is more headline-grabbing. In fact, it is just a bit similar to the function of debugger. It mainly uses js function hijacking to realize the break of the function.
point, let’s take a look at a simple example:
<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>
Interrupt function execution through js function hijacking, and display parameters and function caller code, let’s take a look at the effect of a complete example:
>help
debug commands:
bp 788a85521940291aa43ea2004446ddaa - set a breakpoint on a function, e.g. "bp
window.alert".
bl - list all breakpoints.
bc 4b0cbb54b83399225d8068f177c4acca -
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.
Here is a demonstration of setting breakpoints, viewing breakpoints and deleting breakpoints. The complete code is given in the appendix [1] of this article.
2.
Set traps to capture cross-site testers in real time. People who do cross-site always use alert to confirm whether there is cross-site. If you want to monitor whether someone is testing your website for XSS, you can hook it in the page you want to monitor.
alert function, records the alert calling situation:
<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>
Of course, your function should be added to the beginning of the page, and it should be more hidden. Hehe, you can even make the alert not pop up or pop up. Warning boxes make testers go crazy.
3. Implement DOM
XSS automated scanning. The current general XSS automated scanning method is to search for characteristics from http return results to determine whether there are vulnerabilities. However, this method is not suitable for scanning DOM XSS because DOM
XSS is caused by client-side scripts. For example, the principle of Google's cross-site discovered by Kenshin some time ago (see Appendix [2]) is as follows:
document.write(document.location.hash);
Such cross-site cannot be reflected in http
response, so traditional scanning methods cannot scan it out. But if you were inspired by the previous example, you will definitely think of a way to set up a trap. DOM
XSS eventually causes the alert to be executed, so we hook the alert function to set up a trap. If the XSS is successful, the alert function will be called, triggering our trap to record the results, so that the DOM can be implemented
For automated scanning of XSS, the trap code is similar to the above.
4.
Flexibly use js hijacking to assist your page code analysis work. For example, when analyzing web page Trojans, encryption is often performed through eval or document.write, so we write a hook
Small tools for eval and document.write to assist in decryption:
<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>
Enter the encrypted code in the input box:
eval(unescape("alert(1);"));
Output the decoded code in the output box:
alert(1);
Of course you can think of more flexible applications:)
3. Anti-hijacking
When talking about hijacking, we must talk about anti-hijacking. If you want to write a robust xss playload, you need to consider anti-hijacking. There are two problems to solve:
How to judge whether it has been hijacked?
If you find that you have been hijacked, how to counteract the hijacking?
1. Determine whether a function has been hijacked. This is easy to do. Write a small program to compare the difference before and after a function is hooked:
<textarea id="tb1" cols="80" rows="8"></textarea> <script type="text/javascript"> <!-- document.getElementById("tb1").value = eval + "\n"; var _eval = eval; eval = function(s) { alert(s); _eval(s); } document.getElementById("tb1").value += eval; //--> </script>
结果:
function eval() {
[native code]
}
function(s) {
alert(s);
_eval(s);
}
我们发现那些内置函数是[native
code],而自定义的则是具体的函数定义,用这个特征就可以简单的检测函数是否被劫持:
function checkHook(proc) {
if
(proc.toString().indexOf("[native code]") > 0) {
return false;
} else
{
return true;
}
}
2.
如何反劫持,第一个想法就是恢复被劫持的函数,如果劫持的人把原函数保存在某个变量里那还好办,直接调用原函数就可以了,但是劫持者自己也没保存副本怎么办,只能自己创建个新的环境,然后用新环境里的干净的函数来恢复我们这里被hook了的,怎么创建新环境?整个新的iframe好了,里面就是个全新的环境。ok,动手吧:
function unHook(proc) { var f = document.createElement("iframe"); f.style.border = "0"; f.style.width = "0"; f.style.height = "0"; document.body.appendChild(f); var d = f.contentWindow.document; d.write("<script type=\"text/javascript\">window.parent.escape = escape;<\/script>"); d.close(); }
综合1、2节,整个测试代码如下:
cece1a3bb9e7a7a5bb4659461fe8ec41
<script type="text/javascript"> <!-- escape = function(s) { return s; } //--> </script> <html> <body> <input type="button" onclick="javascript: test();" value="test" /> <script type="text/javascript"> <!-- function test() { alert(escape("s y")); if (checkHook(escape)) { unHook(escape); } alert(escape("s y")); } function checkHook(proc) { if (proc.toString().indexOf("[native code]") > 0) { return false; } else { return true; } } function unHook(proc) { var f = document.createElement("iframe"); f.style.border = "0"; f.style.width = "0"; f.style.height = "0"; document.body.appendChild(f); var d = f.contentWindow.document; d.write("<script type=\"text/javascript\">window.parent.escape = escape;<\/script>"); d.close(); } //--> </script> </body> </html>
3. 不是上面两个问题都解决了么,为什么要有第3节?因为那不是个最好的解决办法,既然我们可以创建全新的iframe,何不把代码直接放到全新iframe里执行呢,这样做的话绿色环保,既不用考虑当前context里的hook问题,也不用改动当前context,不会影响本身的程序执行。给出两个比较通用点的函数:
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); } 把你的payload封装进一个函数,然后调用这两个方法来在iframe里执行: function payload() { // your code goes here } var f = createIframe(top); injectScriptIntoIframe(f, payload);
四、最后
由于国内很少有见文章提及这个东西,所以才草成这篇,希望能够抛砖引玉。由于本人水平有限,难免有错误或者疏漏之处请谅解,没有说清楚的地方,欢迎和我交流。
还有就是一些不得不感谢的人,感谢剑心一直以来毫无保留的交流,感谢黑锅多次鼓励我把自己的心得体会写成文字,感谢幻影所有的朋友们、B.C.T的朋友们以及群里那帮经常一起扯淡的朋友们。
广告一下,没法幻影blog的朋友,可以添加hosts来突破:
72.14.219.190 pstgroup.blogspot.com