Exploiting CORS:SOP与Jsonp劫持

栏目: Json · 发布时间: 5年前

内容简介:emmmmm,jsonp劫持已经是大佬们玩的剩下的了,然而在较大型的企业中还是存在不少的这种类型的漏洞,所以还是有必要学一学的。为了保护用户的安全,现代浏览器都使用了同源策略,不允许访问非同源的页面。然而还是有很多的需求去访问不同源页面的数据,怎么办?浏览器表示,拖鞋是不可能拖鞋的,一辈子都不可能拖鞋的。所以就出现了跨域这种概念。jsonp作为一种跨域方案,被广泛应用在较大互联网站点,而如果这种跨域方案存在安全问题,攻击者也可以利用。惯例,在了解jsonp劫持之前,先将前置的各种概念解释清楚。同源策略(S

简介

emmmmm,jsonp劫持已经是大佬们玩的剩下的了,然而在较大型的企业中还是存在不少的这种类型的漏洞,所以还是有必要学一学的。为了保护用户的安全,现代浏览器都使用了同源策略,不允许访问非同源的页面。然而还是有很多的需求去访问不同源页面的数据,怎么办?浏览器表示,拖鞋是不可能拖鞋的,一辈子都不可能拖鞋的。所以就出现了跨域这种概念。jsonp作为一种跨域方案,被广泛应用在较大互联网站点,而如果这种跨域方案存在安全问题,攻击者也可以利用。

SOP

惯例,在了解jsonp劫持之前,先将前置的各种概念解释清楚。同源策略(SOP),何为同源:

同协议

同域名

同端口

例: https://drops.org.cn 与:

http://drops.org.cn 不同协议

https://test.drops.org.cn 不同域名

http://drops.org.cn:8000 不同端口

于是它们都是不同源的。

正确了解SOP策略

如果不加注意,你也许会认为同源策略就是浏览器简单粗暴地阻止浏览器去请求,而恰恰相反,浏览器不会阻止脚本去访问,而是阻止 Response 。用一个小例子来试验一下。

<script src="http://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js">
$.get('https://drops.org.cn/catch.php')
</script>

catch.php是放在服务器的一个脚本,记录访问日志,将ip等信息写入文件。

对以上代码进行测试发现:

Exploiting CORS:SOP与Jsonp劫持

服务端:

Exploiting CORS:SOP与Jsonp劫持

同源策略阻止了返回资源。这个时候就有人会想到,既然是浏览器阻止返回资源,那么在CSRF攻击利用中,即使无法载入资源,攻击请求已经发出。是不是可以在只验证 referer 的CSRF中伪造 referer 达成CSRF攻击。我们试验 JQuery 在一个 Ajax 添加定制 referer 头。

<script type="text/javascript" src="http://cdn.static.runoob.com/libs/jquery/1.8.3/jquery.js">
</script>
<script type="text/javascript">
    $(document).ready(function(){
        $.ajax({
            type : "get",
            async: false,
            headers: {
              'Referer':'https://drops.org.cn'
            },
            url : "https://drops.org.cn",
            type: "json",
            success : function(data) {
                alert(data)
            }

        });
    });
</script>

当请求时,会发现浏览器阻止 Ajax 伪造Referer:

Exploiting CORS:SOP与Jsonp劫持

跨域与jsonp

同源策略虽然提高了安全性,但也给开发者造成了不便。于是一些常见的跨域解决方案便出现了:

  1. 降域
  2. CORS:跨域资源共享
  3. jsonp:Json With Padding

降域 使用于在子域名较多时,在js中使用 document.domain 降域为主域,于是整个子域都能去获取主域或则相互间加载。

CORS 跨域资源共享是一个W3C标准,是标准的跨域方案。简单来说,就是服务器只需要合理设置 Access-Control-Allow-Origin , Access-Control-Allow-Credentials , Access-Control-Expose-Headers 三个字段,客户端请求时加入 Origin: 字段,服务端判断该 Origin 是否在 Access-Control-Allow-Origin 规则中,若满足规则,则能成功请求数据。详细的CORS原理可在 http://www.ruanyifeng.com/blog/2016/04/cors.html

查看,写的非常详细。本文不再过多解释。

jsonp :在html标签里,一些标签利用 src , href 等属性去加载资源是没有跨域限制的。于是聪明的 程序员 就发明了 jsonp 这种跨域方案,虽然应用广泛,但却不是官方的。常见的可跨域标签有

<script src="..."></script>
<img src="...">
<video src="..."></video>
<audio src="..."></audio>
<embed src="...">
<frame src="...">
<iframe src="..."></iframe>
<link rel="stylesheet" href="...">
<applet code="..."></applet>
<object data="..." ></object>

而jsonp就是利用 scriptsrc 属性可加载任意资源的原理去进行跨域数据传输。

在现在的web等应用程序中,使用 json 传输数据是不二之选,但由于浏览器同源策略限制, javascript 无法直接去获取接口 json 数据。jsonp其实就是将json数据封装在一个js函数中,由 sciptsrc 去请求并返回这个函数。客户端获取到该函数之后执行该函数,我们暂时将此过程称之为一个 callback

而客户端要运行一个js函数,则需要知道这个函数的名字,这时服务端就不能去定义一个死的函数名,这样会造成业务间的高耦合,也不安全。因此这个函数名需要客户端去传输过来,服务端将请求函数名和json数据封装。这个过程在客户端表现为jsonp需要一回调函数。接下来举个简单的例子:

服务端的代码如下

<?php
header('Content-type: application/json');
//获取回调函数名
$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);
//json数据
$json_data = '["customername1","customername2"]';
//输出jsonp格式的数据
echo $jsoncallback . "(" . $json_data . ")";
?>

