10 分钟内演示 CORS、XSS 和 CSRF
跨域资源共享 (CORS)
跨站脚本
CSRF
本文应该能帮你了解现有的网络安全标准、最常见的网络攻击以及防范方法。最后,你还会发现 Samy 是如何以及为何成为众人心目中的英雄的(我猜,除了鲁珀特·默多克)。
跨域资源共享 (CORS)
跨域资源共享 (CORS) 是IE10+、Chrome 4+、Firefox 3.5+ 或 2012 年后发布的几乎所有版本的浏览器(Opera Mini 除外)的安全功能。
当在域上可用的服务器上配置CORS 时website.com
,通过 AJAX 请求的来自该域的资源必须从同一域提供的资产启动。
换句话说,如果我们启用 CORSdomain-b.com
并将其配置为仅允许GET
来自 域名的请求,domain-b.com
那么如果您想https://domain-b.com/images/example.png
在托管于 的网站上使用 Canvas下的图片domain-a.com
,那么大多数访问者将无法加载该图片。
受 CORS 保护的资源在任何不遵循 的工具或浏览器请求时仍然可用CORS policy
。
CORS 配置
默认情况下, CORS 是禁用的,这意味着没有足够的服务器处理程序来配置 CORS,也就意味着您无法在 XHR 中访问来自不同来源的资源。基本上,如果您不执行任何操作或仅为特定域启用 CORS,那么任何尝试访问您的资源的 AJAX 请求都将被拒绝,因为 Web 浏览器尊重CORS policy
。这就是为什么在开始使用 VueJS 和 NodeJS 开发 SPA 时会遇到CORS 问题的
原因。您的 VueJS 应用程序托管在 上,当您尝试访问 上的 NodeJS 服务器应用程序时,您会得到“ ”,因为这是两个不同的( 、和 的组合)。http://localhost:8080
http://localhost:8000
No Access-Control-Allow-Origin header is present
ORIGINS
PROTOCOL
HOST
PORT
解决 VueJS 开发模式中的 CORS 问题的方法是vue.config.js
按如下方式在文件中设置 devServer 代理:
module.exports = {
...
devServer: {
proxy: 'http://localhost:8000',
},
...
}
要在生产环境中设置 CORS,您需要为请求添加适当的监听器OPTIONS
。该监听器应该发送响应200
,no body
但Headers
响应中定义了您想要的CORS 策略:
Access-Control-Allow-Origin: https://domain-b.com
Access-Control-Allow-Methods: GET
有关如何配置 CORS 的更多信息,请查看https://enable-cors.org/index.html,并深入CORS policy
了解https://livebook.manning.com/book/cors-in-action/part-1/
跨站脚本
XSS 代表跨站脚本攻击,是一种注入式攻击。它在 OWASP 2017 年发现的十大漏洞中排名第七。跨站脚本攻击是指攻击者将恶意脚本注入受信任网站的方法。(感谢 Sandor,此部分已更新)此类攻击有三种类型。
- 存储型 XSS - 漏洞来自未受保护且未经过清理的用户输入,这些输入直接存储在数据库中并显示给其他用户
- 反射型 XSS - 漏洞源自网页中直接使用的 URL 中未受保护且未经清理的值
- 基于 DOM 的 XSS - 与反射型 XSS 类似,直接在网页中使用的 URL 值不受保护且未经清理,不同之处在于基于 DOM 的 XSS 甚至不会进入服务器端
攻击
1.存储型XSS
以下是一个攻击示例。攻击者进入您的网站,找到未受保护的输入字段(例如评论字段或用户名字段),并输入恶意脚本而不是预期值。之后,每当该值应该显示给其他用户时,它就会执行恶意代码。恶意脚本可能会尝试访问您在其他网站上的帐户,并可能参与 DDoS 攻击或类似攻击。可视化表示(来源 geeksforgeeks.org):
2.反射型XSS
反射型XSS是当攻击者发现页面存在此类漏洞时发生的攻击,例如:
预期 URL:https://mywebpage.com/search?q=javascript
恶意 URL:https://mywebpage.com/search?q=<script>alert('fortunately, this will not work!')</script>
<body>
...
<div> showing results for keyword
<script> document.write(window.location.href.substr(window.location.href.indexOf('q=') + 2))
</script>
</div>
...
...JavaScript results...
...
</body>
发现后,攻击者会诱骗用户点击此类恶意 URL,然后用户敏感数据就被利用了。
geekforgeeks.com 提供的示例中说明了攻击的生命周期:
3.基于DOM的XSS
这种攻击与反射攻击类似,但不同之处在于恶意URL
部分根本不会发送到服务器。例如:
预期 URL:https://mywebpage.com/search?q=javascript
恶意 URL(反射型 XSS):https://mywebpage.com/search?q=<script>alert('fortunately, this will not work!')</script>
恶意 URL(基于 DOM 的 XSS):https://mywebpage.com/search#q=<script>alert('fortunately, this will not work!')</script>
#
区别在于使用的字符?
。浏览器不会将 URL 中 # 之后的部分发送到服务器,因此它们会将其直接传递给客户端代码。
保护
用户输入的每个值,无论是在服务器端还是客户端,在你的应用中使用时,都应被视为不可信数据,因此在使用前应进行处理!你也应该在服务器应用和客户端应用中进行安全检查!
正如文档所示, VueJS 会在从变量获取值之前自行转义字符串。较新版本的 Angular 也会隐式转义字符串,因此如果你使用的是 Vanilla JS、JQuery 或类似的语言,则应该手动实现字符串转义。
下面列出了处理不受信任数据最常见的三种方法,理想的方法取决于您需要处理的字段的实际类型。
1. 字符串验证
验证是一种用户定义规则集的方法,要求不可信数据在继续操作之前满足这些规则。此方法适用于数值、用户名、邮箱、密码以及类似字段,这些字段具有具体的语法规则。
在考虑自己编写验证器之前,请检查框架中是否存在现有库。
2. 字符串转义
Escape 方法在需要允许用户使用标点符号的情况下非常有用。此方法会遍历字符串并查找特殊字符,例如 ,<
>
并将其替换为合适的 HTML 字符实体名称。以下是您可以使用的基本函数:
function escapeText(text) {
return text.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
}
再次强调,在编写自己的库之前,请检查是否存在现有的库。
3. 字符串清理
当用户被允许在评论、文章或类似内容中输入某些 HTML 标签时,会使用清理字符串。清理方法会遍历文本,查找您指定的 HTML 标签并将其删除。Google Closure是使用这种方法的最流行的库之一。
这种方法资源消耗大且被认为有害,因此在选择之前请做好充分的调查。
Web 浏览器(从哪个版本开始都没有可用来源,IE 在 2014 年修复了这个问题)会在将 URL 发送到服务器端并使其在window.location
对象中可用之前自动对其进行转义,因此这里介绍第二种和第三种类型的攻击只是为了了解它们并明确指出 URL 参数也应被视为不受信任的数据。
有关 XSS 的更多详细信息以及在轮换大量不受信任的数据时如何正确保护您的应用程序,请查看OWASP 关于 XSS 预防的备忘单。
CSRF
跨站请求伪造 (CSRF) 是一种攻击类型,指的是恶意网站、电子邮件、博客、即时消息或程序导致用户的 Web 浏览器在用户已通过身份验证的其他受信任站点上执行不必要的操作。当浏览器在每次请求中自动发送授权资源(例如会话 Cookie、IP 地址或类似信息)时,可能会出现此漏洞。
攻击
假设用户登录到您未受保护的股票交易所 Web 应用程序,并且您使用会话 Cookie 或 JWT Cookie 进行身份验证。攻击者也使用您的服务,并能够检查您的 API 的运行情况。攻击者诱骗用户执行脚本(通过点击邮件中的垃圾邮件链接或类似链接),该脚本会向您的 API 发送请求https://www.stockexchange.com/users/withdraw?how_much=all&address=MY_ADDRESS
(API 设计很糟糕,别问)。由于请求是从浏览器执行的,浏览器会在每个请求中发送身份验证负载,因此您的股票交易所 Web 服务器将成功验证用户身份并执行交易,受骗用户将在毫无察觉的情况下损失所有余额,因为这一切都发生在后台。可视化演示(来源:miro.medium.com)
保护
幸运的是,有一些易于实施的模式可以防止此类 Web 攻击。最常见的模式之一是使用CSRF token
。基本流程如下:
- 为每个用户的请求生成唯一的token,即所谓的
CSRF token
。 - 将其安全地存储在服务器上并将其作为响应的有效负载发送回用户。
- 存储
CSRF token
在客户端。 - 当用户尝试执行任何状态改变*请求时,将该
CSRF token
请求作为有效负载发送。 - 在服务器端执行该请求之前,请检查该请求是否
CSRF token
存在以及是否有效。
这是所有用户防止 CSRF 攻击的最简单的方法。
如果您只与使用现代浏览器的访问者打交道,那么您可以依赖SameSite
会话 cookie 的属性。(感谢 Gergely)
由于服务器的响应可以在 XHR 响应中处理,因此如果您的 Web 应用程序存在 XSS 漏洞,那么就无法防御 CSRF 攻击!
要深入了解,请查看OWASP 关于 CSRF 的备忘单。
奖金
关于 Samy 的简短纪录片,Samy 是 2005 年利用 XSS 漏洞攻击 MySpace 的蠕虫病毒作者,绕过了 MySpace 的 CSRF 防御。https
://youtu.be/DtnuaHl378M
有关 Samy 蠕虫的更多信息
https://samy.pl/myspace/tech.html