我的同事声称 XSS 是服务器端的一个漏洞。我一直认为这是一个客户端漏洞。我们谁是正确的,为什么?
XSS 是服务器端还是客户端漏洞?
在跨站点脚本攻击中,恶意脚本在客户端运行,但实际漏洞在应用程序中。这并不一定意味着它是一个严格的服务器端漏洞,因为该漏洞可能存在于应用程序的 JavaScript 中,但通常,它确实存在于服务器端代码中,并且始终存在于服务器交付的代码中。
有客户端缓解措施,例如现在主流浏览器中内置的 XSS-Protection,或者阻止 JavaScript 执行的插件,但最终 XSS 是一个 Web 应用程序漏洞,需要由应用程序开发人员修复。
我应该提到还有另一种形式的 XSS,它既不利用客户端(浏览器)中的缺陷,也不利用服务器(应用程序)中的缺陷,而是利用用户中的缺陷。这通常被称为 Self-XSS,它利用了无能的用户执行他从 Internet 复制并粘贴到浏览器的开发者工具控制台中的 JavaScript 的意愿,完全基于对所有希望的承诺,它会神奇地允许尽管事实上她已经取消了他的好友并阻止了他,但他还是阅读了他前女友的 Facebook 帖子。
它在客户端表现出来,但这是因为 Web 应用程序允许这样做。应用程序不会验证它发送回浏览器的代码。这就是为什么它是服务器端漏洞。这样想吧。你会如何解决 XSS 的问题?修复服务器端代码还是修复浏览器?
跨站点脚本 (XSS)攻击通常可以归类为以下类型之一:
- 存储型 XSS 攻击
- 反射型 XSS 攻击
- 基于 DOM 的 XSS 攻击
攻击本身发生在客户端上。在单个页面或离线应用程序的情况下,所有三种攻击类型都可以在浏览器本身中充分体现出来。但是,如果数据存储在服务器上或从服务器反映,则服务器正在协助漏洞。
IE8 引入了X-XSS-Protection,这使得反射攻击更难被利用。
tl/dr:如果服务器正在构建 HTML,那么服务器需要防止 XSS。如果客户端正在构建 HTML,则客户端需要防范 XSS。
随着 Web 应用程序构建方式的变化,这个问题值得重新审视,因为答案不仅仅是语义问题。答案实际上非常简单:
XSS 发生在任何构建 HTML 的地方!
在问这个问题时,AngularJS 和 React 大约 3 岁和 1 岁(分别)。这是值得注意的,因为这些框架确实有助于加速向客户端应用程序的切换,其中 HTML 不仅呈现客户端(一如既往),而且还构建客户端。使用客户端应用程序,XSS 从服务器端漏洞切换到客户端漏洞。区别很重要:
防御 XSS
通常,您可以通过转义适当的控制字符来防止 XSS,具体取决于您的上下文。因此,如果您正在构建这样的 HTML:
<div title="[USER_INPUT]">Hi!</div>
您将转换"
为"
(除其他外)。如果您的服务器端应用程序正在向浏览器返回一个 HTML 字符串,那么显然它必须在生成 HTML 时处理这个问题。在许多现代后端框架中,这在模板系统中自动发生。
但是,如果您的服务器只是将数据(可能通过 JSON 响应)返回到运行 React 或 Angular 之类的客户端应用程序,那么它根本不应该做任何事情!原因是客户端应用程序将构建 HTML,因此它将执行任何必要的 XSS 保护。如果服务器首先对 HTML 进行转义,那么它将以双重转义结束,这意味着不会看到以下内容:
Welcome to Bob's Page!
用户将看到:
Welcome to Bob"s Page!
因为整个系统都会经过这个流程:
- 从数据库:
"
- 由服务器转义并发送给客户端:
"
- 由客户端应用程序转义并在浏览器中呈现:
&quot;
这显然会导致问题。此外,重要的是要记住正确保护 XSS 的步骤是依赖于上下文的。停止 XSS 在 HTML 属性中是不同的,与直接注入到 DOM 树中的输入相比,与注入到 JavaScript 字符串中的数据不同。因此,当用户输入实际注入 HTML 时,必须进行 XSS 保护。因此,它可能是服务器端问题或客户端问题,这取决于谁在进行实际的 HTML 构建。