这个可以在 http://www.runoob.com/try/ajax/jsonp.php?jsoncallback=dr0op 请求。可以发现返回数据包如下:

dr0op(["customername1","customername2"])

jsoncallback 传递过去的就是函数名。服务端返回的是一个 函数调用 。可以理解为 dr0op 是一个函数,其中的 ["customername1","customername2"] 是函数参数,也是我们要传输的数据。而客户端只需要去编写一个 dr0op 函数,接收参数并处理,就获取到json数据了。这就是一个 callback

客户端可编写如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP 实例</title>
</head>
<body>
    <div id="divCustomers"></div>
    <script type="text/javascript">
function dr0op(result)
        {
            var html = '<ul>';
            for(var i = 0; i < result.length; i++)
            {
                html += '<li>' + result[i] + '</li>';
            }
            html += '</ul>';
            document.getElementById('divCustomers').innerHTML = html;
        }
</script>
<script type="text/javascript" src="http://www.runoob.com/try/ajax/jsonp.php?jsoncallback=dr0op"></script>
</body>
</html>

客户端获取数据库将数据写入 ul 节点中。查看输出:

Exploiting CORS:SOP与Jsonp劫持

可以发现,成功获取到数据。

jsonp劫持

如果jsonp传输的数据是较为敏感的数据,但是服务端并没有对客户来源页 referer 合理检测,那么攻击者只需要伪造一个页面,类似CSRF攻击那样,就可以获取敏感数据了。

这里来说一个典型的黑产案例:

有时候你不小心点击到了某个培训,医疗,或者保险之类的网站,你并没有去输入你的手机号,等一会就会有人打电话过来,问你需不需要他们的产品。这是黑产挖掘到了运营商的一个漏洞,然后利用漏洞泄漏用户手机号,将手机号发送到后台。其实这个漏洞有一部分就是jsonp劫持导致的:

Exploiting CORS:SOP与Jsonp劫持

Exploiting CORS:SOP与Jsonp劫持

至于为什么手机进行web访问运营商接口,运营商就可以获取手机号。大致因为运营商可以依据当前手机移动窝蜂网络如4G等,依据网络认证获取SIM卡手机号(非HTTP协议)。

具体的原理或许只有运营商通信商掌握。

jsonp劫持获取QQ号:

Exploiting CORS:SOP与Jsonp劫持

jsonp劫持泄漏信息:

Exploiting CORS:SOP与Jsonp劫持

空referer绕过检测

和CSRF一样,防御jsonp劫持可以去检测referer,由于直接使用浏览器打开为空的referer,而检测也会通常忽略这一点,只要攻击者让用户点击时利用浏览器特性发送空referer,即可桡过检测。

如,在 iframe 标签中使用 javascript 伪协议来实现空referer:

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

也可以时候data伪协议实现:

data:text/plain; base64,our_base64_encoded_code

Exploiting CORS:SOP与Jsonp劫持

jsonp劫持防御

1、严格安全的实现 CSRF 方式调用 JSON 文件:限制 Referer 、部署一次性 Token 等。

2、严格安装 JSON 格式标准输出 Content-Type 及编码( Content-Type : application/json; charset=utf-8 )。

3、严格过滤 callback 函数名及 JSON 里数据的输出。

4、严格限制对 JSONP 输出 callback 函数名的长度(如防御上面 flash 输出的方法)。

5、其他一些比较“猥琐”的方法:如在 Callback 输出之前加入其他字符(如:、回车换行)这样不影响 JSON 文件加载,又能一定程度预防其他文件格式的输出。还比如 Gmail 早起使用 AJAX 的方式获取 JSON ,听过在输出 JSON 之前加入 while(1) ;这样的代码来防止 JS 远程调用。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Erlang趣学指南

Erlang趣学指南

邓辉、孙鸣 / 人民邮电出版社 / 2016-9-7 / 79.00元

这是一本讲解Erlang编程语言的入门指南,内容通俗易懂,插图生动幽默,示例短小清晰,结构安排合理。书中从Erlang的基础知识讲起,融汇所有的基本概念和语法。内容涉及模块、函数、类型、递归、错误和异常、常用数据结构、并行编程、多处理、OTP、事件处理,以及所有Erlang的重要特性和强大功能。一起来看看 《Erlang趣学指南》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具