1. 개요
외국인이 언급하는 자바스크립트인 자바스크립트 기능 하이재킹
하이재킹 기술. 제가 처음 본 것은 Kenshin과 문제를 논의할 때 대략 다음과 같이 작성된 코드였습니다.
window.alert = function(s) {};
이 사용법은 매우 기발하고 참신하다고 생각합니다. API Hook과 유사하므로 간단히 javascript 함수라고 부릅니다.
Hook, 즉 함수 하이재킹(Function Hijacking)입니다. 이 함수 호출을 가로채는 목적은 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('Hello World!')" value="test" /> </body> </html>
API 완료
Hook 학생들은 이 코드를 보면 확실히 웃을 것입니다. 먼저 원래 함수 구현을 저장한 다음 이를 자체 함수 구현으로 대체하고 자체 처리 논리를 추가한 다음 마지막으로 원래 함수 구현을 호출하여 경고 함수를 만듭니다. 납치. 원리는 매우 간단합니다. 여기에 우리가 무엇을 할 수 있는지 보여주는 몇 가지 일반적인 응용 프로그램이 있습니다.
2. 적용 예시
1. 간단한 자바스크립트를 구현합니다.
디버거, 여기서는 디버거가 더 헤드라인을 사로잡는다고 합니다. 사실 디버거의 기능과 약간 유사할 뿐입니다. 주로 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 faff960df4899d2a505ee22a0fd0f9a7 - 함수에 중단점을 설정합니다. 예: "bp
window.alert".
bl - 모든 중단점을 나열합니다.
bc 711729f84a46114b1f16c0185d795994 -
지정된 숫자(예: "bc 0")로 중단점을 제거합니다.
도움말
>bp window.alert
* "window.alert" 함수의 중단점
>bl
* 1개의 중단점:
0 - window.alert가 추가되었습니다.
>bc 0
* "window.alert" 함수의 중단점이 성공적으로 삭제되었습니다.
다음은 중단점 설정, 중단점 보기 및 중단점 삭제에 대한 데모입니다. 전체 코드는 이 기사의 부록 [1]에 나와 있습니다.
2.
교차 사이트 테스터를 실시간으로 캡처하도록 트랩을 설정하십시오. 교차 사이트를 수행하는 사람들은 항상 경고를 사용하여 누군가가 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 하이재킹을 사용하여 페이지 코드 분석 작업을 지원합니다. 예를 들어 웹페이지 트로이 목마를 분석할 때 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>
입력 상자에 암호화된 코드를 입력합니다:
eval(unescape("alert(1);"));
디코딩된 코드를 출력 상자에 출력합니다:
alert(1)
물론 더 유연한 응용 프로그램을 생각할 수도 있습니다.)
3.
강력한 xss 플레이로드를 작성하려면 하이재킹 방지에 관해 이야기해야 합니다. 해결해야 할 두 가지 문제가 있습니다.
하이재킹 방지 방법. 납치됐어?
강탈당한 것으로 확인되면, 납치에 대응하는 방법은 무엇인가요?
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