托管在不同域上的 JavaScript 可以读取/修改另一个域的 DOM 吗?

Posted

技术标签:

【中文标题】托管在不同域上的 JavaScript 可以读取/修改另一个域的 DOM 吗?【英文标题】:Can a JavaScript hosted on different domain read/modify DOM of another domain? 【发布时间】:2015-02-08 19:29:33 【问题描述】:

我有一个关于托管在域(例如:CDN 的域,例如 example.com)但从不同域(例如 example.net)下的网站加载的 javascript 的潜在安全问题/限制的问题.

现在想象一下,加载的 JavaScript 只会读取/修改具有特定 ID 的 div 中的文本,所以没有什么“复杂”的。 一个例子:我从http://example.com/myscript.js加载了脚本,并在http://example.net/index.html上执行:[注意不同的TLD!]

<!-- Page example.net/index.html -->
<script src="http://example.com/myscript.js"></script>

我知道我无法从 JavaScript 访问 mysite.com 下的 Cookie,但我可以访问页面上的所有 DOM,以防万一,修改它。 这不是一个可能的安全问题吗?这不应该触发同源策略保护吗?

是否存在阻止托管在不同域中的 JavaScript 访问页面中执行脚本的元素的用户代理?

此外,上面的示例是否也适用于 HTTPS 页面? (例如:https://example.net/index.html 从https://example.com/myscript.js 加载脚本)

【问题讨论】:

【参考方案1】:

客户端 JavaScript 中所有基于 URL 的安全限制均基于包含加载 JS 的 &lt;script&gt; 元素的网页的 URL。

JS 本身所在的 URL 无关紧要。


现在,我知道我无法从 JS 访问 mysite.com 下的 Cookie。

脚本加载到example.net 并托管在example.com。它可以从example.net 读取cookie。它无法从 example.com 读取 cookie。 (example.com 上的服务器端代码可以动态生成 JavaScript 并嵌入从 cookie 中取出的数据)。


但是,我可以访问页面上的所有 DOM,并且,以防万一,修改它。

是的

这不是一个可能的安全问题吗?这不应该触发同源策略保护吗?

这是一个潜在的安全问题,但不应触发同源策略。

通过加载脚本,页面的作者信任托管脚本的站点。

不要从您不信任的网站嵌入 JS。


此外,上面的示例是否也适用于 HTTPS 页面? (例如:https://example.net/index.htmlhttps://example.com/myscript.js 加载脚本)

具有不同方案的 URL 具有不同的来源,就像具有不同主机名的 URL 一样。同源策略规则是相同的,因为它们是基于起源而不是起源的特定特征。

有时您会受到额外的限制,即禁止通过 HTTPS 加载的页面访问通过 HTTP 加载的内容,因为这会破坏 SSL 安全性。这是与同源策略无关的不同安全限制。

【讨论】:

是的,这正是CDN用于加载js文件的原因。 感谢您的详细解答。关于 cookie,如果我想从 example.com 设置一个“全局”cookie(通过 Set-Cookie 标头发送的响应包含 JS 脚本的 cookie),可以从所有从 example.com 加载脚本的站点读取该 cookie( CDN),我应该认为这是不可能的,对吧? 正确。请参阅答案中有关使用服务器端代码的注释。 但是,如果我根据 Http-Referer 标头设置 cookie 的域(解析它并仅提取主机名),我可以设置仅与加载javascript。这是处理由外部请求设置的 cookie 的正确方法,还是不应该在这种情况下使用 Http-Referer? @CarmineGiangregorio — 你不能那样做。 cookie 规则不允许您设置外部域。【参考方案2】:

这不是一个可能的安全问题吗?

是的,这叫Cross-Site-Scripting (XSS)。

这绝对是一个安全问题。

底线,从不包含来自任何域的您不信任的代码。故事结束。

如果攻击者可以让代码在您的域上运行,那么游戏就结束了。

这不应该触发同源策略保护吗?

没有。

same-origin-policy 基本上意味着脚本只能查看/修改它所加载到的域的 DOM。因此,您不能为任意站点创建 iframe 并从父站点读取该 DOM除非 CORS 已打开,或者您的脚本也在其中运行

也许,是否存在阻止托管在不同域上的 Javascript 访问页面中执行脚本的元素的用户代理?

做到这一点的唯一方法是将 javascript 沙箱化到 iframe 在不同的域中

因此您可以创建一个sandbox.example.com 域,该域会生成一个包含javascript 的包装页面。

然后,不要直接链接到 JS,而是创建一个指向沙箱域的 iframe。 JS 将可以访问该域以及该 DOM 中的所有内容,但 iframe 之外没有任何内容。

您仍然必须小心正确设置 cookie(不要使用通配符域等)。但它可以提供帮助。

【讨论】:

以上是关于托管在不同域上的 JavaScript 可以读取/修改另一个域的 DOM 吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 Hetzner 托管的附加域上安装 WordPress

允许子 iframe 从不同域调用其父窗口上的函数

通过多域托管防止直接访问主域上的网站

看我如何绕过某托管公司域上的强大XSS过滤器

告诉另一个域上的控制器有新数据

如果我创建了一个签名的 Java 小程序,我可以将它托管在我想要的任何域上吗?