我正在开发的项目中,每个页面链接都使用 AJAX 调用,更具体地说,是 jQuery AJAX 调用。此外,除了登录以外,每个提交的表单也都是通过 AJAX 提交的,并且其中还包含一些 json 和 xml。我的问题是,这样做存在什么安全风险?所有服务器端代码都是 PHP 编写的,并且已经适当转义。
我正在开发的项目中,每个页面链接都使用 AJAX 调用,更具体地说,是 jQuery AJAX 调用。此外,除了登录以外,每个提交的表单也都是通过 AJAX 提交的,并且其中还包含一些 json 和 xml。我的问题是,这样做存在什么安全风险?所有服务器端代码都是 PHP 编写的,并且已经适当转义。
AJAX中没有特定的内容。它只是您的浏览器执行的请求。它只是一般的HTTP请求,应该像其他任何HTTP请求一样得到保护,无论其XHR性质如何。
被广泛认为,对于只通过GET方式公开数据并通过cookies授权用户的服务,使用XSRF令牌进行保护是不必要的。
但这并不是真的。当输出为JSON数组时,这些服务曾经存在AJAX特定的XSSI漏洞。
考虑一个名为/getfriends
的服务,它返回像[ { "name": "Alice" }, { "name": "Bob" } ]
这样的数据。
攻击页面可以执行以下操作:
<script>
var stolenData;
var RealArray = Array;
Array = function () {
return stolenData = new RealArray();
};
</script>
<script src="https://naivedomain.com/getfriends" type="text/javascript"></script>
第二个 <script>
标签通过用户的 cookies 跨域加载了 JSON 数据,由于 EcmaScript 3 中的一个怪异之处(在 EcmaScript 5.0 和现代 ES 3 解释器中已经修复),页面可以读取被盗数据,因为 JavaScript 解析器在解析 JSON 响应中的 [...]
时调用了被覆盖的 Array
构造函数。
通过 XSRF 令牌保护这些服务以及使用常规基于 cookie 的方法解决了该问题,禁止 GET,通过自定义头授权并包含解析断点也可以解决。解析断点的作用是使响应无效的 JSON,例如返回 throw 0; [{ "name": "Alice" }, { "name": "Bob" }]
,这样 XHR 客户端就可以去掉前缀 throw 0;
,但通过 <script>
加载的客户端则无法去除。
最后,由于 JavaScript 解析器将加载的脚本解析为程序,因此只影响返回 JSON 数组的服务。返回 { "names": ["Alice", "Bob"] }
的 /getfriend
服务不会有漏洞,因为该内容不是有效的程序,而是解析为带有无效标签的块。但是像 { names: [ "Alice", "Bob" ] }
这样的无效 JSON 是有漏洞的,因为它是有效的程序。
new Array()
创建新对象的结果”,但在EcmaScript 5中更改为“让数组成为通过表达式new Array()
创建新对象的结果,其中'Array'是具有该名称的标准内置构造函数。” - Mike Samueldo ... while(1);
,所以也许可以用 response.replace(/^while \(1\);/, "")
。 - Mike Samuel