// 安全研究 · 2025-07-01

页面弹窗≠有效漏洞:揭秘 XSS 中的沙箱与子域名隔离

前言

跨站脚本攻击(Cross-Site Scripting,简称 XSS)是一种常见的安全漏洞,攻击者通过将恶意脚本注入到看似安全可靠的网站中,影响其他用户的正常使用。假设你使用了一个简单的 XSS 有效载荷,比如 alert(1),它会在执行时弹出一个窗口。虽然这个弹窗能直观地告诉你代码被触发,但它无法准确揭示一个关键信息:有效载荷究竟是在哪里执行的?相比之下,使用 alert(document.domain) 或 alert(window.origin) 能提供更具体的位置信息,帮助你判断是否发现了一个值得提交的漏洞。本文将深入探讨这些有效载荷的区别,并结合实例分析如何更高效地定位 XSS 问题。


什么是 XSS?

XSS 是一种典型的注入式攻击,攻击者通过向网站输入恶意脚本,使其在其他用户的浏览器中运行。例如,注入 alert(1) 后,如果浏览器弹出一个显示“1”的窗口,就说明脚本成功执行。这不仅证明了漏洞的存在,还暗示着该漏洞可能存在更严重的危害(如盗取 cookie)。

然而,仅仅看到弹窗并不足以判断漏洞的严重性。关键在于:脚本是在哪个域或环境中执行的?接下来,我们将剖析 alert(1) 的优缺点,并探讨为何更精确的定位方法不可或缺。


alert(1):直观但有限的有效载荷

优点一:视觉反馈明显

alert(1) 的最大优势在于它的直观性。无论你面对的是一个输入框繁多的复杂网页,还是一个简单的表单,只需注入这个有效载荷,弹窗一出现,你就知道脚本被触发了。通过调整 alert() 的参数(比如 alert("test")),你还能快速定位具体生效的注入点。

小技巧:在测试时,可以“遍地开花”式地使用 alert(1),然后观察哪里会触发,效率极高。

优点二:适用于受限环境

在某些客户端 JavaScript 框架中(如早期的模板引擎),开发者可能只允许有限的脚本功能,比如打印变量或进行简单计算,而禁止复杂的恶意代码注入。这时,alert(1) 依然能派上用场。为什么?因为 window 对象是网页运行的核心依赖,window.alert(1) 通常不会被禁用。而同一个 window 对象还承载着攻击者梦寐以求的数据,例如 window.localStorage 或 window.document.cookie。如果 alert(1) 成功执行,往往意味着你可能触及了一个高危漏洞,值得进一步挖掘并报告。

示例:某些旧版框架允许 window.alert(1),却限制其他操作,这为测试提供了突破口。

局限性:缺乏上下文信息

尽管 alert(1) 用起来简单直接,但它有一个致命缺陷——它无法告诉你脚本执行的具体上下文。==弹窗出现并不意味着你找到了一个可利用的漏洞==。为什么?让我们通过一个实际案例来剖析。


案例分析:Google Blogger 中的 XSS 测试

实验步骤

假设你正在使用 Google 的 Blogger 平台创建博客。探索功能时,你可能会发现它允许注入 HTML 和 JavaScript。操作如下:

  1. 创建一篇新博客文章。
  2. 在左侧栏的“布局”菜单中,点击“添加小工具”。
  3. 选择“HTML/JavaScript”选项,输入以下代码:
    <script>alert(1);</script>
  4. 保存并完成博客内容(随便输入一段文字),然后点击右上角的“预览”按钮。

结果令人兴奋:一个显示“1”的弹窗出现了!浏览器地址栏显示的 URL 是 https://www.blogger.com/blog/post/edit/preview/...,这属于 *.blogger.com 的范围。这意味着我们找到漏洞了,对吗?

真相揭晓

别急,事情没那么简单。我们将代码改为 alert(document.domain),重新测试。这次弹窗显示的是 usersubdomain.blogspot.com,而不是预期的 blogger.com。为什么会这样?

使用浏览器的开发者工具查看页面源码,你会发现 blogger.com 通过一个 <iframe> 嵌入了 usersubdomain.blogspot.com,而我们的脚本实际上是在这个子域名中执行的。这解释了为何弹窗显示的不是 blogger.com。

为什么使用两个域名?

