考虑一下,在检查您的GMail帐户后,您将访问我的恶意页面:
现在会发生的是,来自谷歌的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发布的那个.
即使没有
for(;;);
攻击者如何获取数据?
攻击是基于改变内建类型,特别的行为Object
,并Array
通过改变它们的构造函数或其prototype
.然后,当目标JSON使用{...}
或[...]
构造时,它们将成为攻击者自己的那些对象的版本,具有潜在的意外行为.
例如,你可以破解一个setter-property Object
,它会背叛用对象文字写的值:
Object.prototype.__defineSetter__('x', function(x) { alert('Ha! I steal '+x); });
然后,当指向某个使用该属性名称的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的扩展可能会在未来导致类似类型的更多潜在泄漏,在这种情况下,箔条也应该防止这些泄漏.
考虑一下,在检查您的GMail帐户后,您将访问我的恶意页面:
现在会发生的是,来自谷歌的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发布的那个.
编辑
这些字符串通常被称为"不可解析的cruft",它们用于修补影响JSON规范的信息泄漏漏洞.这次攻击是现实世界,Jeremiah Grossman发现了gmail中的漏洞.Mozilla还认为这是JSON规范中的漏洞,并且已在Firefox 3中进行了修补.但是因为这个问题仍然影响其他浏览器,所以这是"不可解析的",因为它是一个兼容的补丁.
Bobice的答案对此次攻击有技术性解释,这是正确的.
如果它无效,它们如何解析它,如果你试图评估它会崩溃?
它是一个功能,如果你尝试它会崩溃eval
. eval
允许任意JavaScript代码,可用于跨站点脚本攻击.
他们只是从字符串中删除它(看起来很贵)?
我想是这样的.可能是这样的:
function parseJson(json) { json = json.replace("throw 1;", ""); if (/* regex to validate the JSON */) { return eval(json); } else { throw "XSS"; } }
"不要做坏事"会阻止开发人员eval
直接使用而不是更安全的替代方案.