ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript 関数ハイジャックに関する簡単な説明 [xfocus から転載]_javascript スキル

JavaScript 関数ハイジャックに関する簡単な説明 [xfocus から転載]_javascript スキル

PHP中文网
PHP中文网オリジナル
2016-05-16 19:06:081338ブラウズ

1. 概要
外国人が言及したJavaScriptの機能ハイジャック ハイジャック技術。私が最初に目にしたのは、Kenshin と問題について話し合っていたときのコードで、大まかに次のように書かれていました。
この使い方は非常に賢くて斬新だと思うので、API Hook に似ているので、単純に JavaScript 関数と呼びます。 フック、つまり関数ハイジャックです。この関数呼び出しをハイジャックする目的は、js 関数の実装を置き換えることによって達成されます。完全なフック アラート関数の例は次のとおりです。
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(&#39;Hello 
World!&#39;)" value="test" /> 
</body> 
</html>
API を実行しました このコードを見たフックの学生は、間違いなく意図的に微笑むでしょう。まず元の関数実装を保存し、それを独自の関数実装に置き換え、独自の処理ロジックを追加して、最後に元の関数実装を呼び出します。これにより、アラート関数は We になります。乗っ取られた。原理は非常に単純です。これを使って何ができるかを示すために、いくつかの典型的なアプリケーションを示します。

2. アプリケーションの例
1. 簡単な JavaScript を実装します。 デバッガ、ここではデバッガがより注目を集めていると言われていますが、実際にはデバッガの機能に少し似ており、主に関数のブレークを実現するために js 関数のハイジャックを使用します。 ポイントとして、簡単な例を見てみましょう:

<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

デバッグ コマンド:
bp - 関数にブレークポイントを設定します。例: "bp window.alert"。
bl - すべてのブレークポイントをリストします。
bc - 指定した番号でブレークポイントを削除します (例: "bc 0")。
>bp window.alert
* 関数「window.alert」のブレークポイント
>bl
* 1 ブレークポイント:
0 - window.alert
>bc 0
* 関数「window.alert」のブレークポイントは正常に削除されました。
ここでは、ブレークポイントの設定、ブレークポイントの表示、およびブレークポイントの削除のデモを示します。完全なコードは、この記事の付録 [1] に記載されています。
2. クロスサイト テスターをリアルタイムで捕捉するためのトラップを設定します。クロスサイトを行う人は常にアラートを使用して、誰かが Web サイトの XSS をテストしているかどうかを監視する必要があります。監視したいページ。 アラート関数、アラートの呼び出し状況を記録します:

もちろん、関数はページの先頭に追加する必要があり、さらに非表示にする必要があります。へへ、アラートをポップしないようにすることもできます。警告ボックスが表示されるとテスターは興奮します。
<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>
3. DOM を実装する XSS 自動スキャン 現在の一般的な XSS 自動スキャン方法は、http の返された結果から特性を検索して脆弱性があるかどうかを判断することですが、この方法は DOM であるため、DOM XSS のスキャンには適していません。 XSS はクライアント側のスクリプトによって引き起こされます。たとえば、Kenshin によって以前に発見された Google のクロスサイトの原理は次のとおりです (付録 [2] を参照)。

document.write(document.location.hash);
このようなクロスサイトは http に反映できません。 そのため、従来のスキャン方法ではスキャンできません。しかし、前の例に触発された人なら、DOM をセットアップする方法を必ず思いつくでしょう。 XSS により最終的にアラートが実行されるため、アラート関数をフックしてトラップをセットアップします。XSS が成功すると、アラート関数が呼び出され、トラップがトリガーされて結果が記録され、DOM を実装できるようになります。 XSS の自動スキャンの場合、トラップ コードは上記と同様です。
4. js ハイジャックを柔軟に使用して、ページのコード分析作業を支援します。たとえば、Web ページのトロイの木馬を分析する場合、暗号化は 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(&#39;input&#39;).value);" value="decode" /> 
<br 
/> 
output: 
<textarea id="output" cols="80" 
rows="10"></textarea> 
</body> 
</html>
eval(unescape("alert(1);"));

デコードされたコードを出力ボックスに出力します:
alert(1);
もちろん、より柔軟なアプリケーションを考えることもできます:)

3.
ハイジャックについて話すときは、ハイジャック対策についても話さなければなりません。堅牢な xss プレイロードを作成したい場合は、解決すべき 2 つの問題があります。
ハイジャック対策が行われているかどうかを判断する方法。乗っ取られた?
乗っ取られたことに気付いた場合、どのように対処すればよいでしょうか?
1. 関数がハイジャックされているかどうかを判断するのは簡単です。関数がフックされる前と後の違いを比較するのは簡単です。

<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 

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。