答案是:沙箱隔离。Google 故意将用户生成的内容(比如博客)放入独立的沙箱域名(如 usersubdomain.blogspot.com),以防止 XSS 攻击影响主域 blogger.com 或其他用户的数据。这种设计利用了浏览器的同源策略(Same-Origin Policy):脚本只能访问与其同源的资源。换句话说,我们的 XSS 虽然触发了,但被限制在沙箱中,无法触及 blogger.com 的 Cookie 或敏感信息。

参考资料:Google 在 Bug Hunter University 中详细说明了沙箱域的用途。


沙箱的奥秘

沙箱域的用途

Google 在其安全博客中提到,他们使用一系列沙箱域来隔离用户上传的内容(包括 HTML、JavaScript 或 Flash)。这些沙箱确保用户脚本无法访问其他用户的数据。例如,blogger.com 上的 Cookie 只能在主域下访问,而 usersubdomain.blogspot.com 的脚本无权染指。

核心目标:XSS 攻击的目的是窃取不该访问的数据(如 Cookie)。沙箱让这种企图化为泡影。

为何选择 alert(document.domain)?

回到我们的实验,使用 alert(document.domain) 或 alert(window.origin) 的最大价值在于,它们能明确告诉你脚本执行的域名。只有当脚本运行在目标域(如 blogger.com)而不是沙箱域时,你才可能发现真正的安全问题。否则,弹窗只是“虚假的胜利”。


更进一步:沙箱化的 <iframe>

除了域名级别的沙箱,<iframe> 也可以通过 sandbox 属性实现隔离。让我们通过另一个实验来验证。

实验:带 sandbox 属性的 <iframe>

假设我们搭建了一个简单工具,允许通过 eval() 执行 JavaScript 表达式。代码如下:

<iframe sandbox>
  <script>
    eval("alert(1)");
  </script>
</iframe>
  1. 输入 1+2,结果返回 3——功能正常。
  2. 输入 alert(1),弹窗显示“1”——XSS 似乎可行。
  3. 输入 alert(document.secret),试图获取隐藏的会话令牌,却失败了。
  4. 输入 alert(window.origin) 或 alert(document.domain),结果为空!

原因分析

在添加 sandbox 属性的 <iframe> 中,脚本被严格隔离,无法访问外部页面(如主域)的资源。这种隔离与 Blogger 的子域名沙箱有异曲同工之妙,但实现方式不同。无论是哪种沙箱,alert(document.domain) 都能帮你快速判断漏洞的可利用性。


控制台日志:更隐秘的线索

有时,沙箱化的 <iframe> 会禁用弹窗(例如未启用 allow-modals)。以 sites.google.com 为例,我们注入 alert(1) 后毫无反应。这时,打开开发者工具的控制台日志,你可能会看到类似“alert() 被沙箱阻止”的提示。

改进方法是用 console.log() 测试:

<script>console.log("XSSTEST");</script>

控制台显示“XSSTEST”,证明脚本执行了。但通过 alert(document.domain) 检查后,你会发现它仍在沙箱域中运行,无法构成有效威胁。


沙箱逃逸的可能性

虽然沙箱中的 XSS 通常不直接构成漏洞,但并非无懈可击。例如,如果网站通过 postMessage 与沙箱化的 <iframe> 通信,攻击者可能利用消息传递机制,将 XSS 有效载荷“逃逸”到主域执行。这种情况下的漏洞不在初始 XSS,而在于逃逸机制的设计缺陷。

提示:发现沙箱中的 XSS 时,别急着放弃。记下细节,检查通信方式,或许能挖出更大的宝藏!


总结与建议

通过本文的分析,我们得出以下结论:

  1. 简单并非万能:alert(1) 虽然直观,但无法提供上下文,容易误导。
  2. 定位为王:使用 alert(document.domain) 或 alert(window.origin),明确脚本执行位置,才能判断漏洞价值。
  3. 沙箱的价值:Google 等平台通过沙箱域和 <iframe> 隔离,有效防御 XSS,但也可能隐藏更复杂的攻击路径。

即使在沙箱中触发了 alert(1),也不要气馁。这可能是发现更大问题的起点。保持记录、深入挖掘,或许下一个漏洞赏金就属于你!

原文 https://blog.csdn.net/2301_79518550/article/details/146427418