给前端开发人员的 10 条安全提示
网络安全是前端开发人员经常忽视的一个话题。当我们评估网站质量时,我们通常会关注性能、SEO友好度和可访问性等指标,而网站抵御恶意攻击的能力却常常被忽视。尽管敏感的用户数据存储在服务器端,后端开发人员也必须采取重要措施来保护服务器,但最终,保护这些数据的责任是由后端和前端共同承担的。敏感数据可能安全地锁在后端仓库中,而前端却掌握着前门的钥匙,窃取这些数据往往是获取访问权限的最简单方法。
“保护用户数据的责任由后端和前端共同承担。”
恶意用户可以利用多种攻击媒介来入侵我们的前端应用程序,但幸运的是,只需正确配置几个响应头并遵循良好的开发实践,我们就能在很大程度上降低此类攻击的风险。在本文中,我们将介绍 10 个简单的方法,帮助您提升 Web 应用程序的安全性。
衡量结果
在开始改进网站安全性之前,务必收集一些关于改进效果的反馈。虽然量化“良好开发实践”的构成要素可能很困难,但安全标头的强度可以相当准确地衡量。就像我们使用 Lighthouse 获取性能、SEO 和可访问性评分一样,我们可以使用SecurityHeaders.com根据当前响应标头获取安全评分。对于评分不理想的情况,它还会提供一些建议,指导我们如何提高评分,从而增强安全性:
SecurityHeaders 能给我们的最高分数是“A+”,我们应该始终努力争取这个分数。
关于响应头的说明
处理响应标头过去是后端的任务,但如今我们经常将 Web 应用程序部署到Zeit或Netlify等“无服务器”云平台,配置它们以返回正确的响应标头就成了前端的责任。请务必了解您的云托管提供商如何处理响应标头,并进行相应的配置。
安全措施
1. 使用强大的内容安全策略
完善的内容安全策略 (CSP) 是前端应用安全的基石。CSP 是浏览器引入的一项标准,用于检测和缓解某些类型的代码注入攻击,包括跨站点脚本 (XSS) 和点击劫持。
强大的 CSP 可以禁用潜在有害的内联代码执行,并限制加载外部资源的域名。您可以通过将Content-Security-Policy
header 设置为以分号分隔的指令列表来启用 CSP。如果您的网站不需要访问任何外部资源,则 header 的良好初始值可能如下所示:
Content-Security-Policy: default-src 'none'; script-src 'self'; img-src 'self'; style-src 'self'; connect-src 'self';
这里我们将script-src
、img-src
、style-src
和connect-src
指令设置为 self ,分别指示所有脚本、图片、样式表和 fetch 调用都应限制在提供 HTML 文档的同一来源。任何其他未明确提及的 CSP 指令都将回退到default-src
指令指定的值。我们将其设置为 ,none
以指示默认行为是拒绝连接到任何 URL。
然而,如今几乎没有任何 Web 应用程序是自包含的,因此您可能需要调整此标头以允许您使用的其他受信任域,例如 Google Fonts 或 AWS S3 存储桶的域,但最好从最严格的策略开始,然后在需要时放宽它。
您可以在MDN 网站上找到 CSP 指令的完整列表。
2.启用XSS保护模式
如果确实从用户输入中注入了恶意代码,我们可以通过提供标头来指示浏览器阻止响应"X-XSS-Protection": "1; mode=block"
。
虽然大多数现代浏览器默认启用了 XSS 保护模式,并且我们也可以使用内容安全策略来禁用内联 JavaScript,但X-XSS-Protection
对于不支持 CSP 标头的旧版浏览器,仍然建议包含标头以确保更好的安全性。
3. 禁用 iframe 嵌入以防止点击劫持攻击
点击劫持是一种攻击,诱骗网站 A 上的用户在网站 B 上执行某些操作。为了实现此目的,恶意用户将网站 B 嵌入到不可见的 iframe 中,然后将其放置在网站 A 上毫无戒心的用户的光标下,因此当用户点击,或者更确切地说,认为他们点击了网站 A 上的元素时,他们实际上点击的是网站 B 上的某个内容。
X-Frame-Options
我们可以通过提供禁止在框架中呈现网站的标头来防止此类攻击:
"X-Frame-Options": "DENY"
或者,我们可以使用frame-ancestors
CSP 指令,它可以更精细地控制哪些父级可以或不可以将页面嵌入 iframe。
4. 限制对浏览器功能和 API 的访问
良好的安全实践之一是限制对网站正常运行所不需要的任何内容的访问。我们已经运用了这一原则,使用 CSP 来限制网站允许连接的域名数量,但它也可以应用于浏览器功能。我们可以通过Feature-Policy
标头指示浏览器拒绝访问应用程序不需要的某些功能和 API。
我们设置Feature-Policy
为一串以分号分隔的规则,其中每个规则是功能的名称,后跟其策略名称。
"Feature-Policy": "accelerometer 'none'; ambient-light-sensor 'none'; autoplay 'none'; camera 'none'; encrypted-media 'none'; fullscreen 'self'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; midi 'none'; payment 'none'; picture-in-picture 'none'; speaker 'none'; sync-xhr 'none'; usb 'none'; vr 'none';"
Smashing Magazine有一篇很棒的文章Feature-Policy
对此进行了详细的解释,但大多数时候你会想要设置none
所有你不使用的功能。
5. 不要泄露 referrer 值
当您点击离开您网站的链接时,目标网站会在referrer
标头中收到您网站最后一个位置的 URL。该 URL 可能包含敏感和半敏感数据(例如会话令牌和用户 ID),这些数据绝不能泄露。
为了防止值泄漏referrer
,我们将Referrer-Policy
标头设置为no-referrer
:
"Referrer-Policy": "no-referrer"
在大多数情况下,这个值应该是好的,但是如果您的应用程序逻辑要求您在某些情况下保留引荐来源,请查看Scott Helme 的这篇文章,其中他分解了所有可能的标头值以及何时应用它们。
6. 不要根据用户输入设置 innerHTML 值
跨站点脚本攻击(即将恶意代码注入网站)可以通过多种不同的 DOM API 进行,但最常用的是innerHTML
。
您绝不应该innerHTML
根据用户未经过滤的输入进行设置。任何可由用户直接操作的值(无论是输入字段中的文本、URL 中的参数还是本地存储条目)都应先进行转义和过滤。理想情况下,使用textContent
而不是 来innerHTML
完全避免生成 HTML 输出。如果您确实需要为用户提供富文本编辑功能,请使用成熟的库,这些库使用白名单(而不是黑名单)来指定允许的 HTML 标签。
不幸的是,innerHTML
这并非 DOM API 的唯一弱点,而且易受 XSS 注入攻击的代码仍然难以检测。因此,始终制定严格的内容安全策略以禁止内联代码执行至关重要。
展望未来,您可能需要关注新的可信类型规范,该规范旨在防止所有基于 DOM 的跨站点脚本攻击。
7.使用UI框架
React、Vue 和 Angular 等现代 UI 框架内置了良好的安全性,可以在很大程度上消除 XSS 攻击的风险。它们会自动编码 HTML 输出,减少使用易受 XSS 攻击的 DOM API 的需求,并为潜在的危险方法赋予明确且警示性的名称,例如dangerouslySetInnerHTML
。
8. 保持依赖项更新
快速浏览一下node_modules
文件夹内部,就能确认我们的 Web 应用程序是由数百个(甚至数千个)依赖项组成的乐高拼图。确保这些依赖项不包含任何已知的安全漏洞,对于网站的整体安全至关重要。
确保依赖项保持安全且最新状态的最佳方法是将漏洞检查纳入开发流程。为此,您可以集成Dependabot和Snyk等工具,它们会针对过期或可能存在漏洞的依赖项创建拉取请求,并帮助您更快地应用修复。
9. 添加第三方服务前请三思
像 Google Analytics、Intercom、Mixpanel 以及其他数百种第三方服务,只需一行代码即可满足您的业务需求。但与此同时,它们也可能使您的网站更容易受到攻击,因为如果第三方服务受到攻击,您的网站也会受到影响。
如果您决定集成第三方服务,请务必设置最强大的 CSP 策略,以确保该服务正常运行。大多数热门服务都已记录其所需的 CSP 指令,因此请务必遵循它们的指南。
使用 Google 跟踪代码管理器、Segment 或任何其他允许组织内任何人集成更多第三方服务的工具时,应格外小心。有权使用此工具的人员必须了解连接其他服务的安全隐患,并最好与其开发团队进行沟通。
10. 对第三方脚本使用子资源完整性
对于您使用的所有第三方脚本,请确保integrity
尽可能包含该属性。浏览器具有子资源完整性功能,可以验证您正在加载的脚本的加密哈希值,并确保其未被篡改。
您的script
标签可能如下所示:
<script src="https://example.com/example-framework.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/ux..."
crossorigin="anonymous"></script>
需要澄清的是,这项技术对第三方库很有用,但对第三方服务的作用较小。大多数情况下,当您为第三方服务添加脚本时,该脚本仅用于加载另一个依赖脚本。由于依赖脚本随时可能被修改,因此无法检查其完整性,因此在这种情况下,我们不得不依赖严格的内容安全策略。
结论
良好的浏览体验是任何现代 Web 应用程序的重要组成部分,用户希望确保其个人数据的安全和私密。虽然这些数据存储在后端,但保护这些数据的责任也延伸到了客户端应用程序。
恶意用户可以利用多种类型的 UI-first 攻击,但如果您遵循本文中的建议,则可以大大增加防御这些攻击的机会。
文章来源:https://dev.to/kosslebedev/10-security-tips-for-frontend-developers-4j8h