11

这很奇怪,我想知道是否有人可以解释为什么会这样。

基本上,我一直在努力测试 JSONP,这样我就可以实现其他网站可以使用的 JSON Web 服务。我正在本地主机上进行开发——特别是 Visual Studio 2008 和 Visual Studio 2008 的内置 Web 服务器。

因此,作为带有 jQ​​uery 的 JSONP 测试运行,我实现了以下内容:

$().ready(function() {
  debugger;
  try {
    $.getJSON("<%= new Uri(Request.Url, "/").ToString() %>XssTest?callback=?", function(data) {
        alert(data.abc);
    });
  } catch (err) {
    alert(err);
  }
});

在服务器上..

<%= Request["callback"] %>({abc : 'def'})

所以最终发生的是我在服务器上设置了一个断点,并且我在第一个“调试器”上都获得了断点;客户端脚本以及服务器上的语句。JSONP URL 确实在页面加载后被调用。这很好用。

我遇到的问题是回调永远不会执行。我在 IE8 和 Firefox 3.5 中都对此进行了测试。没有人会调用回调。也从未达到 catch(err)。什么都没发生!

我已经坚持了一周,甚至在指定端口上的 Telnet 中使用手动键入的 HTTP 请求进行了测试,以确保服务器正在返回格式......

callbackfn({abc : 'def'})

..它是。

然后我突然想到,如果我使用全球化器('.')将主机名从 localhost 更改为 localhost,例如http://localhost.:41559/而不是http://localhost:41559/(是的,添加一个点到任何主机名都是合法的,它是 DNS 什么global::是 C# 命名空间)。然后它起作用了!当我刚刚添加一个点时,Internet Explorer 和 Firefox 3.5 终于向我显示了一条警告消息。

所以这让我想知道,这里发生了什么?为什么后期脚本标记生成可以使用 Internet 主机名而不是普通 localhost?或者这是正确的问题?

显然,这是出于安全原因而实施的,但他们试图保护什么?而且,通过让它与点一起工作,我是否只是在此安全功能中暴露了一个安全漏洞?

顺便说一句,我的 hosts 文件虽然针对其他主机进行了更改,但与 localhost 没有什么特别之处;默认的 127.0.0.1 / ::1 仍然存在,下面没有覆盖。

跟进:出于本地开发目的,我通过添加:

127.0.0.1   local.mysite.com

.. 到我的 hosts 文件中,然后将以下代码添加到我的 global.asax 中:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    if (Request.Headers["Host"].Split(':')[0] == "localhost")
    {
        Response.Redirect(
            Request.Url.Scheme
            + "://"
            + "local.mysite.com"
            + ":" + Request.Url.Port.ToString()
            + Request.Url.PathAndQuery
            , true);
    }
}
4

2 回答 2

3

我将在那里抛出一个答案;经过一番思考,我得出了自己的结论。

这可能是一个安全功能,它被实施以试图阻止 Internet 网站调用运行在客户端计算机上的 JSONP 服务。

一个网站可以只浏览一个端口列表,并在不同的端口和路径上不断调用 localhost。“Localhost”是少数 DNS 主机名之一,其含义取决于查询的时间和地点,从而使潜在目标易受攻击。是的,将点 (.) 附加到“localhost”(“localhost.”)会产生一种可行的解决方法,这确实暴露了一个安全漏洞,但确实为开发目的提供了一个 [暂定的] 解决方法。

更好的方法是将环回 IP 映射到 hosts 文件中的新主机名条目,以便它在本地工作,不容易被浏览器更新“修复”,并且除了在开发工作站上之外不能在其他任何地方工作.

于 2009-08-02T02:09:42.293 回答
1

我遇到了类似的问题。我尝试过的大多数解决方案都适用于 IE (7),但我很难让 Firefox (3.5.2) 发挥作用。

我已经安装了 HttpFox 以查看我的服务器响应在客户端上是如何被解释的,并且我得到了 NS_ERROR_DOM_BAD_URI。不过,我的情况与您的情况有些不同,因为我正在尝试调用 JSONP 调用返回托管页面来自的同一站点,然后此调用响应 302 重定向到另一个站点。(我使用重定向作为一种方便的方式从两个域中获取 cookie 返回到浏览器。)

我正在使用 jQuery,我最初尝试通过 $.ajax() 进行标准 AJAX 调用。我想,由于初始请求是针对与托管页面相同的站点,Firefox 只会跟随对另一个域的 302 响应。但不,它似乎违反了 XSS 防御。(请注意,与返回重定向作为对 XHR 请求的响应相反暗示,jQuery 确实遵循标准 dataType="json" 调用的 302 重定向:重定向到同一域工作正常;重定向到另一个域会在浏览器中生成 NS_ERROR_DOM_BAD_URI。)顺便说一句,我不明白为什么不能仅仅遵循同域 302 重定向到其他域 - 毕竟,发出重定向的是托管页面的域,那为什么不能信任呢?如果您担心脚本注入攻击,那么 JSONP 路由无论如何都可以被滥用...

jQuery 的 $.getJSON() 带有 ?callback=? 后缀在 Firefox 中也失败并出现同样的错误。就像使用 $.getScript() 来滚动我自己的 JSONP <script> 标签一样。

似乎有效的是,在 HTML 中有一个预先存在的 <script id="jsonp" type="text/javascript"></script> 然后使用 $("jsonp").attr("src", url + "?callback=myCallback") 调用 JSONP 调用。如果我这样做了,那么跨域 302 重定向将被执行,并且我的 JSON 响应被传递给 myCallback(我已与 <script/> 标签同时定义)。

而且,是的,我正在使用 Cassini 和 localhost:端口URL 来开发所有这些。Cassini 不会响应非本地主机的 URL,所以我不能轻易地尝试 local.mysite.com 看看这是否对我上面尝试的解决方案有任何影响。但是,在 localhost 末尾添加一个点似乎解决了我所有的问题!

现在我可以使用 localhost__.__: port而不是 localhost: port回到标准的 $.ajax({ ... dataType:"jsonp" ... }) 调用,一切都很好。我觉得有趣的是,修改页面 HTML 中预先存在的脚本标记的 src 属性确实允许调用普通的本地主机 URL - 我想按照您的思考过程,这可能是另一个安全漏洞。

于 2009-08-12T09:50:41.640 回答